ndt-users - Re: NDT 3.6.5 on a 3.2.x kernel
Subject: ndt-users list created
List archive
- From: "Daniel A. Ramaley" <>
- To:
- Subject: Re: NDT 3.6.5 on a 3.2.x kernel
- Date: Mon, 8 Apr 2013 12:55:20 -0500
- Authentication-results: sfpop-ironport01.merit.edu; dkim=neutral (message not signed) header.i=none
- Organization: Drake University
On 2013-04-08 at 12:13:00, Dominic Hamon wrote:
>NDTConstants.java should contain that variable.
That's good to know. It doesn't contain that variable though. There is
only 1 file that contains that variable, and that is the file that is
showing the error when i run make:
$ find . -type f -exec grep -l RFC_2018_Enabled {} +
./Applet/Tcpbw100.java
I do see that the NDTConstants.java contains a similarly-named variable
though: RFC_2018_ENABLED. Assuming that there was a simple typo in the
patch, i've corrected it and attached an updated copy of the patch. With
that change made i was able to get it to compile cleanly! I'll keep
working on it and see if i can get NDT fully working.
Thanks for all the help.
__
Daniel A. Ramaley
Network Engineer 2
Dial Center 112, Drake University
2407 Carpenter Ave / Des Moines IA 50311 USA
Tel: +1 515 271-4540
Fax: +1 515 271-1938
E-mail:
diff --git a/Applet/NDTConstants.java b/Applet/NDTConstants.java index 6fb1c1c..7293b74 100644 --- a/Applet/NDTConstants.java +++ b/Applet/NDTConstants.java @@ -99,7 +99,24 @@ public class NDTConstants { // Section: RFC 1323 options ( Seems like 0/1/2/3 are the options available) - public static final int RFC_1323_DISABLED = 0; + // Not sure 0 is available maybe really old web100? + + public static final int RFC_1323_ENABLED = 1; + // Note Self disabled from servers standpoint i.e. disabled by server + public static final int RFC_1323_SELF_DISABLED = 2; + public static final int RFC_1323_PEER_DISABLED = 3; + + // Section: RFC2018 SAck + public static final int RFC_2018_ENABLED = 1; + + // Section: RFC2018 Nagle + public static final int RFC_896_ENABLED = 1; + + // Section: RFC3168 + public static final int RFC_3168_ENABLED = 1; + // Note Self disabled from servers standpoint i.e. disabled by server + public static final int RFC_3168_SELF_DISABLED = 2; + public static final int RFC_3168_PEER_DISABLED = 3; // Section: Buffer limitation test thresholds public static final float BUFFER_LIMITED = 0.15f; //unused right now diff --git a/Applet/Tcpbw100.java b/Applet/Tcpbw100.java index 54fbd25..93105a5 100644 --- a/Applet/Tcpbw100.java +++ b/Applet/Tcpbw100.java @@ -2746,7 +2746,12 @@ public class Tcpbw100 extends JApplet implements ActionListener { _sEmailText += sSysvar + " " + sStrval + "\n%0A"; if (sStrval.indexOf(".") == -1) { // no decimal point, hence // integer - iSysval = Integer.parseInt(sStrval); + try { + iSysval = Integer.parseInt(sStrval); + } catch (Exception e) { + System.out.println("Exception occured reading a tcp stat var - " + e); + iSysval = -1; + } // save value into a key value expected by us save_int_values(sSysvar, iSysval); } else { // if not integer, save as double @@ -3373,35 +3378,35 @@ public class Tcpbw100 extends JApplet implements ActionListener { _txtStatistics.append("\n" + _resBundDisplayMsgs.getString("web100tcpOpts") + " \n"); _txtStatistics.append("RFC 2018 Selective Acknowledgment: "); - if (_iSACKEnabled == iZero) - _txtStatistics.append(_resBundDisplayMsgs.getString("off") + if (_iSACKEnabled == NDTConstants.RFC_2018_ENABLED) + _txtStatistics.append(_resBundDisplayMsgs.getString("on") + "\n"); else - _txtStatistics.append(_resBundDisplayMsgs.getString("on") + _txtStatistics.append(_resBundDisplayMsgs.getString("off") + "\n"); _txtStatistics.append("RFC 896 Nagle Algorithm: "); - if (_iNagleEnabled == iZero) - _txtStatistics.append(_resBundDisplayMsgs.getString("off") + if (_iNagleEnabled == NDTConstants.RFC_896_ENABLED) + _txtStatistics.append(_resBundDisplayMsgs.getString("on") + "\n"); else - _txtStatistics.append(_resBundDisplayMsgs.getString("on") + _txtStatistics.append(_resBundDisplayMsgs.getString("off") + "\n"); _txtStatistics.append("RFC 3168 Explicit Congestion Notification: "); - if (_iECNEnabled == iZero) - _txtStatistics.append(_resBundDisplayMsgs.getString("off") + if (_iECNEnabled == NDTConstants.RFC_3168_ENABLED) + _txtStatistics.append(_resBundDisplayMsgs.getString("on") + "\n"); else - _txtStatistics.append(_resBundDisplayMsgs.getString("on") + _txtStatistics.append(_resBundDisplayMsgs.getString("off") + "\n"); _txtStatistics.append("RFC 1323 Time Stamping: "); - if (_iTimestampsEnabled == NDTConstants.RFC_1323_DISABLED) - _txtStatistics.append(_resBundDisplayMsgs.getString("off") + if (_iTimestampsEnabled == NDTConstants.RFC_1323_ENABLED) + _txtStatistics.append(_resBundDisplayMsgs.getString("on") + "\n"); else - _txtStatistics.append(_resBundDisplayMsgs.getString("on") + _txtStatistics.append(_resBundDisplayMsgs.getString("off") + "\n"); _txtStatistics.append("RFC 1323 Window Scaling: "); @@ -3592,12 +3597,20 @@ public class Tcpbw100 extends JApplet implements ActionListener { // get client side IP String sClientSideClientIp = tokens.nextToken(); - k = sClientSideServerIp.indexOf("/"); + System.out.println("IP --" + sClientSideClientIp); + k = sClientSideClientIp.indexOf("/"); + System.out.println("k is: " + k); + sClientSideClientIp = sClientSideClientIp.substring(k + 1); + System.out.println("IP --" + sClientSideClientIp); + sClientSideServerIp = sClientSideServerIp.substring(k + 1); // MSS = 1456 = Ethernet MTU = 1500 - 24 -20 (bytes of IP header) = // 1456, thus preserved - + + if (_iTimestampsEnabled == NDTConstants.RFC_1323_ENABLED) + iMss += 12; + if (iMss == NDTConstants.ETHERNET_MTU_SIZE) _txtStatistics.append(_resBundDisplayMsgs .getString("packetSizePreserved") + "\n"); diff --git a/Applet/Tcpbw100_msgs_en_US.properties b/Applet/Tcpbw100_msgs_en_US.properties index 21e64b0..6d852f3 100644 --- a/Applet/Tcpbw100_msgs_en_US.properties +++ b/Applet/Tcpbw100_msgs_en_US.properties @@ -32,7 +32,7 @@ clientDataReports = Client Data reports link is clientInfo = Client System Details clientIpModified = Information: Network Address Translation (NAT) box is modifying the Client's IP address clientIpNotFound = Client IP address not found. For IE users, modify the Java parameters\n click Tools - Internet Options - Security - Custom Level, scroll down to\n Microsoft VM - Java permissions and click Custom, click Java Custom Settings\n Edit Permissions - Access to all Network Addresses, click Eanble and save changes -clientIpPreserved = Server IP addresses are preserved End-to-End +clientIpPreserved = Client IP addresses are preserved End-to-End clientSays = but Client says close = Close comments = Comments diff --git a/WEB10G_README b/WEB10G_README new file mode 100644 index 0000000..a6bcb41 --- /dev/null +++ b/WEB10G_README @@ -0,0 +1,19 @@ +Quick Build Notes +Although you don't need a web10g kernel to build, if you wish to run the server you will. + +I've tested with linux 3.5.1 kernel patched with web10g (web10.org - Web10G-0.4-3.5-patch). I had to modify the patch - Swap ktime_to_ns(...) with ktime_to_us(...). + +You need to make and install the Web10G-userland library I used Web10G-userland-2.0.4. + +Configure and build ndt as normal. Web10G libs should be detected and hence the web10gsrv built. Web100 is still fully supported and if Web100 libs are found web100srv will be built. + +Known issues + +Web10G related +* Logging functionality not yet implemented some related functions are missing. +* Web10g patch not quite right - need to modify ktime_to_ns to ktime_to_us. +* Server and Client(C and Java Applet) have been ported, other tools have not. Depending on their function they may not work. + +Other +* Running the server without a DNS server can cause tests to timeout and fail. Add the NI_NUMERICHOST flag into the getnameinfo call within _I2AddrSetNodePort() in the I2Util library to fix. +* MSS incorrectly detecting modification when testing via IPv6?? diff --git a/configure.ac b/configure.ac index c4f6542..9074dd4 100644 --- a/configure.ac +++ b/configure.ac @@ -145,6 +145,18 @@ AC_CHECK_LIB([web100], [web100_snap], INCLUDED_WEB100LIB="" AM_CONDITIONAL(HAVE_WEB100, false) ]) +AC_CHECK_LIB([tcpe], [tcpe_client_init], + [ + LINKED_TCPELIB="-ltcpe" + INCLUDED_TCPELIB="-I/usr/local/include/tcpe" + AC_DEFINE(HAVE_LIBTCPE, 1, [Define to 1 if you have the 'Web10G' library (-ltcpe).]) + AM_CONDITIONAL(HAVE_TCPE, true) + ], + [ + LINKED_TCPELIB="" + INCLUDED_TCPELIB="" + AM_CONDITIONAL(HAVE_TCPE, false) + ]) AC_CHECK_LIB([pcap], [pcap_open_live], [ @@ -197,14 +209,16 @@ AC_CHECK_LIB([odbc], [SQLDriverConnect], ]) -NDTINCDIR='$(INCLUDED_WEB100LIB) $(INCLUDED_PCAPLIB)' +NDTINCDIR='$(INCLUDED_WEB100LIB) $(INCLUDED_PCAPLIB) $(INCLUDED_TCPELIB)' NDTLIBDIR=/usr/local/lib NDTLDFLAGS='-L$(NDTLIBDIR) -Wl,-rpath,$(NDTLIBDIR)' -NDTLIBS='$(LINKED_WEB100LIB) $(LINKED_PCAPLIB) $(LINKED_ODBCLIB) -lm' +NDTLIBS='$(LINKED_WEB100LIB) $(LINKED_PCAPLIB) $(LINKED_ODBCLIB) $(LINKED_TCPELIB) -lm' NDTINCS='-I$(NDTINCDIR)' AC_SUBST(LINKED_WEB100LIB) AC_SUBST(INCLUDED_WEB100LIB) +AC_SUBST(LINKED_TCPELIB) +AC_SUBST(INCLUDED_TCPELIB) AC_SUBST(LINKED_PCAPLIB) AC_SUBST(INCLUDED_PCAPLIB) AC_SUBST(LINKED_ODBCLIB) @@ -275,6 +289,12 @@ echo "***********************************" echo "" echo "" +if test -z "$HAVE_TCPE_TRUE" && test -n "$HAVE_TCPE_FALSE"; then + SUMMARY_WEB10GSRV="YES" +else + SUMMARY_WEB10GSRV="NO (missing tcpe (web10g) library)" +fi + SUMMARY_WEB100CLT="YES" if test -z "$HAVE_WEB100_TRUE" && test -n "$HAVE_WEB100_FALSE"; then if test -z "$HAVE_PCAP_H_TRUE" && test -n "$HAVE_PCAP_H_FALSE"; then @@ -314,13 +334,14 @@ fi echo "* web100clt: ${SUMMARY_WEB100CLT}" echo "" -if test "$SUMMARY_FAKEWWW" = "YES" && test "$SUMMARY_WEB100SRV" = "YES" && test "$SUMMARY_TCPBW100JAR" = "YES"; then +if test "$SUMMARY_FAKEWWW" = "YES" && (test "$SUMMARY_WEB100SRV" = "YES" || test "$SUMMARY_WEB100GSRV" = "YES") && test "$SUMMARY_TCPBW100JAR" = "YES"; then echo "*** Server Tools - complete" else echo "*** Server Tools - incomplete" fi echo "* fakewww: ${SUMMARY_FAKEWWW}" echo "* web100srv: ${SUMMARY_WEB100SRV}" +echo "* web10gsrv: ${SUMMARY_WEB10GSRV}" echo "* Tcpbw100.jar: ${SUMMARY_TCPBW100JAR}" echo "" diff --git a/src/Makefile.am b/src/Makefile.am index d9b5d3c..b022ebd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -33,6 +33,16 @@ else bin_PROGRAMS = web100clt endif +if HAVE_TCPE +if HAVE_PCAP_H +if HAVE_WEB100 +sbin_PROGRAMS += web10gsrv +else +sbin_PROGRAMS = fakewww web10gsrv +endif +endif +endif + web100clt_SOURCES = web100clt.c network.c usage.c logging.c utils.c protocol.c runningtest.c ndtptestconstants.c \ test_sfw_clt.c test_mid_clt.c test_c2s_clt.c test_s2c_clt.c test_meta_clt.c strlutils.c \ test_results_clt.c @@ -46,7 +56,7 @@ genplot_CPPFLAGS ='-DBASEDIR="$(ndtdir)"' analyze_SOURCES = analyze.c usage.c logging.c runningtest.c ndtptestconstants.c strlutils.c analyze_LDADD = $(NDTLIBS) $(I2UTILLIBDEPS) $(ZLIB) -analyze_CPPFLAGS ='-DBASEDIR="$(ndtdir)"' +analyze_CPPFLAGS ='-DBASEDIR="$(ndtdir)"' -DFORCE_WEB100 fakewww_SOURCES = fakewww.c troute.c troute6.c tr-tree.c tr-tree6.c network.c usage.c logging.c \ runningtest.c ndtptestconstants.c strlutils.c @@ -59,12 +69,21 @@ web100srv_SOURCES = web100srv.c web100-util.c web100-pcap.c web100-admin.c runni test_c2s_srv.c test_s2c_srv.c test_mid_srv.c web100srv_LDFLAGS = $(NDTLDFLAGS) $(I2UTILLDFLAGS) web100srv_LDADD = $(NDTLIBS) $(I2UTILLIBS) $(I2UTILLIBDEPS) -lpthread $(ZLIB) -web100srv_CPPFLAGS ='-DBASEDIR="$(ndtdir)"' +web100srv_CPPFLAGS ='-DBASEDIR="$(ndtdir)"' -DFORCE_WEB100 web100srv_DEPENDENCIES = $(I2UTILLIBDEPS) +web10gsrv_SOURCES = web100srv.c web100-util.c web100-pcap.c web100-admin.c runningtest.c \ + network.c usage.c utils.c mrange.c logging.c testoptions.c ndtptestconstants.c \ + protocol.c test_sfw_srv.c test_meta_srv.c ndt_odbc.c strlutils.c heuristics.c \ + test_c2s_srv.c test_s2c_srv.c test_mid_srv.c web10g-util.c +web10gsrv_LDFLAGS = $(NDTLDFLAGS) $(I2UTILLDFLAGS) +web10gsrv_LDADD = $(NDTLIBS) $(I2UTILLIBS) $(I2UTILLIBDEPS) -lpthread $(ZLIB) +web10gsrv_CPPFLAGS = '-DBASEDIR="$(ndtdir)"' +web10gsrv_DEPENDENCIES = $(I2UTILLIBDEPS) + viewtrace_SOURCES = viewtrace.c usage.c logging.c utils.c runningtest.c ndtptestconstants.c strlutils.c viewtrace_LDADD = $(NDTLIBS) $(I2UTILLIBDEPS) $(ZLIB) -viewtrace_CPPFLAGS ='-DBASEDIR="$(ndtdir)"' +viewtrace_CPPFLAGS ='-DBASEDIR="$(ndtdir)"' -DFORCE_WEB100 tr_mkmap_SOURCES = tr-mkmap.c tr-tree.c tr-tree6.c usage.c logging.c runningtest.c ndtptestconstants.c strlutils.c tr_mkmap_LDADD = $(NDTLIBS) $(I2UTILLIBDEPS) $(ZLIB) diff --git a/src/logging.c b/src/logging.c index 2689dd2..48afa08 100644 --- a/src/logging.c +++ b/src/logging.c @@ -701,7 +701,7 @@ void protolog_println(char *msgdirection, const int type, void* msg, * @param processid PID of process * @param ctlSocket socket over which message has been exchanged * */ -void protolog_sendprintln(const int type, void* msg, const int len, +void protolog_sendprintln(const int type, const void* msg, const int len, const int processid, const int ctlSocket) { char *currentDir; @@ -711,7 +711,7 @@ void protolog_sendprintln(const int type, void* msg, const int len, } currentDir = get_currentdirndesc(); - protolog_println(currentDir, type, msg, len, processid, ctlSocket); + protolog_println(currentDir, type, (void*) msg, len, processid, ctlSocket); } /** diff --git a/src/logging.h b/src/logging.h index 25af4f2..1c587b0 100644 --- a/src/logging.h +++ b/src/logging.h @@ -99,7 +99,7 @@ void log_linkspeed(int index); void protolog_printgeneric(const char* key, const char* val, int socketnum); void protolog_status(int pid, enum TEST_ID testid, enum TEST_STATUS_INT teststatus, int socketnum); -void protolog_sendprintln(const int type, void* msg, const int len, +void protolog_sendprintln(const int type, const void* msg, const int len, const int processid, const int ctlSocket); void protolog_rcvprintln(const int type, void* msg, const int len, const int processid, const int ctlSocket); diff --git a/src/network.c b/src/network.c index 5a6eb08..cfc539c 100644 --- a/src/network.c +++ b/src/network.c @@ -415,7 +415,7 @@ int CreateConnectSocket(int* sockfd, I2Addr local_addr, I2Addr server_addr, * */ -int send_msg(int ctlSocket, int type, void* msg, int len) { +int send_msg(int ctlSocket, int type, const void* msg, int len) { unsigned char buff[3]; int rc, i; @@ -524,9 +524,9 @@ int recv_msg(int ctlSocket, int* type, void* msg, int* len) { * @return The amount of bytes written to the file descriptor */ -int writen(int fd, void* buf, int amount) { +int writen(int fd, const void* buf, int amount) { int sent, n; - char* ptr = buf; + const char* ptr = buf; sent = 0; assert(amount >= 0); while (sent < amount) { diff --git a/src/network.h b/src/network.h index fd0d2f6..2205986 100644 --- a/src/network.h +++ b/src/network.h @@ -20,9 +20,9 @@ I2Addr CreateListenSocket(I2Addr addr, char* serv, int options, int buf_size); int CreateConnectSocket(int* sockfd, I2Addr local_addr, I2Addr server_addr, int option, int buf_sizes); -int send_msg(int ctlSocket, int type, void* msg, int len); +int send_msg(int ctlSocket, int type, const void* msg, int len); int recv_msg(int ctlSocket, int* type, void* msg, int* len); -int writen(int fd, void* buf, int amount); +int writen(int fd, const void* buf, int amount); int readn(int fd, void* buf, int amount); /* web100-util.c routine used in network. */ diff --git a/src/test_c2s_srv.c b/src/test_c2s_srv.c index b3a2103..60de92d 100644 --- a/src/test_c2s_srv.c +++ b/src/test_c2s_srv.c @@ -61,10 +61,13 @@ int mon_pipe1[2]; * -102 - Retries exceeded while waiting for data from connected client * */ -int test_c2s(int ctlsockfd, web100_agent* agent, TestOptions* testOptions, +int test_c2s(int ctlsockfd, tcp_stat_agent* agent, TestOptions* testOptions, int conn_options, double* c2sspd, int set_buff, int window, int autotune, char* device, Options* options, int record_reverse, int count_vars, char spds[4][256], int* spd_index) { + tcp_stat_connection conn; + tcp_stat_group* group = NULL; + int recvsfd; // receiver socket file descriptor pid_t c2s_childpid = 0; // child process pids int msgretvalue, tmpbytecount; // used during the "read"/"write" process @@ -85,14 +88,12 @@ int test_c2s(int ctlsockfd, web100_agent* agent, TestOptions* testOptions, char listenc2sport[10]; // listening port pthread_t workerThreadId; - // web_100 related variables - web100_group* group = NULL; - web100_connection* conn = NULL; - // snap related variables SnapArgs snapArgs; snapArgs.snap = NULL; +#if USE_WEB100 snapArgs.log = NULL; +#endif snapArgs.delay = options->snapDelay; wait_sig = 0; @@ -252,8 +253,8 @@ int test_c2s(int ctlsockfd, web100_agent* agent, TestOptions* testOptions, // commenting out below to move to init_pkttrace function I2Addr src_addr = I2AddrByLocalSockFD(get_errhandle(), recvsfd, 0); - // Get web100 connection. Used to collect web100 variable statistics - conn = web100_connection_from_socket(agent, recvsfd); + // Get tcp_stat connection. Used to collect tcp_stat variable statistics + conn = tcp_stat_connection_from_socket(agent, recvsfd); // set up packet tracing. Collected data is used for bottleneck link // calculations @@ -281,6 +282,7 @@ int test_c2s(int ctlsockfd, web100_agent* agent, TestOptions* testOptions, &cli_addr); init_pkttrace(src_addr, (struct sockaddr *) &cli_addr, clilen, mon_pipe1, device, &pair, "c2s", options->compress); + log_println(1, "c2s is exiting gracefully"); exit(0); /* Packet trace finished, terminate gracefully */ } @@ -292,7 +294,7 @@ int test_c2s(int ctlsockfd, web100_agent* agent, TestOptions* testOptions, continue; break; } - if (strlen(tmpstr) > 5) + //if (strlen(tmpstr) > 5) memcpy(meta.c2s_ndttrace, tmpstr, strlen(tmpstr)); // name of nettrace file passed back from pcap child log_println(3, "--tracefile after packet_trace %s", @@ -375,13 +377,12 @@ int test_c2s(int ctlsockfd, web100_agent* agent, TestOptions* testOptions, // get receiver side Web100 stats and write them to the log file. close // sockets if (record_reverse == 1) - web100_get_data_recv(recvsfd, agent, conn, count_vars); - - close(recvsfd); - close(testOptions->c2ssockfd); + tcp_stat_get_data_recv(recvsfd, agent, conn, count_vars); // Next, send speed-chk a flag to retrieve the data it collected. // Skip this step if speed-chk isn't running. + close(recvsfd); + close(testOptions->c2ssockfd); if (getuid() == 0) { log_println(1, "Signal USR1(%d) sent to child [%d]", SIGUSR1, diff --git a/src/test_meta_srv.c b/src/test_meta_srv.c index b22d1de..216f9bd 100644 --- a/src/test_meta_srv.c +++ b/src/test_meta_srv.c @@ -22,7 +22,7 @@ /** * Performs the META test. * @param ctlsockfd Client control socket descriptor - * @param agent Web100 agent used to track the connection + * @param agent UNUSED Web100 agent used to track the connection * @param testOptions The test options * @param conn_options The connection options * @return 0 - success, @@ -38,7 +38,7 @@ * 4 - Invalid data format in received message */ -int test_meta_srv(int ctlsockfd, web100_agent* agent, TestOptions* testOptions, +int test_meta_srv(int ctlsockfd, tcp_stat_agent* agent, TestOptions* testOptions, int conn_options) { int j; int msgLen, msgType; diff --git a/src/test_mid_srv.c b/src/test_mid_srv.c index 7172d94..367baf4 100644 --- a/src/test_mid_srv.c +++ b/src/test_mid_srv.c @@ -9,7 +9,7 @@ * Author: kkumar */ -#include <syslog.h> +#include <syslog.h> #include <pthread.h> #include <sys/times.h> #include <assert.h> @@ -37,7 +37,7 @@ * >0 - error code. * Error codes: * -1 - Listener socket creation failed - * -3 - web100 connection data not obtained + * -3 - tcp_stat connection data not obtained * -100 - timeout while waiting for client to connect to server�s ephemeral port * -errno- Other specific socket error numbers * -101 - Retries exceeded while waiting for client to connect @@ -49,7 +49,7 @@ * */ -int test_mid(int ctlsockfd, web100_agent* agent, TestOptions* options, +int test_mid(int ctlsockfd, tcp_stat_agent* agent, TestOptions* options, int conn_options, double* s2c_throughput_mid) { int maxseg = ETHERNET_MTU_SIZE; /* int maxseg=1456, largewin=16*1024*1024; */ @@ -66,7 +66,7 @@ int test_mid(int ctlsockfd, web100_agent* agent, TestOptions* options, char listenmidport[10]; // listener socket for middlebox tests int msgType; int msgLen; - web100_connection* conn; + tcp_stat_connection conn; char tmpstr[256]; // temporary string storage struct timeval sel_tv; // time fd_set rfd; // receiver file descriptor @@ -235,8 +235,9 @@ int test_mid(int ctlsockfd, web100_agent* agent, TestOptions* options, meta.family = ((struct sockaddr *) &cli_addr)->sa_family; buff[0] = '\0'; - // get web100 connection data - if ((conn = web100_connection_from_socket(agent, midsfd)) == NULL) { + // get tcp_stat connection data +#if USE_WEB100 + if ((conn = tcp_stat_connection_from_socket(agent, midsfd)) == NULL) { log_println( 0, "!!!!!!!!!!! test_mid() failed to get web100 connection data, rc=%d", @@ -244,9 +245,18 @@ int test_mid(int ctlsockfd, web100_agent* agent, TestOptions* options, /* exit(-1); */ return -3; } +#elif USE_TCPE + if ((conn = tcp_stat_connection_from_socket(agent, midsfd)) == -1) { + log_println( + 0, + "test_min() failed to get web10g connection data, rc=%d", + errno); + return -3; + } +#endif // Perform S->C throughput test. Obtained results in "buff" - web100_middlebox(midsfd, agent, conn, buff, sizeof(buff)); + tcp_stat_middlebox(midsfd, agent, conn, buff, sizeof(buff)); // Transmit results in the form of a TEST_MSG message send_msg(ctlsockfd, TEST_MSG, buff, strlen(buff)); diff --git a/src/test_results_clt.c b/src/test_results_clt.c index a6aff54..345c1c0 100644 --- a/src/test_results_clt.c +++ b/src/test_results_clt.c @@ -296,15 +296,27 @@ void print_packetloss_excess(double spd, double loss) { /** * Print if TCP Selective Acknowledgment Options based on RFC 2018 is on - * + * web100: 0 off, >=1 on. + * web10g: 1 on, 2 selfDisabled, 3 peerDisabled. * @param SACKEnabled */ void print_SAck_RFC2018(int SACKEnabled) { printf("RFC 2018 Selective Acknowledgment: "); +#if USE_TCPE + if (SACKEnabled == 1) + printf("ON\n"); + else if (SACKEnabled == 2) + printf("OFF (self)\n"); + else if (SACKEnabled == 3) + printf("OFF (peer)\n"); + else + printf("<undefined (%d)>\n", SACKEnabled); +#elif USE_WEB100 if (SACKEnabled == 0) printf("OFF\n"); else printf("ON\n"); +#endif } /** @@ -314,35 +326,69 @@ void print_SAck_RFC2018(int SACKEnabled) { void print_Nagle_RFC896(int is_nagleenabled) { printf("RFC 896 Nagle Algorithm: "); +#if USE_TCPE + if (is_nagleenabled == 1) + printf("ON\n"); + else if (is_nagleenabled == 2) + printf("OFF\n"); + else + printf("<undefined (%d)>\n", is_nagleenabled); +#elif USE_WEB100 if (is_nagleenabled == 0) printf("OFF\n"); else printf("ON\n"); +#endif } /** * Print if Explicit congestion notification to IP is on - RFC 3168 related + * web100 0 off, >=1 on + * web10g 1 on, 2 selfDisabled, 3 peerDisabled * @param is_ECNenabled */ void print_congestion_RFC3168(int is_ECNenabled) { printf("RFC 3168 Explicit Congestion Notification: "); +#if USE_TCPE + if (is_ECNenabled == 1) + printf("ON\n"); + else if (is_ECNenabled == 2) + printf("OFF (self)\n"); + else if (is_ECNenabled == 3) + printf("OFF (peer)\n"); + else + printf("<undefined (%d)>\n", is_ECNenabled); +#elif USE_WEB100 if (is_ECNenabled == 0) printf("OFF\n"); else printf("ON\n"); +#endif } /** * Print details of whether time stamping is on - RFC 1323 related. - * + * web100 1 on, 0 off + * web10g 1 on, 2 selfDisabled, 3 peerDisabled * @param is_timestampenabled */ void print_timestamping_RFC1323(int is_timestampenabled) { printf("RFC 1323 Time Stamping: "); +#if USE_TCPE + if (is_timestampenabled == 1) + printf("ON\n"); + else if (is_timestampenabled == 2) + printf("OFF (self)\n"); + else if (is_timestampenabled == 3) + printf("OFF (peer)\n"); + else + printf("<undefined (%d)>\n", is_timestampenabled); +#elif USE_WEB100 if (is_timestampenabled == 0) printf("OFF\n"); else printf("ON\n"); +#endif } /** diff --git a/src/test_s2c_srv.c b/src/test_s2c_srv.c index a297cf1..ee6b0fa 100644 --- a/src/test_s2c_srv.c +++ b/src/test_s2c_srv.c @@ -25,7 +25,7 @@ extern pthread_mutex_t mainmutex; extern pthread_cond_t maincond; -// used to store file descriptors of pipes created for ndttrace for C2S tests +// used to store file descriptors of pipes created for ndttrace for S2C tests int mon_pipe2[2]; /** @@ -46,7 +46,7 @@ int mon_pipe2[2]; * @param testOptions - the test options * @param conn_options - the connection options * @param testOptions Test options - * @param s2cspd In-out parameter to store C2S throughput value + * @param s2cspd In-out parameter to store S2C throughput value * @param set_buff enable setting TCP send/recv buffer size to be used (seems unused in file) * @param window value of TCP send/rcv buffer size intended to be used. * @param autotune autotuning option. Deprecated. @@ -70,10 +70,25 @@ int mon_pipe2[2]; * -102 - Retries exceeded while waiting for data from connected client * -errno - Other specific socket error numbers */ -int test_s2c(int ctlsockfd, web100_agent* agent, TestOptions* testOptions, +int test_s2c(int ctlsockfd, tcp_stat_agent* agent, TestOptions* testOptions, int conn_options, double* s2cspd, int set_buff, int window, int autotune, char* device, Options* options, char spds[4][256], int* spd_index, int count_vars, CwndPeaks* peaks) { +#if USE_WEB100 + /* experimental code to capture and log multiple copies of the + * web100 variables using the web100_snap() & log() functions. + */ + web100_snapshot* tsnap = NULL; + web100_snapshot* rsnap = NULL; + web100_group* tgroup; + web100_group* rgroup; + web100_var* var; +#elif USE_TCPE + tcpe_data* snap; +#endif + tcp_stat_connection conn; + /* Just a holder for web10g */ + tcp_stat_group* group = NULL; int ret; // ctrl protocol read/write return status int j, k, n; int xmitsfd; // transmit (i.e server) socket fd @@ -101,16 +116,6 @@ int test_s2c(int ctlsockfd, web100_agent* agent, TestOptions* testOptions, int sndqueue; struct sigaction new, old; - /* experimental code to capture and log multiple copies of the - * web100 variables using the web100_snap() & log() functions. - */ - web100_snapshot* tsnap = NULL; - web100_snapshot* rsnap = NULL; - web100_group* group; - web100_group* tgroup; - web100_group* rgroup; - web100_connection* conn; - web100_var* var; pthread_t workerThreadId; int nextseqtosend = 0, lastunackedseq = 0; int drainingqueuecount = 0, bufctlrnewdata = 0; @@ -124,7 +129,9 @@ int test_s2c(int ctlsockfd, web100_agent* agent, TestOptions* testOptions, SnapArgs snapArgs; snapArgs.snap = NULL; +#if USE_WEB100 snapArgs.log = NULL; +#endif snapArgs.delay = options->snapDelay; wait_sig = 0; @@ -224,7 +231,7 @@ int test_s2c(int ctlsockfd, web100_agent* agent, TestOptions* testOptions, clilen = sizeof(cli_addr); FD_ZERO(&rfd); - FD_SET(testOptions->c2ssockfd, &rfd); + FD_SET(testOptions->s2csockfd, &rfd); sel_tv.tv_sec = 5; // wait for 5 secs sel_tv.tv_usec = 0; for (j = 0; j < RETRY_COUNT; j++) { @@ -276,7 +283,7 @@ ximfd: xmitsfd = accept(testOptions->s2csockfd, } } src_addr = I2AddrByLocalSockFD(get_errhandle(), xmitsfd, 0); - conn = web100_connection_from_socket(agent, xmitsfd); + conn = tcp_stat_connection_from_socket(agent, xmitsfd); // set up packet capture. The data collected is used for bottleneck link // calculations @@ -340,10 +347,15 @@ ximfd: xmitsfd = accept(testOptions->s2csockfd, // system("/sbin/sysctl -w net.ipv4.route.flush=1"); system("echo 1 > /proc/sys/net/ipv4/route/flush"); } + +#if USE_WEB100 rgroup = web100_group_find(agent, "read"); rsnap = web100_snapshot_alloc(rgroup, conn); tgroup = web100_group_find(agent, "tune"); tsnap = web100_snapshot_alloc(tgroup, conn); +#elif USE_TCPE + tcpe_data_new(&snap); +#endif // fill send buffer with random printable data for throughput test bytes_written = 0; @@ -394,6 +406,7 @@ ximfd: xmitsfd = accept(testOptions->s2csockfd, // get details of next sequence # to be sent and fetch value from // snap file +#if USE_WEB100 web100_agent_find_var_and_group(agent, "SndNxt", &group, &var); web100_snap_read(var, snapArgs.snap, tmpstr); @@ -407,6 +420,13 @@ ximfd: xmitsfd = accept(testOptions->s2csockfd, lastunackedseq = atoi( web100_value_to_text(web100_get_var_type(var), tmpstr)); +#elif USE_TCPE + struct tcpe_val value; + web10g_find_val(snapArgs.snap, "SndNxt", &value); + nextseqtosend = value.uv32; + web10g_find_val(snapArgs.snap, "SndUna", &value); + lastunackedseq = value.uv32; +#endif pthread_mutex_unlock(&mainmutex); // Temporarily stop sending data if you sense that the buffer is @@ -463,8 +483,12 @@ ximfd: xmitsfd = accept(testOptions->s2csockfd, "S2C test - failed to send test message to pid=%d", s2c_childpid); +#if USE_WEB100 web100_snap(rsnap); web100_snap(tsnap); +#elif USE_TCPE + tcpe_read_vars(snap, conn, agent); +#endif log_println(1, "sent %d bytes to client in %0.2f seconds", (int) bytes_written, tx_duration); @@ -546,12 +570,18 @@ ximfd: xmitsfd = accept(testOptions->s2csockfd, // Get web100 variables from snapshot taken earlier and send to client log_println(6, "S2C-Send web100 data vars to client pid=%d", s2c_childpid); + +#if USE_WEB100 // send web100 data to client - ret = web100_get_data(tsnap, ctlsockfd, agent, count_vars); + ret = tcp_stat_get_data(tsnap, xmitsfd, ctlsockfd, agent, count_vars); web100_snapshot_free(tsnap); // send tuning-related web100 data collected to client - ret = web100_get_data(rsnap, ctlsockfd, agent, count_vars); + ret = tcp_stat_get_data(rsnap, xmitsfd, ctlsockfd, agent, count_vars); web100_snapshot_free(rsnap); +#elif USE_TCPE + ret = tcp_stat_get_data(snap, xmitsfd, ctlsockfd, agent, count_vars); + tcpe_data_free(&snap); +#endif // If sending web100 variables above failed, indicate to client if (ret < 0) { diff --git a/src/test_sfw_srv.c b/src/test_sfw_srv.c index 359b48f..2481168 100644 --- a/src/test_sfw_srv.c +++ b/src/test_sfw_srv.c @@ -120,7 +120,7 @@ void finalize_sfw(int ctlsockfd) { * 5 - Unable to resolve client address */ -int test_sfw_srv(int ctlsockfd, web100_agent* agent, TestOptions* options, +int test_sfw_srv(int ctlsockfd, tcp_stat_agent* agent, TestOptions* options, int conn_options) { char buff[BUFFSIZE + 1]; I2Addr sfwsrv_addr = NULL; @@ -130,9 +130,15 @@ int test_sfw_srv(int ctlsockfd, web100_agent* agent, TestOptions* options, fd_set fds; struct timeval sel_tv; int msgLen, msgType; + +#if USE_WEB100 web100_var* var; web100_connection* cn; web100_group* group; +#elif USE_TCPE + struct tcpe_val value; + int cn; +#endif int maxRTT, maxRTO; char hostname[256]; int rc; @@ -169,26 +175,39 @@ int test_sfw_srv(int ctlsockfd, web100_agent* agent, TestOptions* options, sfwsockport = I2AddrPort(sfwsrv_addr); log_println(1, " -- port: %d", sfwsockport); - cn = web100_connection_from_socket(agent, ctlsockfd); + cn = tcp_stat_connection_from_socket(agent, ctlsockfd); if (cn) { // Get remote end's address + memset(hostname, 0, sizeof(hostname)); + +#if USE_WEB100 web100_agent_find_var_and_group(agent, "RemAddress", &group, &var); web100_raw_read(var, cn, buff); - memset(hostname, 0, 256); // strncpy(hostname, web100_value_to_text(web100_get_var_type(var), buff), // 255); strlcpy(hostname, web100_value_to_text(web100_get_var_type(var), buff), sizeof(hostname)); +#elif USE_TCPE + web10g_get_remote_addr(agent, cn, hostname, sizeof(hostname)); +#endif // Determine test time in seconds. // test-time = max(round trip time, timeout) > 3 ? 3 : 1 +#if USE_WEB100 web100_agent_find_var_and_group(agent, "MaxRTT", &group, &var); web100_raw_read(var, cn, buff); maxRTT = atoi(web100_value_to_text(web100_get_var_type(var), buff)); web100_agent_find_var_and_group(agent, "MaxRTO", &group, &var); web100_raw_read(var, cn, buff); maxRTO = atoi(web100_value_to_text(web100_get_var_type(var), buff)); +#elif USE_TCPE + web10g_get_val(agent, cn, "MaxRTT", &value); + maxRTT = value.uv32; + web10g_get_val(agent, cn, "MaxRTO", &value); + maxRTO = value.uv32; +#endif + if (maxRTT > maxRTO) maxRTO = maxRTT; if ((((double) maxRTO) / 1000.0) > 3.0) diff --git a/src/testoptions.c b/src/testoptions.c index d16c383..2b40e7b 100644 --- a/src/testoptions.c +++ b/src/testoptions.c @@ -24,7 +24,7 @@ // Worker thread characteristics used to record snaplog and Cwnd peaks typedef struct workerArgs { SnapArgs* snapArgs; // snapArgs struct pointer - web100_agent* agent; // web_100 agent pointer + tcp_stat_agent* agent; // tcp_stat agent pointer CwndPeaks* peaks; // data indicating Cwnd values int writeSnap; // enable writing snaplog } WorkerArgs; @@ -44,17 +44,25 @@ static int decreasing = 0; * @param peaks Structure containing CWND peaks information * @param snap Web100 snapshot structure */ - -void findCwndPeaks(web100_agent* agent, CwndPeaks* peaks, - web100_snapshot* snap) { +void findCwndPeaks(tcp_stat_agent* agent, CwndPeaks* peaks, + tcp_stat_snap* snap) { + int CurCwnd; +#if USE_WEB100 web100_group* group; web100_var* var; - int CurCwnd; char tmpstr[256]; +#elif USE_TCPE + struct tcpe_val value; +#endif +#if USE_WEB100 web100_agent_find_var_and_group(agent, "CurCwnd", &group, &var); web100_snap_read(var, snap, tmpstr); CurCwnd = atoi(web100_value_to_text(web100_get_var_type(var), tmpstr)); +#elif USE_TCPE + web10g_find_val(snap, "CurCwnd", &value); + CurCwnd = value.uv32; +#endif if (slowStart) { if (CurCwnd < prevCWNDval) { @@ -108,9 +116,11 @@ void catch_s2c_alrm(int signo) { void* snapWorker(void* arg) { + /* WARNING void* arg (workerArgs) is on the stack of the function below and + * doesn't exist forever. */ WorkerArgs *workerArgs = (WorkerArgs*) arg; SnapArgs *snapArgs = workerArgs->snapArgs; - web100_agent* agent = workerArgs->agent; + tcp_stat_agent* agent = workerArgs->agent; CwndPeaks* peaks = workerArgs->peaks; int writeSnap = workerArgs->writeSnap; @@ -136,6 +146,7 @@ snapWorker(void* arg) { pthread_mutex_unlock(&mainmutex); break; } +#if USE_WEB100 web100_snap(snapArgs->snap); if (peaks) { findCwndPeaks(agent, peaks, snapArgs->snap); @@ -143,6 +154,15 @@ snapWorker(void* arg) { if (writeSnap) { web100_log_write(snapArgs->log, snapArgs->snap); } +#elif USE_TCPE + tcpe_read_vars(snapArgs->snap, snapArgs->conn, agent); + if (peaks) { + findCwndPeaks(agent, peaks, snapArgs->snap); + } + if (writeSnap) { + // TODO: logging + } +#endif pthread_mutex_unlock(&mainmutex); mysleep(delay); } @@ -249,20 +269,20 @@ int initialize_tests(int ctlsockfd, TestOptions* options, char * buff, /** Method to start snap worker thread that collects snap logs * @param snaparg object - * @param web100_agent Agent + * @param tcp_stat_agent Agent * @param snaplogenabled Is snap logging enabled? - * @param workerlooparg integer used to syncronize writing/reading from snaplog/web100 snapshot + * @param workerlooparg integer used to syncronize writing/reading from snaplog/tcp_stat snapshot * @param wrkrthreadidarg Thread Id of workera * @param metafilevariablename Which variable of the meta file gets assigned the snaplog name (unused now) * @param metafilename value of metafile name - * @param web100_connection connection pointer - * @param web100_group group web100_group pointer + * @param tcp_stat_connection connection pointer + * @param tcp_stat_group group web100_group pointer */ -void start_snap_worker(SnapArgs *snaparg, web100_agent *agentarg, +void start_snap_worker(SnapArgs *snaparg, tcp_stat_agent* agentarg, CwndPeaks* peaks, char snaplogenabled, pthread_t *wrkrthreadidarg, char *metafilevariablename, - char *metafilename, web100_connection* conn, - web100_group* group) { + char *metafilename, tcp_stat_connection conn, + tcp_stat_group* group) { FILE *fplocal; WorkerArgs workerArgs; @@ -271,8 +291,13 @@ void start_snap_worker(SnapArgs *snaparg, web100_agent *agentarg, workerArgs.peaks = peaks; workerArgs.writeSnap = snaplogenabled; +#if USE_WEB100 group = web100_group_find(agentarg, "read"); snaparg->snap = web100_snapshot_alloc(group, conn); +#elif USE_TCPE + snaparg->conn = conn; + tcpe_data_new(&snaparg->snap); +#endif if (snaplogenabled) { // memcpy(metafilevariablename, metafilename, strlen(metafilename)); @@ -280,7 +305,10 @@ void start_snap_worker(SnapArgs *snaparg, web100_agent *agentarg, // just the file name, but full filename is needed to open the log file fplocal = fopen(get_logfile(), "a"); + +#if USE_WEB100 snaparg->log = web100_log_open_write(metafilename, conn, group); +#endif if (fplocal == NULL) { log_println( 0, @@ -302,10 +330,15 @@ void start_snap_worker(SnapArgs *snaparg, web100_agent *agentarg, pthread_mutex_lock(&mainmutex); workerLoop= 1; // obtain web100 snap into "snaparg.snap" +#if USE_WEB100 web100_snap(snaparg->snap); if (snaplogenabled) { web100_log_write(snaparg->log, snaparg->snap); } +#elif USE_TCPE + tcpe_read_vars(snaparg->snap, conn, agentarg); + // TODO: logging +#endif pthread_cond_wait(&maincond, &mainmutex); pthread_mutex_unlock(&mainmutex); } @@ -325,11 +358,15 @@ void stop_snap_worker(pthread_t *workerThreadId, char snaplogenabled, pthread_join(*workerThreadId, NULL); } // close writing snaplog, if snaplog recording is enabled +#if USE_WEB100 if (snaplogenabled) { web100_log_close_write(snapArgs_ptr->log); } web100_snapshot_free(snapArgs_ptr->snap); +#elif USE_TCPE + tcpe_data_free(&snapArgs_ptr->snap); +#endif } /** @@ -411,22 +448,28 @@ void stop_packet_trace(int *monpipe_arr) { /** * Set Cwnd limit - * @param connarg web100_connection pointer - * @param group_arg web100 group pointer - * @param agentarg web100 agent pointer + * @param connarg tcp_stat_connection pointer + * @param group_arg tcp_stat group pointer + * @param agentarg tcp_stat agent pointer * */ -void setCwndlimit(web100_connection* connarg, web100_group* grouparg, - web100_agent* agentarg, Options* optionsarg) { +void setCwndlimit(tcp_stat_connection connarg, tcp_stat_group* grouparg, + tcp_stat_agent* agentarg, Options* optionsarg) { +#if USE_WEB100 web100_var *LimRwin, *yar; +#elif USE_TCPE + struct tcpe_val yar; +#endif + u_int32_t limrwin_val; - char yuff[32]; if (optionsarg->limit > 0) { log_print(1, "Setting Cwnd limit - "); +#if USE_WEB100 if (connarg != NULL) { log_println(1, "Got web100 connection pointer for recvsfd socket\n"); + char yuff[32]; web100_agent_find_var_and_group(agentarg, "CurMSS", &grouparg, &yar); web100_raw_read(yar, connarg, yuff); @@ -442,6 +485,17 @@ void setCwndlimit(web100_connection* connarg, web100_group* grouparg, log_print(1, "now write %d to limit the Receive window", limrwin_val); web100_raw_write(LimRwin, connarg, &limrwin_val); +#elif USE_TCPE + if (connarg != -1) { + log_println(1, + "Got web10g connection for recvsfd socket\n"); + web10g_get_val(agentarg, connarg, "CurMSS", &yar); + log_println(1, "MSS = %s, multiplication factor = %d", + yar.uv32, optionsarg->limit); + limrwin_val = optionsarg->limit * yar.uv32; + log_print(1, "now write %d to limit the Receive window", limrwin_val); + tcpe_write_var("LimRwin", limrwin_val, connarg, agentarg); +#endif log_println(1, " --- Done"); } } diff --git a/src/testoptions.h b/src/testoptions.h index c2eaa93..c5eaee6 100644 --- a/src/testoptions.h +++ b/src/testoptions.h @@ -17,7 +17,6 @@ #define RETRY_EXCEEDED_WAITING_DATA -102 #define SOCKET_STATUS_FAILED -1 - typedef struct testoptions { int multiple; // multiples tests enabled int mainport; // main port used for test @@ -47,8 +46,9 @@ typedef struct testoptions { // Snap log characteristics typedef struct snapArgs { - web100_snapshot* snap; // web_100 snapshot indicator - web100_log* log; // web_100 log + tcp_stat_connection conn; + tcp_stat_snap* snap; + tcp_stat_log* log; int delay; // periodicity, in ms, of collecting snap } SnapArgs; @@ -59,26 +59,26 @@ int initialize_tests(int ctlsockfd, TestOptions* testOptions, void catch_s2c_alrm(int signo); -int test_sfw_srv(int ctlsockfd, web100_agent* agent, TestOptions* options, +int test_sfw_srv(int ctlsockfd, tcp_stat_agent* agent, TestOptions* options, int conn_options); -int test_meta_srv(int ctlsockfd, web100_agent* agent, TestOptions* options, +int test_meta_srv(int ctlsockfd, tcp_stat_agent* agent, TestOptions* options, int conn_options); int getCurrentTest(); void setCurrentTest(int testId); -// void start_snap_worker(SnapArgs *snaparg, web100_agent *agentarg, -void start_snap_worker(SnapArgs *snaparg, web100_agent *agentarg, +// void start_snap_worker(SnapArgs *snaparg, tcp_stat_agent *agentarg, +void start_snap_worker(SnapArgs *snaparg, tcp_stat_agent *agentarg, CwndPeaks* peaks, char snaplogenabled, pthread_t *wrkrthreadidarg, char *metafilevariablename, - char *metafilename, web100_connection* conn, - web100_group* group); + char *metafilename, tcp_stat_connection conn, + tcp_stat_group* group); void stop_snap_worker(pthread_t *workerThreadId, char snaplogenabled, SnapArgs* snapArgs_ptr); -void setCwndlimit(web100_connection* connarg, web100_group* grouparg, - web100_agent* agentarg, Options* optionsarg); +void setCwndlimit(tcp_stat_connection connarg, tcp_stat_group* grouparg, + tcp_stat_agent* agentarg, Options* optionsarg); int is_buffer_clogged(int nextseqtosend, int lastunackedseq); void stop_packet_trace(int *monpipe_arr); diff --git a/src/tests_srv.h b/src/tests_srv.h index baaed65..4d86947 100644 --- a/src/tests_srv.h +++ b/src/tests_srv.h @@ -11,19 +11,19 @@ #include "testoptions.h" -int test_c2s(int ctlsockfd, web100_agent* agent, TestOptions* testOptions, +int test_c2s(int ctlsockfd, tcp_stat_agent* agent, TestOptions* testOptions, int conn_options, double* c2sspd, int set_buff, int window, int autotune, char* device, Options* options, int record_reverse, int count_vars, char spds[4][256], int* spd_index); // S2C test -int test_s2c(int ctlsockfd, web100_agent* agent, TestOptions* testOptions, +int test_s2c(int ctlsockfd, tcp_stat_agent* agent, TestOptions* testOptions, int conn_options, double* s2cspd, int set_buff, int window, int autotune, char* device, Options* options, char spds[4][256], int* spd_index, int count_vars, CwndPeaks* peaks); // the middlebox test -int test_mid(int ctlsockfd, web100_agent* agent, TestOptions* testOptions, +int test_mid(int ctlsockfd, tcp_stat_agent* agent, TestOptions* testOptions, int conn_options, double* s2c2spd); #endif // SRC_TESTS_SRV_H_ diff --git a/src/web100-admin.c b/src/web100-admin.c index 06bf6e7..319ec22 100644 --- a/src/web100-admin.c +++ b/src/web100-admin.c @@ -7,16 +7,18 @@ * */ +#include "web100-admin.h" + #include <math.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> -#include "web100srv.h" +#include "heuristics.h" #include "logging.h" -#include "web100-admin.h" -#include "utils.h" #include "strlutils.h" +#include "utils.h" +#include "web100srv.h" /* Initialize the Administrator view. Process the data in the existing log file to * catch up on what's happened before. diff --git a/src/web100-pcap.c b/src/web100-pcap.c index 889da44..783df4d 100644 --- a/src/web100-pcap.c +++ b/src/web100-pcap.c @@ -90,6 +90,15 @@ void get_iflist(void) { pcap_freealldevs(alldevs); } +/** + * Force the pcap_loop to return. Safe to call from signal handler. + */ +void force_breakloop() { + if (pd != NULL) { + pcap_breakloop(pd); + } +} + /** Check signal flags and process them accordingly. * If signal indicates request to terminate data collection for the speed bins, * make packet-pair based speed bins available to the parent process. @@ -97,7 +106,7 @@ void get_iflist(void) { * @return 1 if data was successfully written * 0 if no relevant signals were actually received */ -int check_signal_flags() { +static int check_signal_flags() { if ((sig1 == 1) || (sig2 == 1)) { log_println( 5, @@ -135,9 +144,6 @@ int check_signal_flags() { usleep(30000); /* wait here 30 msec, for parent to read this data */ print_bins(&rev, mon_pipe1); usleep(30000); /* wait here 30 msec, for parent to read this data */ - if (pd != NULL) { - pcap_breakloop(pd); - } if (dumptrace == 1) pcap_dump_close(pdump); sig1 = 2; @@ -175,9 +181,6 @@ int check_signal_flags() { usleep(30000); /* wait here 30 msec, for parent to read this data */ print_bins(&rev, mon_pipe2); usleep(30000); /* wait here 30 msec, for parent to read this data */ - if (pd != NULL) { - pcap_breakloop(pd); - } if (dumptrace == 1) pcap_dump_close(pdump); sig2 = 2; @@ -559,10 +562,6 @@ void print_speed(u_char *user, const struct pcap_pkthdr *h, const u_char *p) { return; } - if (check_signal_flags()) { - return; - } - current.sec = h->ts.tv_sec; current.usec = h->ts.tv_usec; current.time = (current.sec * 1000000) + current.usec; @@ -787,7 +786,7 @@ void print_speed(u_char *user, const struct pcap_pkthdr *h, const u_char *p) { void init_pkttrace(I2Addr srcAddr, struct sockaddr *sock_addr, socklen_t saddrlen, int monitor_pipe[2], char *device, - PortPair* pair, char *direction, int compress) { + PortPair* pair, const char *direction, int compress) { char cmdbuf[256], dir[256]; pcap_handler printer; u_char * pcap_userdata = (u_char*) pair; @@ -1046,6 +1045,10 @@ void print_speed(u_char *user, const struct pcap_pkthdr *h, const u_char *p) { log_println(5, "pcap_loop exited %s", pcap_geterr(pd)); } + if (check_signal_flags() == 0) { + log_println(5, "We should have a sig flag set"); + } + pcap_close(pd); log_println( diff --git a/src/web100-util.c b/src/web100-util.c index 6164c02..43db4b5 100644 --- a/src/web100-util.c +++ b/src/web100-util.c @@ -10,12 +10,67 @@ #include <time.h> #include <assert.h> -#include "web100srv.h" -#include "network.h" #include "logging.h" -#include "utils.h" +#include "network.h" #include "protocol.h" #include "strlutils.h" +#include "utils.h" +#include "web100srv.h" + +struct tcp_name { + char* web100_name; + char* web10g_name; +}; + +/* Must match in-order with tcp_vars in web100srv.h struct */ +// TODO: more robust order matching with included file and preprocessor macros +static struct tcp_name tcp_names[] = { +/* {"WEB100", "WEB10G" } / tcp_vars name / */ + {"Timeouts", "Timeouts"}, /* Timeouts */ + {"SumRTT", "SumRTT"}, /* SumRTT */ + {"CountRTT", "CountRTT"}, /* CountRTT */ + {"PktsRetrans", "SegsRetrans"}, /* PktsRetrans */ + {"FastRetran", "FastRetran"}, /* FastRetran */ + {"DataPktsOut", "DataSegsOut"}, /* DataPktsOut */ + {"AckPktsOut", NULL}, /* AckPktsOut - not included in web10g */ + {"CurMSS", "CurMSS"}, /* CurrentMSS */ + {"DupAcksIn", "DupAcksIn"}, /* DupAcksIn */ + /* NOTE: in the server to client throughput test all packets received from client are ack's + * So SegsIn == AckPktsIn. I don't see a replacement in web10g maybe (SegsIn - DataSegsIn) + */ + {"AckPktsIn", "SegsIn"}, /* AckPktsIn - not included in web10g */ + {"MaxRwinRcvd", "MaxRwinRcvd"}, /* MaxRwinRcvd */ + {"X_Sndbuf", NULL}, /* Sndbuf - Not in Web10g pull from socket */ + {"CurCwnd", "CurCwnd"}, /* CurrentCwnd */ + {"SndLimTimeRwin", "SndLimTimeRwin"}, /* SndLimTimeRwin */ + {"SndLimTimeCwnd", "SndLimTimeCwnd"}, /* SndLimTimeCwnd */ + {"SndLimTimeSender", "SndLimTimeSnd"}, /* SndLimTimeSender */ + {"DataBytesOut", "DataOctetsOut"}, /* DataBytesOut */ + {"SndLimTransRwin", "SndLimTransRwin"}, /* SndLimTransRwin */ + {"SndLimTransCwnd", "SndLimTransCwnd"}, /* SndLimTransCwnd */ + {"SndLimTransSender", "SndLimTransSnd"}, /* SndLimTransSender */ + {"MaxSsthresh", "MaxSsthresh"}, /* MaxSsthresh */ + {"CurRTO", "CurRTO"}, /* CurrentRTO */ + {"CurRwinRcvd", "CurRwinRcvd"}, /* CurrentRwinRcvd */ + {"MaxCwnd", NULL}, /* MaxCwnd split into MaxSsCwnd and MaxCaCwnd web10g */ + {"CongestionSignals", "CongSignals"}, /* CongestionSignals */ + {"PktsOut", "SegsOut"}, /* PktsOut */ + {"MinRTT", "MinRTT"}, /* MinRTT */ + {"RcvWinScale", "WinScaleRcvd"}, /* RcvWinScale */ + {"SndWinScale", "WinScaleSent"}, /* SndWinScale */ + {"CongAvoid", "CongAvoid"}, /* CongAvoid */ + {"CongestionOverCount", "CongOverCount"}, /* CongestionOverCount */ + {"MaxRTT", "MaxRTT"}, /* MaxRTT */ + {"OtherReductions", "OtherReductions"}, /* OtherReductions */ + {"CurTimeoutCount", "CurTimeoutCount"}, /* CurTimeoutCount */ + {"AbruptTimeouts", "AbruptTimeouts"}, /* AbruptTimeouts */ + {"SendStall", "SendStall"}, /* SendStall */ + {"SlowStart", "SlowStart"}, /* SlowStart */ + {"SubsequentTimeouts", "SubsequentTimeouts"}, /* SubsequentTimeouts */ + {"ThruBytesAcked", "ThruOctetsAcked"}, /* ThruBytesAcked */ + { NULL, "MaxSsCwnd" }, /* MaxSsCwnd */ + { NULL, "MaxCaCwnd" } /* MaxCaCwnd */ +}; /** * set up the necessary structures for monitoring connections at the @@ -24,7 +79,8 @@ * @return integer indicating number of web100 variables read * or indicating failure of initialization */ -int web100_init(char *VarFileName) { +int tcp_stat_init(char *VarFileName) { +#if USE_WEB100 FILE * fp; char line[256], trimmedline[256]; int count_vars = 0; @@ -54,6 +110,45 @@ int web100_init(char *VarFileName) { log_println(1, "web100_init() read %d variables from file", count_vars); return (count_vars); +#elif USE_TCPE + return TOTAL_INDEX_MAX; +#endif +} + +/** + * Get a string representation of an ip address. + * + * @param addr A sockaddr structure which contains the address + * @param buf A buffer to fill with the ip address as a string + * @param len The length of buf. + */ +static void addr2a(struct sockaddr_storage * addr,char * buf, int len){ + if(((struct sockaddr *)addr)->sa_family == AF_INET) { + inet_ntop(AF_INET, &(((struct sockaddr_in *)addr)->sin_addr), buf, len); + } +#ifdef AF_INET6 + else if(((struct sockaddr *)addr)->sa_family == AF_INET6 ){ + inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)addr)->sin6_addr), buf, len); + } +#endif +} + +/** + * Get a string representation of an port number. + * + * @param addr A sockaddr structure which contains the port number + * @param buf A buffer to fill with the port number as a string + * @param len The length of buf. + */ +static void port2a(struct sockaddr_storage * addr,char * buf, int len){ + if(((struct sockaddr *)addr)->sa_family == AF_INET){ + snprintf(buf, len, "%hu", ntohs(((struct sockaddr_in *)addr)->sin_port)); + } +#ifdef AF_INET6 + else if(((struct sockaddr *)addr)->sa_family == AF_INET6 ){ + snprintf(buf, len, "%hu", ntohs(((struct sockaddr_in6 *)addr)->sin6_port)); + } +#endif } /** @@ -74,11 +169,18 @@ int web100_init(char *VarFileName) { * * */ -void web100_middlebox(int sock, web100_agent* agent, web100_connection* cn, - char *results, size_t results_strlen) { +void tcp_stat_middlebox(int sock, tcp_stat_agent* agent, tcp_stat_connection cn, + char *results, size_t results_strlen) { +#if USE_WEB100 web100_var* var; web100_group* group; web100_snapshot* snap; + web100_var* LimCwnd; +#elif USE_TCPE + struct tcpe_val value; + tcpe_data* data = NULL; +#endif + char buff[8192], line[256]; char* sndbuff; int i, j, k, currentMSSval = 0; @@ -88,9 +190,9 @@ void web100_middlebox(int sock, web100_agent* agent, web100_connection* cn, int ret; char tmpstr[200]; size_t tmpstrlen = sizeof(tmpstr); - I2Addr addr = NULL; - web100_var *LimCwnd; u_int32_t limcwnd_val; + struct sockaddr_storage saddr; + socklen_t saddr_size = sizeof(saddr); // middlebox test results static char vars[][255] = { "CurMSS", "WinScaleSent", "WinScaleRecv", }; @@ -100,17 +202,23 @@ void web100_middlebox(int sock, web100_agent* agent, web100_connection* cn, log_println(4, "Looking for Web100 data on socketid %d", sock); // get Server address and add to "results" - - // get socket name - addr = I2AddrByLocalSockFD(get_errhandle(), sock, False); - memset(tmpstr, 0, 200); - // copy address into tmpstr String - I2AddrNodeName(addr, tmpstr, &tmpstrlen); - // now copy tmpstr containing address into "line" - snprintf(line, sizeof(line), "%s;", tmpstr); - memset(tmpstr, 0, 200); - // service name into tmpstr - I2AddrServName(addr, tmpstr, &tmpstrlen); + // get socket IP address + if (getsockname(sock, (struct sockaddr*) &saddr, &saddr_size) == -1) { + /* Make it clear something failed but continue test */ + log_println(0,"Middlebox - getsockname() failed: %s", strerror(errno)); + snprintf(line, sizeof(line), "address_error;"); + snprintf(tmpstr, sizeof(tmpstr), "0"); + } else { + // copy address into tmpstr String + memset(tmpstr, 0, 200); + addr2a(&saddr, tmpstr, tmpstrlen); + // now copy tmpstr containing address into "line" + snprintf(line, sizeof(line), "%s;", tmpstr); + memset(tmpstr, 0, 200); + // service name into tmpstr + tmpstrlen = sizeof(tmpstr); + port2a(&saddr, tmpstr, tmpstrlen); + } log_print(3, "Server: %s%s ", line, tmpstr); // copy servers address into the meta test struct memcpy(meta.server_ip, line, strlen(line)); @@ -118,22 +226,31 @@ void web100_middlebox(int sock, web100_agent* agent, web100_connection* cn, meta.server_ip[(strlen(line) - 1)] = 0; // Add this address to results strlcat(results, line, results_strlen); - I2AddrFree(addr); // free memory // Now perform the above set of functions for client address/service name // and copy into results tmpstrlen = sizeof(tmpstr); - addr = I2AddrBySockFD(get_errhandle(), sock, False); - memset(tmpstr, 0, 200); - I2AddrNodeName(addr, tmpstr, &tmpstrlen); - snprintf(line, sizeof(line), "%s;", tmpstr); - I2AddrServName(addr, tmpstr, &tmpstrlen); + saddr_size = sizeof(saddr); + if (getpeername(sock, (struct sockaddr*) &saddr, &saddr_size) == -1) { + /* Make it clear something failed but continue test */ + log_println(0, "Middlebox - getpeername() failed: %s", strerror(errno)); + snprintf(line, sizeof(line), "address_error;"); + snprintf(tmpstr, sizeof(tmpstr), "0"); + } else { + // copy address into tmpstr String + memset(tmpstr, 0, 200); + addr2a(&saddr, tmpstr, tmpstrlen); + snprintf(line, sizeof(line), "%s;", tmpstr); + tmpstrlen = sizeof(tmpstr); + port2a(&saddr, tmpstr, tmpstrlen); + } + log_print(3, "Client: %s%s ", line, tmpstr); strlcat(results, line, results_strlen); - I2AddrFree(addr); // get web100 values for the middlebox test result group - for (i = 0; i < 3; i++) { + for (i = 0; i < ARRAYSIZE(vars); i++) { +#if USE_WEB100 // read web100_group and web100_var of vars[i] into group and var web100_agent_find_var_and_group(agent, vars[i], &group, &var); // read variable value from web100 connection @@ -147,6 +264,13 @@ void web100_middlebox(int sock, web100_agent* agent, web100_connection* cn, web100_value_to_text(web100_get_var_type(var), buff)); snprintf(line, sizeof(line), "%s;", web100_value_to_text(web100_get_var_type(var), buff)); +#elif USE_TCPE + web10g_get_val(agent, cn, vars[i], &value); + if (strcmp(vars[i], "CurMSS") == 0) + currentMSSval = value.uv32; + snprintf(line, sizeof(line), "%u;", value.uv32); +#endif + if (strcmp(line, "4294967295;") == 0) snprintf(line, sizeof(line), "%d;", -1); @@ -165,12 +289,18 @@ void web100_middlebox(int sock, web100_agent* agent, web100_connection* cn, * RAC 2/28/06 */ + limcwnd_val = 2 * currentMSSval; + +#if USE_WEB100 // get web100_var and web100_group web100_agent_find_var_and_group(agent, "LimCwnd", &group, &LimCwnd); // set TCP CWND web100 variable to twice the current MSS Value - limcwnd_val = 2 * currentMSSval; web100_raw_write(LimCwnd, cn, &limcwnd_val); +#elif USE_TCPE + tcpe_write_var("LimCwnd", (uint32_t)limcwnd_val, cn, agent); +#endif + log_println(5, "Setting Cwnd Limit to %d octets", limcwnd_val); // try to allocate memory of the size of current MSS Value @@ -194,9 +324,13 @@ void web100_middlebox(int sock, web100_agent* agent, web100_connection* cn, sndbuff[j] = (k++ & 0x7f); } +#if USE_WEB100 // get web100 group with name "read" group = web100_group_find(agent, "read"); snap = web100_snapshot_alloc(group, cn); +#elif USE_TCPE + tcpe_data_new(&data); +#endif FD_ZERO(&wfd); FD_SET(sock, &wfd); @@ -206,6 +340,7 @@ void web100_middlebox(int sock, web100_agent* agent, web100_connection* cn, if ((ret == -1) && (errno == EINTR)) /* a signal arrived, ignore it */ continue; +#if USE_WEB100 web100_snap(snap); // get next sequence # to be sent @@ -216,6 +351,13 @@ void web100_middlebox(int sock, web100_agent* agent, web100_connection* cn, web100_agent_find_var_and_group(agent, "SndUna", &group, &var); web100_snap_read(var, snap, line); SndUna = atoi(web100_value_to_text(web100_get_var_type(var), line)); +#elif USE_TCPE + tcpe_read_vars(data, cn, agent); + web10g_find_val(data, "SndNxt", &value); + SndMax = value.uv32; + web10g_find_val(data, "SndUna", &value); + SndUna = value.uv32; +#endif // stop sending data if (buf size * 16) < // [ (Next Sequence # To Be Sent) - (Oldest Unacknowledged Sequence #) - 1 ] @@ -231,9 +373,16 @@ void web100_middlebox(int sock, web100_agent* agent, web100_connection* cn, if (k < 0) // general error writing to socket. quit break; } + +#if USE_WEB100 log_println(5, "Finished with web100_middlebox() routine snap-0x%x, " "sndbuff=%x0x", snap, sndbuff); web100_snapshot_free(snap); +#elif USE_TCPE + tcpe_data_free(&data); + log_println(5, "Finished with web10g_middlebox() routine, " + "sndbuff=%x0x", sndbuff); +#endif /* free(sndbuff); */ } @@ -241,17 +390,21 @@ void web100_middlebox(int sock, web100_agent* agent, web100_connection* cn, * Get receiver side Web100 stats and write them to the log file * * @param sock integer socket file descriptor - * @param agent pointer to a web100_agent - * @param cn pointer to a web100_connection - * @param count_vars integer number of web100_variables to get value of + * @param agent pointer to a tcp_stat_agent + * @param cn pointer to a tcp_stat_connection + * @param count_vars integer number of tcp_stat_vars to get value of * */ -void web100_get_data_recv(int sock, web100_agent* agent, web100_connection* cn, - int count_vars) { - int i, ok; - web100_var* var; +void tcp_stat_get_data_recv(int sock, tcp_stat_agent* agent, + tcp_stat_connection cn, int count_vars) { +#if USE_WEB100 + web100_var* var = NULL; + web100_group* group = NULL; +#elif USE_TCPE + tcpe_data* data = NULL; +#endif + int i; char buf[32], line[256], *ctime(); - web100_group* group; FILE * fp; time_t tt; @@ -263,18 +416,24 @@ void web100_get_data_recv(int sock, web100_agent* agent, web100_connection* cn, fprintf(fp, "%15.15s;", ctime(&tt) + 4); // get values for group, var of IP Address of the Remote host's side of // connection + +#if USE_WEB100 web100_agent_find_var_and_group(agent, "RemAddress", &group, &var); web100_raw_read(var, cn, buf); snprintf(line, sizeof(line), "%s;", web100_value_to_text(web100_get_var_type(var), buf)); +#elif USE_TCPE + web10g_get_remote_addr(agent, cn, buf, sizeof(buf)); + snprintf(line, sizeof(line), "%s;", buf); +#endif // write remote address to log file if (fp) fprintf(fp, "%s", line); - ok = 1; - // get values for other web100 variables and write to the log file +#if USE_WEB100 + int ok = 1; for (i = 0; i < count_vars; i++) { if ((web100_agent_find_var_and_group(agent, web_vars[i].name, &group, &var)) != WEB100_ERR_SUCCESS) { @@ -305,6 +464,48 @@ void web100_get_data_recv(int sock, web100_agent* agent, web100_connection* cn, } ok = 1; } +#elif USE_TCPE + tcpe_data_new(&data); + tcpe_read_vars(data, cn, agent) ; + + //Loop through all the web10g variables and write to file/log_print them + for(i = 0; i < ARRAYSIZE(data->val); i++) { + if (data->val[i].mask) continue; + + switch(tcpe_var_array[i].type) { + case TCPE_UNSIGNED64: + if (fp) + fprintf(fp, "%" PRIu64 ";", data->val[i].uv64 ); + log_println(9, "%s: %" PRIu64, + tcpe_var_array[i].name, data->val[i].uv64); + break; + case TCPE_UNSIGNED32: + if (fp) + fprintf(fp, "%u;", data->val[i].uv32 ); + log_println(9, "%s: %u", tcpe_var_array[i].name, data->val[i].uv32); + break; + case TCPE_SIGNED32: + if (fp) + fprintf(fp, "%d;", data->val[i].sv32 ); + log_println(9, "%s: %d", tcpe_var_array[i].name, data->val[i].sv32); + break; + case TCPE_UNSIGNED16: + if (fp) + fprintf(fp, "%" PRIu16 ";", data->val[i].uv16 ); + log_println(9, "%s: %" PRIu16, + tcpe_var_array[i].name, data->val[i].uv16); + break; + case TCPE_UNSIGNED8: + if (fp) + fprintf(fp, "%" PRIu8 ";", data->val[i].uv8 ); + log_println(9, "%s: %" PRIu8, tcpe_var_array[i].name, data->val[i].uv8); + break; + default: + break; + } + } + tcpe_data_free(&data); +#endif // close file pointers after web100 variables have been fetched if (fp) { @@ -313,23 +514,32 @@ void web100_get_data_recv(int sock, web100_agent* agent, web100_connection* cn, } } +#if USE_TCPE +// Persistent storage needed. +static tcpe_data* dataDumpSave; +static int X_SndBuf; +static int X_RcvBuf; +#endif + /** * Collect Web100 stats from a snapshot and transmit to a receiver. * The transmission is done using a TES_MSG type message and sent to * client reachable via the input parameter socket FD. * - * @param snap pointer to a web100_snapshot taken earlier + * @param snap pointer to a tcp_stat_snapshot taken earlier * @param ctlsock integer socket file descriptor indicating data recipient - * @param agent pointer to a web100_agent - * @param count_vars integer number of web100_variables to get value of + * @param agent pointer to a tcp_stat_agent + * @param count_vars integer number of tcp_stat_variables to get value of * */ -int web100_get_data(web100_snapshot* snap, int ctlsock, web100_agent* agent, - int count_vars) { +int tcp_stat_get_data(tcp_stat_snap* snap, int testsock, int ctlsock, + tcp_stat_agent* agent, int count_vars) { + char line[256]; +#if USE_WEB100 int i; web100_var* var; - char buf[32], line[256]; web100_group* group; + char buf[32]; assert(snap); assert(agent); @@ -371,8 +581,169 @@ int web100_get_data(web100_snapshot* snap, int ctlsock, web100_agent* agent, } log_println(6, "S2C test - Send web100 data to client pid=%d", getpid()); return (0); +#elif USE_TCPE + int j; + unsigned int m; + struct tcpe_val val; + + m = sizeof(X_RcvBuf); + getsockopt(testsock, SOL_SOCKET, SO_RCVBUF, (void *)&X_RcvBuf, &m); + m = sizeof(X_SndBuf); + getsockopt(testsock, SOL_SOCKET, SO_SNDBUF, (void *)&X_SndBuf, &m); + + assert(snap); + + tcpe_data_new(&dataDumpSave); + + for(j = 0; j < ARRAYSIZE(snap->val); j++) { + dataDumpSave->val[j].mask = snap->val[j].mask; + dataDumpSave->val[j].uv64 = snap->val[j].uv64; + if (snap->val[j].mask) continue; + + switch(tcpe_var_array[j].type) { + case TCPE_UNSIGNED64: + snprintf(line, sizeof(line), "%s: %" PRIu64 "\n", + tcpe_var_array[j].name, snap->val[j].uv64); + break; + case TCPE_UNSIGNED32: + snprintf(line, sizeof(line), "%s: %u\n", + tcpe_var_array[j].name, snap->val[j].uv32 ); + break; + case TCPE_SIGNED32: + snprintf(line, sizeof(line), "%s: %d\n", + tcpe_var_array[j].name, snap->val[j].sv32 ); + break; + case TCPE_UNSIGNED16: + snprintf(line, sizeof(line), "%s: %" PRIu16 "\n", + tcpe_var_array[j].name, snap->val[j].uv16); + case TCPE_UNSIGNED8: + snprintf(line, sizeof(line), "%s: %" PRIu8 "\n", + tcpe_var_array[j].name, snap->val[j].uv8); + break; + default: + break; + } + send_msg(ctlsock, TEST_MSG, line, strlen(line)); + log_print(9, "%s", line); + } + + /* This is the list of changed variable names that the client tries to read. + * Web100 -> Web10g + * ECNEnabled -> ECN + * NagleEnabled -> Nagle + * SACKEnabled -> WillSendSACK & WillUseSACK + * TimestampsEnabled -> TimeStamps + * PktsRetrans -> SegsRetrans + * X_Rcvbuf -> Not in web10g doesn't acutally use it so just leave it out + * DataPktsOut -> DataSegsOut + * AckPktsOut -> Depreciated + * MaxCwnd -> MaxSsCwnd MaxCaCwnd + * SndLimTimeSender -> SndLimTimeSnd + * DataBytesOut -> DataOctetsOut + * AckPktsIn -> Depreciated + * SndLimTransSender -> SndLimTransSnd + * PktsOut -> SegsOut + * CongestionSignals -> CongSignals + * RcvWinScale -> Same as WinScaleSent if WinScaleSent != -1 + */ + static const char* msg = "-~~~Web100_old_var_names~~~-: 1\n"; + send_msg(ctlsock, TEST_MSG, msg, strlen(msg)); + uint32_t temp; + + /* ECNEnabled -> ECN */ + val.uv64 = 0; + web10g_find_val(snap, "ECN", &val); + snprintf(line, sizeof(line), "ECNEnabled: %d\n", val.sv32); + send_msg(ctlsock, TEST_MSG, line, strlen(line)); + + /* NagleEnabled -> Nagle */ + val.uv64 = 0; + web10g_find_val(snap, "Nagle", &val); + snprintf(line, sizeof(line), "NagleEnabled: %d\n", val.sv32); + send_msg(ctlsock, TEST_MSG, line, strlen(line)); + + /* SACKEnabled -> WillUseSACK & WillSendSACK + * keep this in line with web100 for now i.e. 0 == off 1 == on */ + val.uv64 = 0; + web10g_find_val(snap, "WillUseSACK", &val); + snprintf(line, sizeof(line), "SACKEnabled: %d\n", (val.sv32 == 1) ? 1 : 0); + send_msg(ctlsock, TEST_MSG, line, strlen(line)); + + /* TimestampsEnabled -> TimeStamps */ + val.uv64 = 0; + web10g_find_val(snap, "TimeStamps", &val); + snprintf(line, sizeof(line), "TimestampsEnabled: %d\n", val.sv32); + send_msg(ctlsock, TEST_MSG, line, strlen(line)); + + /* PktsRetrans -> SegsRetrans */ + val.uv64 = 0; + web10g_find_val(snap, "SegsRetrans", &val); + snprintf(line, sizeof(line), "PktsRetrans: %u\n", val.uv32); + send_msg(ctlsock, TEST_MSG, line, strlen(line)); + + /* DataPktsOut -> DataSegsOut */ + val.uv64 = 0; + web10g_find_val(snap, "DataSegsOut", &val); + snprintf(line, sizeof(line), "DataPktsOut: %u\n", val.uv32); + send_msg(ctlsock, TEST_MSG, line, strlen(line)); + + /* MaxCwnd -> MaxSsCwnd MaxCaCwnd */ + val.uv64 = 0; + web10g_find_val(snap, "MaxSsCwnd", &val); + temp = val.uv32; + val.uv64 = 0; + web10g_find_val(snap, "MaxCaCwnd", &val); + temp = MAX(temp, val.uv32); + snprintf(line, sizeof(line), "DataPktsOut: %u\n", temp); + send_msg(ctlsock, TEST_MSG, line, strlen(line)); + + /* SndLimTimeSender -> SndLimTimeSnd */ + val.uv64 = 0; + web10g_find_val(snap, "SndLimTimeSnd", &val); + snprintf(line, sizeof(line), "SndLimTimeSender: %u\n", val.uv32); + send_msg(ctlsock, TEST_MSG, line, strlen(line)); + + /* DataBytesOut -> DataOctetsOut */ + val.uv64 = 0; + web10g_find_val(snap, "DataOctetsOut", &val); + snprintf(line, sizeof(line), "DataBytesOut: %u\n", val.uv32); + send_msg(ctlsock, TEST_MSG, line, strlen(line)); + + /* SndLimTransSender -> SndLimTransSnd */ + val.uv64 = 0; + web10g_find_val(snap, "SndLimTransSnd", &val); + snprintf(line, sizeof(line), "SndLimTransSender: %u\n", val.uv32); + send_msg(ctlsock, TEST_MSG, line, strlen(line)); + + /* PktsOut -> SegsOut */ + val.uv64 = 0; + web10g_find_val(snap, "SegsOut", &val); + snprintf(line, sizeof(line), "PktsOut: %u\n", val.uv32); + send_msg(ctlsock, TEST_MSG, line, strlen(line)); + + /* CongestionSignals -> CongSignals */ + val.uv64 = 0; + web10g_find_val(snap, "CongSignals", &val); + snprintf(line, sizeof(line), "CongestionSignals: %u\n", val.uv32); + send_msg(ctlsock, TEST_MSG, line, strlen(line)); + + /* RcvWinScale -> Same as WinScaleSent if WinScaleSent != -1 */ + val.uv64 = 0; + web10g_find_val(snap, "WinScaleSent", &val); + if(val.sv32 == -1) + snprintf(line, sizeof(line), "RcvWinScale: %u\n", 0); + else + snprintf(line, sizeof(line), "RcvWinScale: %d\n", val.sv32); + send_msg(ctlsock, TEST_MSG, line, strlen(line)); + + send_msg(ctlsock, TEST_MSG, msg, strlen(msg)); + + log_println(6, "S2C test - Send web100 data to client pid=%d", getpid()); + return 0; +#endif } +#if USE_WEB100 /** * Calculate Web100 based Round-Trip Time (RTT) value. * @@ -417,6 +788,7 @@ int web100_rtt(int sock, web100_agent* agent, web100_connection* cn) { sum = atoi(web100_value_to_text(web100_get_var_type(var), buf)); return (sum / count); } +#endif /** * Check if the "Auto Tune Send Buffer" and "Auto Tune Receive Buffer" options @@ -435,7 +807,8 @@ int web100_rtt(int sock, web100_agent* agent, web100_connection* cn) { * 23 cannot read the value of the X_SBufMode or X_RBufMode web100_variable. */ -int web100_autotune(int sock, web100_agent* agent, web100_connection* cn) { +int tcp_stat_autotune(int sock, tcp_stat_agent* agent, tcp_stat_connection cn) { +#if USE_WEB100 web100_var* var; char buf[32]; web100_group* group; @@ -476,8 +849,13 @@ int web100_autotune(int sock, web100_agent* agent, web100_connection* cn) { if (i == 0) j |= 0x02; return (j); +#elif USE_TCPE + // Disabled in web10g. + return 0x03; +#endif } +#if USE_WEB100 /** * Check if the "Auto Tune Send Buffer" and "Auto Tune Receive Buffer" options * are enabled. If not, scale the Send window or receive window sizes based on the @@ -501,8 +879,8 @@ int web100_autotune(int sock, web100_agent* agent, web100_connection* cn) { * 35 - cannot read value of RcvWinScale web100 variable. * */ -int web100_setbuff(int sock, web100_agent* agent, web100_connection* cn, - int autotune) { +int tcp_stat_setbuff(int sock, tcp_stat_agent* agent, tcp_stat_connection cn, + int autotune) { web100_var* var; char buf[32]; web100_group* group; @@ -566,114 +944,67 @@ int web100_setbuff(int sock, web100_agent* agent, web100_connection* cn, return (0); } +#endif /** * @param sock integer socket file descriptor indicating data recipient - * @param pointers to local copies of web100 variables + * @param tcp_vars to local copies of tcp_stat variables * @return integer 0 - * - * */ -int web100_logvars(int *Timeouts, int *SumRTT, int *CountRTT, int *PktsRetrans, - int *FastRetran, int *DataPktsOut, int *AckPktsOut, - int *CurrentMSS, int *DupAcksIn, int *AckPktsIn, - int *MaxRwinRcvd, int *Sndbuf, int *CurrentCwnd, - int *SndLimTimeRwin, int *SndLimTimeCwnd, - int *SndLimTimeSender, int *DataBytesOut, - int *SndLimTransRwin, int *SndLimTransCwnd, - int *SndLimTransSender, int *MaxSsthresh, int *CurrentRTO, - int *CurrentRwinRcvd, int *MaxCwnd, int *CongestionSignals, - int *PktsOut, int *MinRTT, int count_vars, int *RcvWinScale, - int *SndWinScale, int *CongAvoid, int *CongestionOverCount, - int *MaxRTT, int *OtherReductions, int *CurTimeoutCount, - int *AbruptTimeouts, int *SendStall, int *SlowStart, - int *SubsequentTimeouts, int *ThruBytesAcked) { - int i; +int tcp_stat_logvars(struct tcp_vars* vars, int count_vars) { +#if USE_WEB100 + int a, b; + for (a = 0; a < sizeof(struct tcp_vars) / sizeof(tcp_stat_var); ++a) { + const char* web100_name = tcp_names[a].web100_name; + if (web100_name == NULL) + continue; + + for (b = 0; b < count_vars; b++) { + if (strcmp(web_vars[b].name, web100_name) == 0) { + tcp_stat_var* var = ((tcp_stat_var*) vars) + a; + *var = atoi(web_vars[b].value); + log_println(5, "Found %s : %i", web100_name, *var); + break; + } + } + if (b == count_vars) { + log_println(1, "WARNING: Failed to find Web100 var %s", web100_name); + } + } +#elif USE_TCPE + int a, b; + assert(dataDumpSave); + for (a = 0; a < (sizeof(struct tcp_vars) / sizeof(tcp_stat_var)); ++a) { + const char* web10g_name = tcp_names[a].web10g_name; + if (web10g_name == NULL) + continue; - for (i = 0; i <= count_vars; i++) { - if (strcmp(web_vars[i].name, "Timeouts") == 0) - *Timeouts = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "SumRTT") == 0) - *SumRTT = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "CountRTT") == 0) - *CountRTT = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "PktsRetrans") == 0) - *PktsRetrans = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "FastRetran") == 0) - *FastRetran = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "DataPktsOut") == 0) - *DataPktsOut = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "AckPktsOut") == 0) - *AckPktsOut = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "CurMSS") == 0) - *CurrentMSS = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "DupAcksIn") == 0) - *DupAcksIn = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "AckPktsIn") == 0) - *AckPktsIn = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "MaxRwinRcvd") == 0) - *MaxRwinRcvd = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "X_Sndbuf") == 0) - *Sndbuf = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "CurCwnd") == 0) - *CurrentCwnd = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "MaxCwnd") == 0) - *MaxCwnd = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "SndLimTimeRwin") == 0) - *SndLimTimeRwin = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "SndLimTimeCwnd") == 0) - *SndLimTimeCwnd = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "SndLimTimeSender") == 0) - *SndLimTimeSender = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "DataBytesOut") == 0) - *DataBytesOut = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "SndLimTransRwin") == 0) - *SndLimTransRwin = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "SndLimTransCwnd") == 0) - *SndLimTransCwnd = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "SndLimTransSender") == 0) - *SndLimTransSender = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "MaxSsthresh") == 0) - *MaxSsthresh = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "CurRTO") == 0) - *CurrentRTO = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "CurRwinRcvd") == 0) - *CurrentRwinRcvd = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "CongestionSignals") == 0) - *CongestionSignals = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "PktsOut") == 0) - *PktsOut = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "MinRTT") == 0) - *MinRTT = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "RcvWinScale") == 0) - *RcvWinScale = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "SndWinScale") == 0) - *SndWinScale = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "CongAvoid") == 0) - *CongAvoid = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "CongestionOverCount") == 0) - *CongestionOverCount = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "MaxRTT") == 0) - *MaxRTT = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "OtherReductions") == 0) - *OtherReductions = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "CurTimeoutCount") == 0) - *CurTimeoutCount = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "AbruptTimeouts") == 0) - *AbruptTimeouts = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "SendStall") == 0) - *SendStall = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "SlowStart") == 0) - *SlowStart = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "SubsequentTimeouts") == 0) - *SubsequentTimeouts = atoi(web_vars[i].value); - else if (strcmp(web_vars[i].name, "ThruBytesAcked") == 0) - *ThruBytesAcked = atoi(web_vars[i].value); + for (b = 0; b < ARRAYSIZE(dataDumpSave->val); ++b) { + if (dataDumpSave->val[b].mask) + continue; + if (strcmp(tcpe_var_array[b].name, web10g_name) == 0) { + tcp_stat_var* var = ((tcp_stat_var*) vars) + a; + *var = dataDumpSave->val[b].uv32; + log_println(5, "Found %s : %i", web10g_name, *var); + break; + } + } + if (b == ARRAYSIZE(dataDumpSave->val)) { + log_println(1, "WARNING: Failed to find Web10g var %s", web10g_name); + } } - return (0); + vars->AckPktsOut = 0; + vars->Sndbuf = X_SndBuf; + vars->MaxCwnd = MAX(vars->MaxSsCwnd, vars->MaxCaCwnd); + + tcpe_data_free(&dataDumpSave); + dataDumpSave = NULL; +#endif + return 0; } +#if USE_WEB100 /** * Routine to read snaplog file and determine the number of times the * congestion window is reduced. @@ -751,7 +1082,9 @@ int CwndDecrease(web100_agent* agent, char* logname, u_int32_t *dec_cnt, *inc_cnt, *dec_cnt, *same_cnt); return (0); } +#endif // TODO: Implement in web10g when logging is doable. +#if USE_WEB100 /** * Generate TCP/IP checksum for our packet * @@ -939,3 +1272,4 @@ int KillHung(void) { return (-1); return (0); } +#endif diff --git a/src/web100clt.c b/src/web100clt.c index f2e302c..42cbfd1 100644 --- a/src/web100clt.c +++ b/src/web100clt.c @@ -1,5 +1,7 @@ #include "../config.h" +#include <arpa/inet.h> +#include <assert.h> #include <ctype.h> #include <errno.h> #include <getopt.h> @@ -237,6 +239,26 @@ void testResults(char tests, char *testresult_str, char* host) { } /** + * Get a string representation of an ip address. + * + * @param addr A sockaddr structure which contains the address + * @param buf A buffer to fill with the ip address as a string + * @param len The length of buf. + */ +static void addr2a(struct sockaddr_storage * addr,char * buf, int len){ + if (((struct sockaddr *)addr)->sa_family == AF_INET) { + inet_ntop(AF_INET, &(((struct sockaddr_in *)addr)->sin_addr), + buf, len); + } +#ifdef AF_INET6 + else if (((struct sockaddr *)addr)->sa_family == AF_INET6) { + inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)addr)->sin6_addr), + buf, len); + } +#endif +} + +/** * This routine decodes the middlebox test results. The data is returned * from the server in a specific order. This routine pulls the string apart * and puts the values into the proper variable. It then compares the values @@ -247,14 +269,14 @@ void testResults(char tests, char *testresult_str, char* host) { * Client then adds * Server IP; Client IP. * @param midresult_str String containing test results - * @param local_addr Client IP address - * @param peer_addr Server IP address + * @param cltsock Used to get address information */ -void middleboxResults(char *midresult_str, I2Addr local_addr, - I2Addr peer_addr) { +void middleboxResults(char *midresult_str, int cltsock) { char ssip[64], scip[64], *str; char csip[64], ccip[64]; + struct sockaddr_storage addr; + socklen_t addr_size = sizeof(addr); int mss; size_t tmpLen; @@ -274,10 +296,19 @@ void middleboxResults(char *midresult_str, I2Addr local_addr, memset(ccip, 0, 64); tmpLen = 63; - I2AddrNodeName(local_addr, ccip, &tmpLen); + if (getsockname(cltsock, (struct sockaddr*) &addr, &addr_size) == -1) { + perror("Middlebox - getsockname() failed"); + } else { + addr2a(&addr, ccip, tmpLen); + } memset(csip, 0, 64); tmpLen = 63; - I2AddrNodeName(peer_addr, csip, &tmpLen); + addr_size = sizeof(addr); + if (getpeername(cltsock, (struct sockaddr*) &addr, &addr_size) == -1) { + perror("Middlebox - getpeername() failed"); + } else { + addr2a(&addr, csip, tmpLen); + } // Check if MSS modification is happening check_MSS_modification(TimestampsEnabled, &mss); @@ -486,7 +517,6 @@ int main(int argc, char *argv[]) { int testId; // test ID received from server // addresses.. I2Addr server_addr = NULL; - I2Addr local_addr = NULL, remote_addr = NULL; char* ptr; #ifdef AF_INET6 #define GETOPT_LONG_INET6(x) "46"x @@ -854,19 +884,17 @@ int main(int argc, char *argv[]) { log_println(6, "resultstr = '%s'", resultstr); } - local_addr = I2AddrByLocalSockFD(get_errhandle(), ctlSocket, False); - remote_addr = I2AddrBySockFD(get_errhandle(), ctlSocket, False); - I2AddrFree(server_addr); - strlcpy(varstr, resultstr, sizeof(varstr)); // print test results testResults(tests, resultstr, host); // print middlebox test results if (tests & TEST_MID) { - middleboxResults(mid_resultstr, local_addr, remote_addr); + middleboxResults(mid_resultstr, ctlSocket); } + I2AddrFree(server_addr); + // print extra information collected from web100 variables if ((tests & TEST_S2C) && (msglvl > 1)) printVariables(varstr); diff --git a/src/web100srv.c b/src/web100srv.c index 0f63b85..0d0670f 100644 --- a/src/web100srv.c +++ b/src/web100srv.c @@ -468,15 +468,19 @@ void cleanup(int signo) { } exit(0); case SIGUSR1: + // Used exclusively by C2S to interrupt pcap capture. log_println(6, "DEBUG, caught SIGUSR1, setting sig1 flag to force exit"); + force_breakloop(); sig1 = 1; /* check_signal_flags(); */ break; case SIGUSR2: + // Used exclusively by S2C to interrupt pcap capture. log_println(6, "DEBUG, caught SIGUSR2, setting sig2 flag to force exit"); + force_breakloop(); sig2 = 1; /* check_signal_flags(); */ break; @@ -552,7 +556,7 @@ void cleanup(int signo) { case SIGHUP: /* Initialize Web100 structures */ - count_vars = web100_init(VarFileName); + count_vars = tcp_stat_init(VarFileName); /* The administrator view automatically generates a usage page for the * NDT server. This page is then accessable to the general public. @@ -628,8 +632,13 @@ static void LoadConfig(char* name, char **lbuf, size_t *lbuf_max) { set_debuglvl(atoi(val)); continue; } else if (strncasecmp(key, "variable_file", 6) == 0) { + +#if USE_WEB100 snprintf(wvfn, sizeof(wvfn), "%s", val); VarFileName = wvfn; +#elif USE_TCPE + log_println(0, "Web10G does not require variable file. Ignoring"); +#endif continue; } else if (strncasecmp(key, "log_file", 3) == 0) { snprintf(lgfn, sizeof(lgfn), "%s", val); @@ -834,12 +843,6 @@ void * zombieWorker(void *head_ptr) { recv_msg(tmp_ptr->ctlsockfd, &msgType, buff, &msgLen); tmp_ptr = tmp_ptr->next; pre_ptr = pre_ptr->next; - /* - if ((sig1 > 0) || (sig2 > 0)) - check_signal_flags(); - if (sig17 > 0) - child_sig(0); - */ break; case -1: // some error status if (errno == EINTR) { @@ -893,14 +896,15 @@ cputimeWorker(void* arg) { /** * Run all tests, process results, record them into relevant log files * - * @param agent pointer to web_100 agent + * @param agent pointer to tcp_stat agent * @param ctlsockfd socket used for server->client communication * @param testopt TestOptions * * @param test_suite pointer to string indicating tests to be run * */ -int run_test(web100_agent* agent, int ctlsockfd, TestOptions* testopt, +int run_test(tcp_stat_agent* agent, int ctlsockfd, TestOptions* testopt, char *test_suite) { + tcp_stat_connection conn = -1; char date[32]; // date indicator char spds[4][256]; // speed "bin" array containing counters for speeds char logstr1[4096], logstr2[1024]; // log @@ -908,18 +912,8 @@ int run_test(web100_agent* agent, int ctlsockfd, TestOptions* testopt, char isoTime[64]; // int n; // temporary iterator variable --// commented out -> calc_linkspeed - int Timeouts, SumRTT, CountRTT, PktsRetrans, FastRetran, DataPktsOut; - int AckPktsOut, CurrentMSS, DupAcksIn, AckPktsIn, MaxRwinRcvd, Sndbuf; - int CurrentCwnd, SndLimTimeRwin, SndLimTimeCwnd, SndLimTimeSender, - DataBytesOut; - int SndLimTransRwin, SndLimTransCwnd, SndLimTransSender, MaxSsthresh; - int CurrentRTO, CurrentRwinRcvd, MaxCwnd, CongestionSignals, PktsOut, - MinRTT; - int CongAvoid, CongestionOverCount, MaxRTT, OtherReductions, - CurTimeoutCount = 0; - int AbruptTimeouts, SendStall, SlowStart, SubsequentTimeouts, - ThruBytesAcked; - int RcvWinScale, SndWinScale; + struct tcp_vars vars; + int link = CANNOT_DETERMINE_LINK; // local temporary variable indicative of // link speed. Transmitted but unused at client end , which has a similar // link speed variable @@ -974,8 +968,6 @@ int run_test(web100_agent* agent, int ctlsockfd, TestOptions* testopt, FILE * fp; - web100_connection* conn; - // start with a clean slate of currently running test and direction setCurrentTest(TEST_NONE); log_println(7, "Remote host= %s", get_remotehost()); @@ -991,8 +983,8 @@ int run_test(web100_agent* agent, int ctlsockfd, TestOptions* testopt, spd_index = 0; // obtain web100 connection and check auto-tune status - conn = web100_connection_from_socket(agent, ctlsockfd); - autotune = web100_autotune(ctlsockfd, agent, conn); + conn = tcp_stat_connection_from_socket(agent, ctlsockfd); + autotune = tcp_stat_autotune(ctlsockfd, agent, conn); // client needs to be version compatible. Send current version snprintf(buff, sizeof(buff), "v%s", VERSION); @@ -1086,88 +1078,82 @@ int run_test(web100_agent* agent, int ctlsockfd, TestOptions* testopt, // Get web100 vars // ...determine number of times congestion window has been changed +#if USE_WEB100 if (options.cwndDecrease) { dec_cnt = inc_cnt = same_cnt = 0; CwndDecrease(agent, options.s2c_logname, &dec_cnt, &same_cnt, &inc_cnt); log_println(2, "####### decreases = %d, increases = %d, no change = %d", dec_cnt, inc_cnt, same_cnt); } +#endif // ...other variables - web100_logvars(&Timeouts, &SumRTT, &CountRTT, &PktsRetrans, &FastRetran, - &DataPktsOut, &AckPktsOut, &CurrentMSS, &DupAcksIn, &AckPktsIn, - &MaxRwinRcvd, &Sndbuf, &CurrentCwnd, &SndLimTimeRwin, - &SndLimTimeCwnd, &SndLimTimeSender, &DataBytesOut, - &SndLimTransRwin, &SndLimTransCwnd, &SndLimTransSender, - &MaxSsthresh, &CurrentRTO, &CurrentRwinRcvd, &MaxCwnd, - &CongestionSignals, &PktsOut, &MinRTT, count_vars, - &RcvWinScale, &SndWinScale, &CongAvoid, &CongestionOverCount, - &MaxRTT, &OtherReductions, &CurTimeoutCount, &AbruptTimeouts, - &SendStall, &SlowStart, &SubsequentTimeouts, &ThruBytesAcked); + tcp_stat_logvars(&vars, count_vars); // end getting web100 variable values /* if (rc == 0) { */ // section to calculate duplex mismatch // Calculate average round trip time and convert to seconds - rttsec = calc_avg_rtt(SumRTT, CountRTT, &avgrtt); + rttsec = calc_avg_rtt(vars.SumRTT, vars.CountRTT, &avgrtt); // Calculate packet loss - packetloss_s2c = calc_packetloss(CongestionSignals, PktsOut, + packetloss_s2c = calc_packetloss(vars.CongestionSignals, vars.PktsOut, c2s_linkspeed_data); // Calculate ratio of packets arriving out of order - oo_order = calc_packets_outoforder(DupAcksIn, AckPktsIn); + oo_order = calc_packets_outoforder(vars.DupAcksIn, vars.AckPktsIn); // calculate theoretical maximum goodput in bits - bw_theortcl = calc_max_theoretical_throughput(CurrentMSS, rttsec, + bw_theortcl = calc_max_theoretical_throughput(vars.CurrentMSS, rttsec, packetloss_s2c); // get window sizes - calc_window_sizes(&SndWinScale, &RcvWinScale, Sndbuf, MaxRwinRcvd, - MaxCwnd, &rwin, &swin, &cwin); + calc_window_sizes(&vars.SndWinScale, &vars.RcvWinScale, vars.Sndbuf, + vars.MaxRwinRcvd, vars.MaxCwnd, &rwin, &swin, &cwin); // Total test time - totaltime = calc_totaltesttime(SndLimTimeRwin, SndLimTimeCwnd, - SndLimTimeSender); + totaltime = calc_totaltesttime(vars.SndLimTimeRwin, vars.SndLimTimeCwnd, + vars.SndLimTimeSender); // time spent being send-limited due to client's recv window - rwintime = calc_sendlimited_rcvrfault(SndLimTimeRwin, totaltime); + rwintime = calc_sendlimited_rcvrfault(vars.SndLimTimeRwin, totaltime); // time spent in being send-limited due to congestion window - cwndtime = calc_sendlimited_cong(SndLimTimeCwnd, totaltime); + cwndtime = calc_sendlimited_cong(vars.SndLimTimeCwnd, totaltime); // time spent in being send-limited due to own fault - sendtime = calc_sendlimited_sndrfault(SndLimTimeSender, totaltime); + sendtime = calc_sendlimited_sndrfault(vars.SndLimTimeSender, totaltime); timesec = totaltime / MEGA; // total time in microsecs // get fraction of total test time waiting for packets to arrive - RTOidle = calc_RTOIdle(Timeouts, CurrentRTO, timesec); + RTOidle = calc_RTOIdle(vars.Timeouts, vars.CurrentRTO, timesec); // get timeout, retransmission, acks and dup acks ratios. - tmoutsratio = (double) Timeouts / PktsOut; - rtranratio = (double) PktsRetrans / PktsOut; - acksratio = (double) AckPktsIn / PktsOut; - dackratio = (double) DupAcksIn / (double) AckPktsIn; + tmoutsratio = (double) vars.Timeouts / vars.PktsOut; + rtranratio = (double) vars.PktsRetrans / vars.PktsOut; + acksratio = (double) vars.AckPktsIn / vars.PktsOut; + dackratio = (double) vars.DupAcksIn / (double) vars.AckPktsIn; // get actual throughput in Mbps (totaltime is in microseconds) - realthruput = calc_real_throughput(DataBytesOut, totaltime); + realthruput = calc_real_throughput(vars.DataBytesOut, totaltime); // total time spent waiting - waitsec = cal_totalwaittime(CurrentRTO, Timeouts); + waitsec = cal_totalwaittime(vars.CurrentRTO, vars.Timeouts); log_println(2, "CWND limited test = %0.2f while unlimited = %0.2f", s2c2spd, s2cspd); // Is thruput measured with limited cwnd(midbox test) > as reported S->C test - if (is_limited_cwnd_throughput_better(s2c2spd, s2cspd) - && isNotMultipleTestMode(multiple)) + if (is_limited_cwnd_throughput_better(s2c2spd, s2cspd) && + isNotMultipleTestMode(multiple)) { log_println( 2, "Better throughput when CWND is limited, may be duplex mismatch"); - else + } else { log_println(2, "Better throughput without CWND limits - normal operation"); + } // remove the following line when the new detection code is ready for release // retaining old comment above @@ -1175,8 +1161,8 @@ int run_test(web100_agent* agent, int ctlsockfd, TestOptions* testopt, old_mismatch = 1; if (old_mismatch == 1) { - if (detect_duplexmismatch(cwndtime, bw_theortcl, PktsRetrans, timesec, - MaxSsthresh, RTOidle, link, s2cspd, s2c2spd, + if (detect_duplexmismatch(cwndtime, bw_theortcl, vars.PktsRetrans, timesec, + vars.MaxSsthresh, RTOidle, link, s2cspd, s2c2spd, multiple)) { if (is_c2s_throughputbetter(c2sspd, s2cspd)) { // also, S->C throughput is lesser than C->S throughput @@ -1213,7 +1199,7 @@ int run_test(web100_agent* agent, int ctlsockfd, TestOptions* testopt, // Faulty hardware link heuristic. if (detect_faultyhardwarelink(packetloss_s2c, cwndtime, timesec, - MaxSsthresh)) + vars.MaxSsthresh)) bad_cable = POSSIBLE_BAD_CABLE; // test for Ethernet link (assume Fast E.) @@ -1222,14 +1208,17 @@ int run_test(web100_agent* agent, int ctlsockfd, TestOptions* testopt, link = LINK_ETHERNET; // test for wireless link - if (detect_wirelesslink(sendtime, realthruput, bw_theortcl, SndLimTransRwin, - SndLimTransCwnd, rwintime, link)) + if (detect_wirelesslink(sendtime, realthruput, bw_theortcl, + vars.SndLimTransRwin, vars.SndLimTransCwnd, rwintime, + link)) { link = LINK_WIRELESS; + } // test for DSL/Cable modem link - if (detect_DSLCablelink(SndLimTimeSender, SndLimTransSender, realthruput, - bw_theortcl, link)) + if (detect_DSLCablelink(vars.SndLimTimeSender, vars.SndLimTransSender, + realthruput, bw_theortcl, link)) { link = LINK_DSLORCABLE; + } // full/half link duplex setting heuristic: // receiver-limited- time > 95%, @@ -1238,7 +1227,7 @@ int run_test(web100_agent* agent, int ctlsockfd, TestOptions* testopt, // ...and the number of transitions into the 'Sender Limited' state is // greater than 30 per second - if (detect_halfduplex(rwintime, SndLimTransRwin, SndLimTransSender, + if (detect_halfduplex(rwintime, vars.SndLimTransRwin, vars.SndLimTransSender, timesec)) half_duplex = POSSIBLE_HALF_DUPLEX; @@ -1272,7 +1261,7 @@ int run_test(web100_agent* agent, int ctlsockfd, TestOptions* testopt, snprintf(buff, sizeof(buff), "cwin: %0.4f\nrttsec: %0.6f\nSndbuf: %d\naspd: %0.5f\n" - "CWND-Limited: %0.2f\n", cwin, rttsec, Sndbuf, aspd, s2c2spd); + "CWND-Limited: %0.2f\n", cwin, rttsec, vars.Sndbuf, aspd, s2c2spd); send_msg(ctlsockfd, MSG_RESULTS, buff, strlen(buff)); snprintf(buff, sizeof(buff), @@ -1295,15 +1284,17 @@ int run_test(web100_agent* agent, int ctlsockfd, TestOptions* testopt, memset(tmpstr, 0, sizeof(tmpstr)); snprintf(tmpstr, sizeof(tmpstr), "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,", - (int) s2c2spd, (int) s2cspd, (int) c2sspd, Timeouts, SumRTT, - CountRTT, PktsRetrans, FastRetran, DataPktsOut, AckPktsOut, - CurrentMSS, DupAcksIn, AckPktsIn); + (int) s2c2spd, (int) s2cspd, (int) c2sspd, vars.Timeouts, + vars.SumRTT, vars.CountRTT, vars.PktsRetrans, vars.FastRetran, + vars.DataPktsOut, vars.AckPktsOut, vars.CurrentMSS, vars.DupAcksIn, + vars.AckPktsIn); memcpy(meta.summary, tmpstr, strlen(tmpstr)); memset(tmpstr, 0, sizeof(tmpstr)); snprintf(tmpstr, sizeof(tmpstr), "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,", - MaxRwinRcvd, Sndbuf, MaxCwnd, SndLimTimeRwin, SndLimTimeCwnd, - SndLimTimeSender, DataBytesOut, SndLimTransRwin, SndLimTransCwnd, - SndLimTransSender, MaxSsthresh, CurrentRTO, CurrentRwinRcvd); + vars.MaxRwinRcvd, vars.Sndbuf, vars.MaxCwnd, vars.SndLimTimeRwin, + vars.SndLimTimeCwnd, vars.SndLimTimeSender, vars.DataBytesOut, + vars.SndLimTransRwin, vars.SndLimTransCwnd, vars.SndLimTransSender, + vars.MaxSsthresh, vars.CurrentRTO, vars.CurrentRwinRcvd); strlcat(meta.summary, tmpstr, sizeof(meta.summary)); memset(tmpstr, 0, sizeof(tmpstr)); @@ -1314,15 +1305,16 @@ int run_test(web100_agent* agent, int ctlsockfd, TestOptions* testopt, memset(tmpstr, 0, sizeof(tmpstr)); snprintf(tmpstr, sizeof(tmpstr), ",%d,%d,%d,%d,%d,%d,%d,%d,%d", c2s_linkspeed_data, c2s_linkspeed_ack, s2c_linkspeed_data, - s2c_linkspeed_ack, CongestionSignals, PktsOut, MinRTT, RcvWinScale, - autotune); + s2c_linkspeed_ack, vars.CongestionSignals, vars.PktsOut, vars.MinRTT, + vars.RcvWinScale, autotune); strlcat(meta.summary, tmpstr, sizeof(meta.summary)); memset(tmpstr, 0, sizeof(tmpstr)); - snprintf(tmpstr, sizeof(tmpstr), ",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", CongAvoid, - CongestionOverCount, MaxRTT, OtherReductions, CurTimeoutCount, - AbruptTimeouts, SendStall, SlowStart, SubsequentTimeouts, - ThruBytesAcked); + snprintf(tmpstr, sizeof(tmpstr), ",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", + vars.CongAvoid, vars.CongestionOverCount, vars.MaxRTT, + vars.OtherReductions, vars.CurTimeoutCount, vars.AbruptTimeouts, + vars.SendStall, vars.SlowStart, vars.SubsequentTimeouts, + vars.ThruBytesAcked); strlcat(meta.summary, tmpstr, sizeof(meta.summary)); memset(tmpstr, 0, sizeof(tmpstr)); @@ -1342,59 +1334,63 @@ int run_test(web100_agent* agent, int ctlsockfd, TestOptions* testopt, snprintf(date, sizeof(date), "%15.15s", ctime(&stime) + 4); fprintf(fp, "%s,", date); fprintf(fp, "%s,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,", rmt_host, - (int) s2c2spd, (int) s2cspd, (int) c2sspd, Timeouts, SumRTT, - CountRTT, PktsRetrans, FastRetran, DataPktsOut, AckPktsOut, - CurrentMSS, DupAcksIn, AckPktsIn); - fprintf(fp, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,", MaxRwinRcvd, - Sndbuf, MaxCwnd, SndLimTimeRwin, SndLimTimeCwnd, - SndLimTimeSender, DataBytesOut, SndLimTransRwin, - SndLimTransCwnd, SndLimTransSender, MaxSsthresh, CurrentRTO, - CurrentRwinRcvd); + (int) s2c2spd, (int) s2cspd, (int) c2sspd, vars.Timeouts, + vars.SumRTT, vars.CountRTT, vars.PktsRetrans, vars.FastRetran, + vars.DataPktsOut, vars.AckPktsOut, vars.CurrentMSS, vars.DupAcksIn, + vars.AckPktsIn); + fprintf(fp, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,", vars.MaxRwinRcvd, + vars.Sndbuf, vars.MaxCwnd, vars.SndLimTimeRwin, vars.SndLimTimeCwnd, + vars.SndLimTimeSender, vars.DataBytesOut, vars.SndLimTransRwin, + vars.SndLimTransCwnd, vars.SndLimTransSender, vars.MaxSsthresh, + vars.CurrentRTO, vars.CurrentRwinRcvd); fprintf(fp, "%d,%d,%d,%d,%d", link, mismatch, bad_cable, half_duplex, congestion); fprintf(fp, ",%d,%d,%d,%d,%d,%d,%d,%d,%d", c2s_linkspeed_data, c2s_linkspeed_ack, s2c_linkspeed_data, s2c_linkspeed_ack, - CongestionSignals, PktsOut, MinRTT, RcvWinScale, autotune); - fprintf(fp, ",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", CongAvoid, - CongestionOverCount, MaxRTT, OtherReductions, CurTimeoutCount, - AbruptTimeouts, SendStall, SlowStart, SubsequentTimeouts, - ThruBytesAcked); + vars.CongestionSignals, vars.PktsOut, vars.MinRTT, vars.RcvWinScale, + autotune); + fprintf(fp, ",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", vars.CongAvoid, + vars.CongestionOverCount, vars.MaxRTT, vars.OtherReductions, + vars.CurTimeoutCount, vars.AbruptTimeouts, vars.SendStall, + vars.SlowStart, vars.SubsequentTimeouts, vars.ThruBytesAcked); fprintf(fp, ",%d,%d,%d\n", peaks.min, peaks.max, peaks.amount); fclose(fp); } db_insert(spds, runave, cputimelog, options.s2c_logname, options.c2s_logname, testName, testPort, date, rmt_host, s2c2spd, - s2cspd, c2sspd, Timeouts, SumRTT, CountRTT, PktsRetrans, FastRetran, - DataPktsOut, AckPktsOut, CurrentMSS, DupAcksIn, AckPktsIn, - MaxRwinRcvd, Sndbuf, MaxCwnd, SndLimTimeRwin, SndLimTimeCwnd, - SndLimTimeSender, DataBytesOut, SndLimTransRwin, SndLimTransCwnd, - SndLimTransSender, MaxSsthresh, CurrentRTO, CurrentRwinRcvd, link, + s2cspd, c2sspd, vars.Timeouts, vars.SumRTT, vars.CountRTT, + vars.PktsRetrans, vars.FastRetran, vars.DataPktsOut, + vars.AckPktsOut, vars.CurrentMSS, vars.DupAcksIn, vars.AckPktsIn, + vars.MaxRwinRcvd, vars.Sndbuf, vars.MaxCwnd, vars.SndLimTimeRwin, + vars.SndLimTimeCwnd, vars.SndLimTimeSender, vars.DataBytesOut, + vars.SndLimTransRwin, vars.SndLimTransCwnd, vars.SndLimTransSender, + vars.MaxSsthresh, vars.CurrentRTO, vars.CurrentRwinRcvd, link, mismatch, bad_cable, half_duplex, congestion, c2s_linkspeed_data, c2s_linkspeed_ack, s2c_linkspeed_data, s2c_linkspeed_ack, - CongestionSignals, PktsOut, MinRTT, RcvWinScale, autotune, - CongAvoid, CongestionOverCount, MaxRTT, OtherReductions, - CurTimeoutCount, AbruptTimeouts, SendStall, SlowStart, - SubsequentTimeouts, ThruBytesAcked, peaks.min, peaks.max, - peaks.amount); + vars.CongestionSignals, vars.PktsOut, vars.MinRTT, vars.RcvWinScale, + autotune, vars.CongAvoid, vars.CongestionOverCount, vars.MaxRTT, + vars.OtherReductions, vars.CurTimeoutCount, vars.AbruptTimeouts, + vars.SendStall, vars.SlowStart, vars.SubsequentTimeouts, + vars.ThruBytesAcked, peaks.min, peaks.max, peaks.amount); if (usesyslog == 1) { snprintf( logstr1, sizeof(logstr1), "client_IP=%s,c2s_spd=%2.0f,s2c_spd=%2.0f,Timeouts=%d,SumRTT=%d," "CountRTT=%d,PktsRetrans=%d,FastRetran=%d,DataPktsOut=%d,AckPktsOut=%d," "CurrentMSS=%d,DupAcksIn=%d,AckPktsIn=%d,", - rmt_host, c2sspd, s2cspd, Timeouts, SumRTT, CountRTT, - PktsRetrans, FastRetran, DataPktsOut, AckPktsOut, CurrentMSS, - DupAcksIn, AckPktsIn); + rmt_host, c2sspd, s2cspd, vars.Timeouts, vars.SumRTT, vars.CountRTT, + vars.PktsRetrans, vars.FastRetran, vars.DataPktsOut, vars.AckPktsOut, + vars.CurrentMSS, vars.DupAcksIn, vars.AckPktsIn); snprintf( logstr2, sizeof(logstr2), "MaxRwinRcvd=%d,Sndbuf=%d,MaxCwnd=%d,SndLimTimeRwin=%d," "SndLimTimeCwnd=%d,SndLimTimeSender=%d,DataBytesOut=%d," "SndLimTransRwin=%d,SndLimTransCwnd=%d,SndLimTransSender=%d," "MaxSsthresh=%d,CurrentRTO=%d,CurrentRwinRcvd=%d,", - MaxRwinRcvd, Sndbuf, MaxCwnd, SndLimTimeRwin, SndLimTimeCwnd, - SndLimTimeSender, DataBytesOut, SndLimTransRwin, - SndLimTransCwnd, SndLimTransSender, MaxSsthresh, CurrentRTO, - CurrentRwinRcvd); + vars.MaxRwinRcvd, vars.Sndbuf, vars.MaxCwnd, vars.SndLimTimeRwin, + vars.SndLimTimeCwnd, vars.SndLimTimeSender, vars.DataBytesOut, + vars.SndLimTransRwin, vars.SndLimTransCwnd, vars.SndLimTransSender, + vars.MaxSsthresh, vars.CurrentRTO, vars.CurrentRwinRcvd); strlcat(logstr1, logstr2, sizeof(logstr1)); snprintf( logstr2, sizeof(logstr2), @@ -1403,7 +1399,7 @@ int run_test(web100_agent* agent, int ctlsockfd, TestOptions* testopt, "CongestionSignals=%d,PktsOut=%d,MinRTT=%d,RcvWinScale=%d\n", link, mismatch, bad_cable, half_duplex, congestion, c2s_linkspeed_data, c2s_linkspeed_ack, s2c_linkspeed_data, s2c_linkspeed_ack, - CongestionSignals, PktsOut, MinRTT, RcvWinScale); + vars.CongestionSignals, vars.PktsOut, vars.MinRTT, vars.RcvWinScale); strlcat(logstr1, logstr2, sizeof(logstr1)); syslog(LOG_FACILITY | LOG_INFO, "%s", logstr1); closelog(); @@ -1421,15 +1417,17 @@ int run_test(web100_agent* agent, int ctlsockfd, TestOptions* testopt, * updated. Otherwise the changes are lost when the client terminates. */ if (admin_view == 1) { - totalcnt = calculate(date, SumRTT, CountRTT, CongestionSignals, PktsOut, - DupAcksIn, AckPktsIn, CurrentMSS, SndLimTimeRwin, - SndLimTimeCwnd, SndLimTimeSender, MaxRwinRcvd, - CurrentCwnd, Sndbuf, DataBytesOut, mismatch, bad_cable, - (int) c2sspd, (int) s2cspd, c2s_linkspeed_data, - s2c_linkspeed_ack, 1); - gen_html((int) c2sspd, (int) s2cspd, MinRTT, PktsRetrans, Timeouts, - Sndbuf, MaxRwinRcvd, CurrentCwnd, mismatch, bad_cable, totalcnt, - refresh); + totalcnt = calculate(date, vars.SumRTT, vars.CountRTT, + vars.CongestionSignals, vars.PktsOut, vars.DupAcksIn, + vars.AckPktsIn, vars.CurrentMSS, vars.SndLimTimeRwin, + vars.SndLimTimeCwnd, vars.SndLimTimeSender, + vars.MaxRwinRcvd, vars.CurrentCwnd, vars.Sndbuf, + vars.DataBytesOut, mismatch, bad_cable, (int) c2sspd, + (int) s2cspd, c2s_linkspeed_data, s2c_linkspeed_ack, + 1); + gen_html((int) c2sspd, (int) s2cspd, vars.MinRTT, vars.PktsRetrans, + vars.Timeouts, vars.Sndbuf, vars.MaxRwinRcvd, vars.CurrentCwnd, + mismatch, bad_cable, totalcnt, refresh); } shutdown(ctlsockfd, SHUT_WR); /* shutdown(ctlsockfd, SHUT_RDWR); */ @@ -1453,7 +1451,7 @@ int main(int argc, char** argv) { int i, loopcnt, t_opts = 0; struct sockaddr_storage cli_addr; struct sigaction new; - web100_agent* agent; + tcp_stat_agent* agent; char *lbuf = NULL, *ctime(); char buff[32], tmpstr[256]; char test_suite[16]; @@ -1616,7 +1614,11 @@ int main(int argc, char** argv) { admin_view = 1; break; case 'f': +#if USE_WEB100 VarFileName = optarg; +#elif USE_TCPE + log_println(2, "Web10g doesn't require a varfile. Ignored."); +#endif break; case 'i': device = optarg; @@ -1818,10 +1820,15 @@ int main(int argc, char** argv) { } listenfd = I2AddrFD(listenaddr); + if (listenfd == -1) { + log_println(0, "ERROR: Socket already in use."); + return 0; + } + log_println(1, "server ready on port %s (family %d)", port, meta.family); - // Initialize Web100 structures - count_vars = web100_init(VarFileName); + // Initialize tcp_stat structures + count_vars = tcp_stat_init(VarFileName); if (count_vars == -1) { log_println(0, "No web100 variables file found, terminating program"); exit(-5); @@ -1923,11 +1930,6 @@ mainloop: if (head_ptr == NULL) "zombie_check=%d", head_ptr->pid, testing, waiting, mclients, zombie_check); - // moved condition from interrupt handler to here - /* if ((sig1 > 0) || (sig2 > 0)) - * check_signal_flags; - */ - if (sig13 == 1) { log_println(5, "todo: Handle SIGPIPE signal, terminate child?"); child_sig(0); @@ -2599,11 +2601,18 @@ sel_12: retcode = select(listenfd + 1, &rfd, NULL, NULL, NULL); "pid=%d", chld_pipe[0], chld_pipe[1], chld_pid); close(listenfd); close(chld_pipe[1]); +#if USE_WEB100 if ((agent = web100_attach(WEB100_AGENT_TYPE_LOCAL, NULL)) == NULL) { web100_perror("web100_attach"); return 1; } +#elif USE_TCPE + if (tcpe_client_init(&agent) != NULL) { + log_println(0, "Error: tcpe_client_init failed. Unable to use web10g."); + return 1; + } +#endif // This is the child process from the above fork(). The parent // is in control, and will send this child a signal when it gets @@ -2727,7 +2736,11 @@ sel_12: retcode = select(listenfd + 1, &rfd, NULL, NULL, NULL); child_sig(0); } close(ctlsockfd); +#if USE_WEB100 web100_detach(agent); +#elif USE_TCPE + tcpe_client_destroy(&agent); +#endif log_free(); if (cputime && workerThreadId) { diff --git a/src/web100srv.h b/src/web100srv.h index a48c7bb..d797e0f 100644 --- a/src/web100srv.h +++ b/src/web100srv.h @@ -19,6 +19,9 @@ #ifdef HAVE_LIBWEB100 #include <web100.h> #endif +#ifdef HAVE_LIBTCPE +#include <tcpe.h> +#endif #ifdef HAVE_LIBPCAP #include <pcap.h> #endif @@ -190,6 +193,53 @@ struct iflists { u_int16_t speed[32]; } iflist; +typedef int tcp_stat_var; + +struct tcp_vars { + tcp_stat_var Timeouts; + tcp_stat_var SumRTT; + tcp_stat_var CountRTT; + tcp_stat_var PktsRetrans; + tcp_stat_var FastRetran; + tcp_stat_var DataPktsOut; + tcp_stat_var AckPktsOut; + tcp_stat_var CurrentMSS; + tcp_stat_var DupAcksIn; + tcp_stat_var AckPktsIn; + tcp_stat_var MaxRwinRcvd; + tcp_stat_var Sndbuf; + tcp_stat_var CurrentCwnd; + tcp_stat_var SndLimTimeRwin; + tcp_stat_var SndLimTimeCwnd; + tcp_stat_var SndLimTimeSender; + tcp_stat_var DataBytesOut; + tcp_stat_var SndLimTransRwin; + tcp_stat_var SndLimTransCwnd; + tcp_stat_var SndLimTransSender; + tcp_stat_var MaxSsthresh; + tcp_stat_var CurrentRTO; + tcp_stat_var CurrentRwinRcvd; + tcp_stat_var MaxCwnd; + tcp_stat_var CongestionSignals; + tcp_stat_var PktsOut; + tcp_stat_var MinRTT; + tcp_stat_var RcvWinScale; + tcp_stat_var SndWinScale; + tcp_stat_var CongAvoid; + tcp_stat_var CongestionOverCount; + tcp_stat_var MaxRTT; + tcp_stat_var OtherReductions; + tcp_stat_var CurTimeoutCount; + tcp_stat_var AbruptTimeouts; + tcp_stat_var SendStall; + tcp_stat_var SlowStart; + tcp_stat_var SubsequentTimeouts; + tcp_stat_var ThruBytesAcked; + /* Additional for web10g */ + tcp_stat_var MaxSsCwnd; + tcp_stat_var MaxCaCwnd; +}; + /* web100-pcap */ #ifdef HAVE_LIBPCAP void init_vars(struct spdpair *cur); @@ -198,40 +248,78 @@ void calculate_spd(struct spdpair *cur, struct spdpair *cur2, int port2, int port3); void init_pkttrace(I2Addr srcAddr, struct sockaddr *sock_addr, socklen_t saddrlen, int monitor_pipe[2], char *device, - PortPair* pair, char * direction, int compress); -int check_signal_flags(); + PortPair* pair, const char * direction, int compress); +void force_breakloop(); #endif /* web100-util */ -#ifdef HAVE_LIBWEB100 +#if defined(HAVE_LIBWEB100) +#if (!defined(HAVE_LIBTCPE) || defined(FORCE_WEB100)) +#define USE_WEB100 true +#define USE_TCPE false +#else +#define USE_WEB100 false +#define USE_TCPE true +#endif +#elif defined(HAVE_LIBTCPE) +#define USE_WEB100 false +#define USE_TCPE true +#else +#error Either Web100 or Web10g must be available +#define USE_WEB100 false +#define USE_TCPE false +#endif + +#if USE_WEB100 || USE_TCPE void get_iflist(void); -int web100_init(char *VarFileName); -int web100_autotune(int sock, web100_agent* agent, web100_connection* cn); -void web100_middlebox(int sock, web100_agent* agent, web100_connection* cn, + +#if USE_TCPE +typedef struct tcpe_client tcp_stat_agent; +typedef int tcp_stat_connection; +typedef struct tcpe_data tcp_stat_snap; +/* Not relevent to web10g */ +typedef void tcp_stat_group; +/* Log currently unimplemented in web100 */ +typedef void tcp_stat_log; +#define tcp_stat_connection_from_socket web10g_connection_from_socket + +/* Extra Web10G functions web10g-util.c */ +int web10g_find_val(tcpe_data* data, char* name, struct tcpe_val* value); +int web10g_get_val(struct tcpe_client* client, int conn, char* name, struct tcpe_val * value); +int web10g_connection_from_socket(struct tcpe_client* client,int sockfd); +int web10g_get_remote_addr(struct tcpe_client* client, int conn, char* out, int size); + +#elif USE_WEB100 + +typedef web100_agent tcp_stat_agent; +typedef web100_connection* tcp_stat_connection; +typedef web100_snapshot tcp_stat_snap; +/* Group only relevent to web100 */ +typedef web100_group tcp_stat_group; +/* Log currently unimplemented in web100 */ +typedef web100_log tcp_stat_log; +#define tcp_stat_connection_from_socket web100_connection_from_socket + +#endif + +int tcp_stat_autotune(int sock, tcp_stat_agent* agent, tcp_stat_connection cn); +int tcp_stat_init(char *VarFileName); +void tcp_stat_middlebox(int sock, tcp_stat_agent* agent, tcp_stat_connection cn, char *results, size_t results_strlen); -int web100_setbuff(int sock, web100_agent* agent, web100_connection* cn, - int autotune); -void web100_get_data_recv(int sock, web100_agent* agent, web100_connection* cn, +int tcp_stat_setbuff(int sock, tcp_stat_agent* agent, tcp_stat_connection cn, + int autotune);/* Not used so no web10g version */ +void tcp_stat_get_data_recv(int sock, tcp_stat_agent* agent, tcp_stat_connection cn, int count_vars); -int web100_get_data(web100_snapshot* snap, int ctlsock, web100_agent* agent, +int tcp_stat_get_data(tcp_stat_snap* snap, int testsock, int ctlsock, tcp_stat_agent* agent, int count_vars); -int CwndDecrease(web100_agent* agent, char* logname, + +// TODO web10g version of CwndDecrease +int CwndDecrease(tcp_stat_agent* agent, char* logname, u_int32_t *dec_cnt, u_int32_t *same_cnt, u_int32_t *inc_cnt); -int web100_logvars(int *Timeouts, int *SumRTT, int *CountRTT, - int *PktsRetrans, int *FastRetran, int *DataPktsOut, - int *AckPktsOut, int *CurrentMSS, int *DupAcksIn, - int *AckPktsIn, int *MaxRwinRcvd, int *Sndbuf, - int *CurrentCwnd, int *SndLimTimeRwin, int *SndLimTimeCwnd, - int *SndLimTimeSender, int *DataBytesOut, - int *SndLimTransRwin, int *SndLimTransCwnd, - int *SndLimTransSender, int *MaxSsthresh, int *CurrentRTO, - int *CurrentRwinRcvd, int *MaxCwnd, int *CongestionSignals, - int *PktsOut, int *MinRTT, int count_vars, int *RcvWinScale, - int *SndWinScale, int *CongAvoid, int *CongestionOverCount, - int *MaxRTT, int *OtherReductions, int *CurTimeoutCount, - int *AbruptTimeouts, int *SendStall, int *SlowStart, - int *SubsequentTimeouts, int *ThruBytesAcked); -#endif +int tcp_stat_logvars(struct tcp_vars* vars, int count_vars); + +#endif // defined(HAVE_LIBWEB100) || defined(HAVE_LIBTCPE) + int KillHung(void); void writeMeta(int compress, int cputime, int snaplog, int tcpdump); diff --git a/src/web10g-util.c b/src/web10g-util.c new file mode 100644 index 0000000..50e0622 --- /dev/null +++ b/src/web10g-util.c @@ -0,0 +1,227 @@ +/* + * A handful of functions to handle some web10g specific stuff + * + * Author: Richard Sanger + * + */ + +/* + * These are used to pass information between web10g_connection_from_socket + * and getremote_callback. It would be nice if these were not globals. + */ +#include "web100srv.h" +#include "logging.h" + +static struct sockaddr_storage local_name; +static struct sockaddr_storage peer_name; +static int connection_id; + +/** + * Callback function used by web10g_connection_from_socket, will set + * connection_id if the correct connection is found. + * + * @param ct A tuple containing connection information + */ +static void fromsocket_callback(struct tcpe_connection_tuple* ct) { + /* I'm assuming local_name and remote_name should both be on + * the same addressing scheme i.e. either IPv4 or IPv6 not a mix of both */ + if(local_name.ss_family == AF_INET && peer_name.ss_family == AF_INET) { + /* We are IPv4 check if this web10g connection also is */ + if ((ct->local_addr[16]) == TCPE_ADDRTYPE_IPV4 && + (ct->rem_addr[16]) == TCPE_ADDRTYPE_IPV4) { + struct sockaddr_in * ipv4_local = (struct sockaddr_in *) &local_name; + struct sockaddr_in * ipv4_peer = (struct sockaddr_in *) &peer_name; + + /* Compare local and remote ports and addresses */ + if (ct->local_port == ntohs(ipv4_local->sin_port) && + ct->rem_port == ntohs(ipv4_peer->sin_port) && + ((struct in_addr*) ct->rem_addr)->s_addr == ipv4_peer->sin_addr.s_addr && + ((struct in_addr*) ct->local_addr)->s_addr == ipv4_local->sin_addr.s_addr ) { + /* Found it */ + connection_id = ct->cid; + log_println(2, "Matched socket to web10g IPv4 connection #%d", connection_id); + } + } + } else if(local_name.ss_family == AF_INET6 && peer_name.ss_family == AF_INET6) { + /* We are IPv6 check if this web10g connection also is */ + if ((ct->local_addr[16]) == TCPE_ADDRTYPE_IPV6 && + (ct->rem_addr[16]) == TCPE_ADDRTYPE_IPV6) { + struct sockaddr_in6 * ipv6_local = (struct sockaddr_in6 *) &local_name; + struct sockaddr_in6 * ipv6_peer = (struct sockaddr_in6 *) &peer_name; + + /* Compare local and remote ports and addresses */ + if (ct->local_port == ntohs(ipv6_local->sin6_port) && + ct->rem_port == ntohs(ipv6_peer->sin6_port) && + memcmp(ct->rem_addr, ipv6_peer->sin6_addr.s6_addr, sizeof(struct in6_addr)) == 0 && + memcmp(ct->local_addr, ipv6_local->sin6_addr.s6_addr, sizeof(struct in6_addr)) == 0) { + /* Found it */ + connection_id = ct->cid; + log_println(2, "Matched socket to web10g IPv6 connection #%d", connection_id); + } + } + } else { + log_println(1, "WARNING: Mismatch between local and peer family"); + } +} + +/** + * Find the web10g connection number related to a given socket. + * + * @param client A web10g client + * @param sockfd The socket file descriptor + * + * @return The connection number if successful. If an error occurs -1 + * will be returned. + * + */ +int web10g_connection_from_socket(struct tcpe_client* client, int sockfd) { + socklen_t local_name_len; + socklen_t peer_name_len; + + local_name_len = sizeof(local_name); + peer_name_len = sizeof(peer_name); + connection_id = -1; + + /* Get the ip address of ourself on the localsocket */ + if (getsockname(sockfd,(struct sockaddr *) &local_name, &local_name_len) == -1) { + log_println(1, "getsockname() failed: %s ", strerror(errno)); + return -1; + } + + /* Get the ip address of our peer */ + if (getpeername(sockfd,(struct sockaddr *) &peer_name, &peer_name_len) == -1) { + log_println(1, "getpeername() failed: %s ", strerror(errno)); + return -1; + } + + tcpe_list_conns(client, fromsocket_callback); + + return connection_id; +} + +/** + * Find the specified web10g variable given a connection at the current + * time. + * Similar to web10g_find_val except this also retrieves data from web10g + * rather than from a provided capture. If many varibles are being read + * it's probably best to capture the data then use web10g_find_val. + * + * @param data A web10g data capture + * @param name The web10g variable name + * @param *value A pointer to a web10g value structure. If successful + * this will contain the requested value upon return. If an error occurs + * it's contents will remain untouched. + * + * @return int 0 if successful otherwise 1 in the event of an error + * (including the case the specified value cannot be found). + * + */ +int web10g_get_val(struct tcpe_client* client, int conn, char* name, struct tcpe_val* value) { + int i; + tcpe_data* data = NULL; + + tcpe_data_new(&data); + tcpe_read_vars(data, conn, client); + + for (i = 0; i < ARRAYSIZE(data->val); i++) { + if (data->val[i].mask) continue; + + if (strcmp(tcpe_var_array[i].name, name) == 0){ + value->uv64 = data->val[i].uv64; + value->mask = data->val[i].mask; + i = -1; + break; + } + } + + tcpe_data_free(&data); + return i == -1 ? 1 : 0; +} + +/* + * These are used to pass information between web10g_get_remote_addr + * and getremotecallback. It would be nice if these were not globals. + */ +static int connid; +static char * remote_name; +static int remote_name_size; + +/** + * Callback function used by web10g_get_remote_addr, will fill in + * remote_name once if the correct connection is found and set remote_name + * to NULL to indicate to web10g_get_remote_addr that the connection was + * found. + * + * @param ct A tuple containing connection information + * + */ +static void getremote_callback(struct tcpe_connection_tuple* ct) { + if (ct->cid != connid) + return; + if (ct->local_addr[16] == TCPE_ADDRTYPE_IPV4) { + inet_ntop(AF_INET, &(ct->rem_addr[0]), remote_name, remote_name_size); + remote_name = NULL; + } else if (ct->local_addr[16] == TCPE_ADDRTYPE_IPV6) { + inet_ntop(AF_INET6, &(ct->rem_addr[0]), remote_name, remote_name_size); + remote_name = NULL; + } +} + +/** + * Get the remote address given connection number + * + * @param client Web10g client + * @param conn The web10g connection number + * @param out A pointer to a character buffer, into which the remote + * address will be returned if successful. Upon error the contents are + * remain unchanged. + * @param size The size of the buffer 'out'. + * + * @return int 0 if successful otherwise 1 in the event of an error + * (The connection could not be found). + * + */ +int web10g_get_remote_addr(struct tcpe_client* client, int conn, char* out, int size) { + /* Pass these to the callback routine using those globals */ + connid = conn; + remote_name = out; + remote_name_size = size; + /* This will call the getremote_callback once for every tcp connection */ + tcpe_list_conns(client, getremote_callback); + + return remote_name == NULL ? 0 : 1; +} + +/** + * Find the specified web10g variables value within a provided capture. + * Similar to web10g_get_val except this works on a previously retrieved + * set of data. + * + * @param data A web10g data capture + * @param name The web10g variable name + * @param *value A pointer to a web10g value structure. If successful + * this will contain the requested value upon return. If an error occurs + * its contents will remain untouched. + * + * @return int 0 if successful otherwise 1 in the event of an error + * (including the case the specified value cannot be found). + * + */ +int web10g_find_val(tcpe_data* data, char* name, struct tcpe_val* value) { + int i; + + if(data == NULL || name == NULL || value == NULL) + return 1; + + for (i = 0; i < ARRAYSIZE(data->val); i++) { + if (data->val[i].mask) continue; + if (strcmp(tcpe_var_array[i].name, name) == 0){ + value->uv64 = data->val[i].uv64; + value->mask = data->val[i].mask; + return 0; + } + } + + return 1; +} +
- Re: NDT 3.6.5 on a 3.2.x kernel, Jon Kåre Hellan, 04/05/2013
- <Possible follow-up(s)>
- Re: NDT 3.6.5 on a 3.2.x kernel, Aaron Brown, 04/05/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Richard Sanger, 04/05/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Aaron Brown, 04/09/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Richard Sanger, 04/05/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Daniel A. Ramaley, 04/05/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Aaron Brown, 04/05/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Daniel A. Ramaley, 04/08/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Daniel A. Ramaley, 04/08/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Daniel A. Ramaley, 04/08/2013
- Message not available
- Re: NDT 3.6.5 on a 3.2.x kernel, Daniel A. Ramaley, 04/08/2013
- Message not available
- Re: NDT 3.6.5 on a 3.2.x kernel, Daniel A. Ramaley, 04/08/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Aaron Brown, 04/05/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Daniel A. Ramaley, 04/08/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Richard Sanger, 04/08/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Daniel A. Ramaley, 04/09/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Richard Sanger, 04/10/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Daniel A. Ramaley, 04/10/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Richard Sanger, 04/10/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Daniel A. Ramaley, 04/09/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Richard Sanger, 04/08/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Aaron Brown, 04/09/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Dominic Hamon, 04/09/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Dominic Hamon, 04/10/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Dominic Hamon, 04/10/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Aaron Brown, 04/10/2013
- Re: NDT 3.6.5 on a 3.2.x kernel, Dominic Hamon, 04/10/2013
Archive powered by MHonArc 2.6.16.