Index: src/web100srv.h =================================================================== --- src/web100srv.h (revision 796) +++ src/web100srv.h (working copy) @@ -19,6 +19,9 @@ #ifdef HAVE_LIBWEB100 #include #endif +#ifdef HAVE_LIBTCPE +#include +#endif #ifdef HAVE_LIBPCAP #include #endif @@ -190,6 +193,54 @@ 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 +249,63 @@ 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) || defined(HAVE_LIBTCPE) 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, +#ifdef FORCE_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 + +#else /* web10g */ +#ifdef HAVE_LIBTCPE + +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); + +#endif /* HAVE_LIBTCPE */ +#endif /* FORCE_WEB100 */ + +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 count_vars); -int web100_get_data(web100_snapshot* snap, int ctlsock, web100_agent* agent, - int count_vars); -int CwndDecrease(web100_agent* agent, char* logname, +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 tcp_stat_get_data(tcp_stat_snap snap, int testsock, int ctlsock, tcp_stat_agent agent, + int count_vars); + +/* 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); @@ -244,4 +318,5 @@ sig_atomic_t sig17; pid_t sig17_pid[256]; + #endif // SRC_WEB100SRV_H_ Index: src/test_results_clt.c =================================================================== --- src/test_results_clt.c (revision 796) +++ src/test_results_clt.c (working copy) @@ -296,7 +296,9 @@ /** * Print if TCP Selective Acknowledgment Options based on RFC 2018 is on - * + * web100 0 off 1< on - directly from tcp_options_received.sack_ok (Storage size is 4bits) + * web10g 1 is on 2 is selfDisabled 3 peerDisabled - split into WillSendSACK + * and WillUseSack. For now change web10G to return either 0 off or 1 on. * @param SACKEnabled */ void print_SAck_RFC2018(int SACKEnabled) { @@ -309,40 +311,57 @@ /** * Print if Nagle algorithm (rfc 896) is on + * web100 1 is on 0 is off + * web10g 1 is on 2 is off * @param is_nagleenabled */ void print_Nagle_RFC896(int is_nagleenabled) { printf("RFC 896 Nagle Algorithm: "); - if (is_nagleenabled == 0) + if (is_nagleenabled == 1) + printf("ON\n"); + else printf("OFF\n"); - else - printf("ON\n"); } /** * Print if Explicit congestion notification to IP is on - RFC 3168 related + * web100 0 is off 1 is on + * web10g 1 is on 2 is selfDisabled 3 peerDisabled * @param is_ECNenabled */ void print_congestion_RFC3168(int is_ECNenabled) { printf("RFC 3168 Explicit Congestion Notification: "); - if (is_ECNenabled == 0) - printf("OFF\n"); - else - printf("ON\n"); + if (is_ECNenabled == 1) + printf("ON\n"); + else if (is_ECNenabled == 0) + printf("OFF\n"); + else if (is_ECNenabled == 2) + printf("OFF - disabled by server\n"); + else if (is_ECNenabled == 3) + printf("OFF - disabled by client\n"); + else + printf("OFF? - unable to determine setting\n"); } /** * Print details of whether time stamping is on - RFC 1323 related. - * + * web100 1 is on 0 is off - directly from tcp_options_received.tstamp_ok (Storage size is 1bit) + * web10g 1 is on 2 is selfDisabled 3 peerDisabled. * @param is_timestampenabled */ void print_timestamping_RFC1323(int is_timestampenabled) { printf("RFC 1323 Time Stamping: "); - if (is_timestampenabled == 0) - printf("OFF\n"); - else - printf("ON\n"); + if (is_timestampenabled == 1) + printf("ON\n"); + else if (is_timestampenabled == 0) + printf("OFF\n"); + else if (is_timestampenabled == 2) + printf("OFF - disabled by server\n"); + else if (is_timestampenabled == 3) + printf("OFF - disabled by client\n"); + else + printf("OFF? - unable to determine setting\n"); } /** Index: src/kernel_coalesce.c =================================================================== --- src/kernel_coalesce.c (revision 0) +++ src/kernel_coalesce.c (revision 0) @@ -0,0 +1,308 @@ +/* + * This contains functions used by ndt to disable disable packet + * coalescing on network interfaces. This uses the ETHTOOL API to + * access and modify coalescing settings. + * + * disable_coalesce is intended to be called first followed by + * revert_coalesce to undo any changes made by disable_coalesce. + * + * Author: Richard Sanger + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../config.h" +#include "logging.h" + +#define RX_ON 0x1 +#define RX_IRQ_ON 0x2 +#define TX_ON 0x4 +#define TX_IRQ_ON 0x8 +#define RX_ADAPT_ON 0x10 +#define TX_ADAPT_ON 0x20 + + +/* We need to keep a copy of the ethtool_coalescing for every interface + * that we change. This is the number of coal_settings data structures + * we can keep for the purpose to later revert. 6 seems plenty + * since 'lo' isn't included nor any other interface without coalescing + * support. + */ +#define MAX_IFACES 6 +#define IS_DISABLED(a,b) ((a == 0 || a==1) && (b==0 || b == 1)) + +/* Keep the original coalescing data so we can switch back to this */ +static struct coal_settings{ + /* The original coal data */ + struct ethtool_coalesce coal; + /* The interfaces name, if empty we don't revert this one */ + char name[IFNAMSIZ]; +} eth_coal_org[MAX_IFACES]; + +/** + * Check if coalescing is already off and fill in the new structure as + * required. See linux/ethtool.h header for discriptions of each field + * Note: we cannot set both coalesce_usecs and coalesce_max_frame to 0 + * this is because 0 means to ignore this setting and only use the other + * no 0 one. + * + * @param org (in) - the original coalesce data + * @param new (out) - the new coalesce data which will have all + * coalescing turned off upon return. + * + * @return flags indicating which settings have been changed in 'new'. + * If return value is 0 then coalescing is already off and no changes + * to new have been made. + */ +static __u32 check_disable_coalesce(const struct ethtool_coalesce * org, + struct ethtool_coalesce * new){ + __u32 flags = 0; + + assert(org); + assert(new); + + /* Copy across the orginal settings into new settings */ + memcpy(new, org, sizeof(struct ethtool_coalesce)); + + log_println(6, "--rx_coalesce_usecs : %d\n--rx_max_coalesced_frames : %d", + org->rx_coalesce_usecs, org->rx_max_coalesced_frames); + if(IS_DISABLED(org->rx_coalesce_usecs, org->rx_max_coalesced_frames)){ + log_println(6, " RX coalescing is already disabled"); + } else { + flags |= RX_ON; + new->rx_coalesce_usecs = 0; + new->rx_max_coalesced_frames = 1; + log_println(6, " ndt will attempt to disable RX coalescing"); + } + + log_println(6, "--rx_coalesce_usecs_irq : %d\n--rx_max_coalesced_frames_irq : %d", + org->rx_coalesce_usecs_irq, org->rx_max_coalesced_frames_irq); + if(IS_DISABLED(org->rx_coalesce_usecs_irq, org->rx_max_coalesced_frames_irq)){ + log_println(6, " RX irq coalescing is already disabled"); + } else { + flags |= RX_IRQ_ON; + new->rx_coalesce_usecs_irq = 0; + new->rx_max_coalesced_frames_irq = 1; + log_println(6, " ndt will attempt to disable RX irq coalescing"); + } + + log_println(6, "--tx_coalesce_usecs : %d\n--tx_max_coalesced_frames : %d", + org->tx_coalesce_usecs, org->tx_max_coalesced_frames); + if(IS_DISABLED(org->tx_coalesce_usecs, org->tx_max_coalesced_frames)){ + log_println(6, " TX coalescing is already disabled"); + } else { + flags |= TX_ON; + new->tx_coalesce_usecs = 0; + new->tx_max_coalesced_frames = 1; + log_println(6, " ndt will attempt to disable TX coalescing"); + } + + log_println(6, "--tx_coalesce_usecs_irq : %d\n--tx_max_coalesced_frames_irq : %d", + org->tx_coalesce_usecs_irq, org->tx_max_coalesced_frames_irq); + if(IS_DISABLED(org->tx_coalesce_usecs_irq, org->tx_max_coalesced_frames_irq)){ + log_println(6, " TX irq coalescing is already disabled"); + } else { + flags |= TX_IRQ_ON; + new->tx_coalesce_usecs_irq = 0; + new->tx_max_coalesced_frames_irq = 1; + log_println(6, " ndt will attempt to disable TX irq coalescing"); + } + + log_println(6, "--use_adaptive_rx_coalesce : %d", org->use_adaptive_rx_coalesce); + if(org->use_adaptive_rx_coalesce == 0){ + log_println(6, " Adaptive RX coalescing is already disabled"); + } else { + flags |= RX_ADAPT_ON; + new->use_adaptive_rx_coalesce = 0; + log_println(6, " ndt will attempt to disable RX adaptive coalescing"); + } + + log_println(6, "--use_adaptive_tx_coalesce : %d", org->use_adaptive_tx_coalesce); + if(org->use_adaptive_tx_coalesce == 0){ + log_println(6, " Adaptive TX coalescing is already disabled"); + } else { + flags |= TX_ADAPT_ON; + new->use_adaptive_rx_coalesce = 0; + log_println(6, " ndt will attempt to disable TX adaptive coalescing"); + } + + return flags; +} + +/** + * Where possible disables packet coalecsing on all interfaces. + * This will log information about any interfaces which it fails on. + * + * @param autofix + */ +void disable_coalesce(int autofix){ + struct ethtool_coalesce eth_coal_new; + pcap_if_t *alldevs, *dp; + /* The current item in the eth_coal_org stucture we are filling */ + int curr = 0; + /* We use ifr for the ETHTOOL query ioctl*/ + struct ifreq ifr; + int skfd; + __u32 flags; + memset(&ifr, 0, sizeof(ifr)); + char errbuf[PCAP_ERRBUF_SIZE]; + + /* ioctl needs a file discriptor, make sure we get this without + * needing super user permissions. + */ + if (( skfd = socket(AF_INET, SOCK_DGRAM, 0 ) ) < 0 ) + { + log_println(0, "disable_coalesce - Socket error: %s", strerror(errno)); + return; + } + + /* Get all the interfaces using pcap since it only lists + * the interfaces it can actually open. + */ + if (pcap_findalldevs(&alldevs, errbuf) != 0) { + log_println(0, "disable_coalesce - pcap_findalldevs error: %s", errbuf); + close(skfd); + return; + } + + for(dp = alldevs; dp != NULL; dp = dp->next){ + /* Ignore any it's a silly device to try and change */ + if( strcmp("any", dp->name) == 0 || dp->flags & PCAP_IF_LOOPBACK) + continue; + + log_println(6, "Found interface %s", dp->name); + /* Try get current coalesce settings */ + eth_coal_org[curr].coal.cmd = ETHTOOL_GCOALESCE; + strncpy(ifr.ifr_name, dp->name, strlen(dp->name)); + ifr.ifr_data = (char *) ð_coal_org[curr].coal; + + if (ioctl(skfd, SIOCETHTOOL, &ifr)) + { + switch(errno){ + case EPERM: + log_println(1, "I can not read coalesce settings for %s. " + "You should try running ndt as a super user: %s", + dp->name, strerror(errno)); + break; + case EOPNOTSUPP: + /* This is actually ok, the card doesn't support coalescing" */ + log_println(6, "Network interface %s doesn't support" + " coalescing: %s", dp->name, strerror(errno)); + continue; + default: + log_println(1, "I can not read coalesce settings for" + " %s: %s", dp->name, strerror(errno)); + break; + } + log_println(0, "WARNING - Link speed detection may be inaccurate for %s.", dp->name); + continue; + } + + /* Check what the current coalescing settings are and change if necessary */ + flags = check_disable_coalesce(ð_coal_org[curr].coal, ð_coal_new); + + if(flags != 0){ + if (!autofix){ + log_println(0, "Warning: Link speed detection may be inaccurate for %s.", dp->name); + continue; + } + + if (curr == MAX_IFACES) + log_println(0, "Ran out of space to store coalescing settings," + " consider rebuiling with an increased MAX_IFACES kernel_coalesce.c"); + + /* Only change coalesce settings if they are actually enabled */ + eth_coal_new.cmd = ETHTOOL_SCOALESCE; + ifr.ifr_data = (char *) ð_coal_new; + if (ioctl(skfd, SIOCETHTOOL, &ifr)) + { + switch(errno){ + case EPERM: + log_println(1, "I can not set new coalesce settings for %s. " + "You should try running ndt as a super user: %s" + , dp->name, strerror(errno)); + break; + case EOPNOTSUPP: + /* We should have already checked this */ + log_println(1, "Network interface %s doesn't support coalescing" + "However it appeared to when querying for settings: %s" + , dp->name, strerror(errno)); + break; + default: + log_println(1, "I can not set coalesce settings" + " for %s: %s.", dp->name, strerror(errno)); + break; + } + log_println(0, "Warning: Link speed detection may be inaccurate for %s.", dp->name); + continue; + } + log_println(6, "Successfully disabled coalescing for %s.", dp->name); + /* Mark the slot */ + strncpy(eth_coal_org[curr].name, dp->name, strlen(dp->name)); + curr++; + } + } + + if (alldevs != NULL) + pcap_freealldevs(alldevs); + close(skfd); + return; +} + +/** + * Revert the coalesce setting to their original state before ndt was + * launched. Called after disable_coalesce to revert all of the changes. + * This will log information about any interfaces which it fails on. + */ +void revert_coalesce(){ + struct ifreq ifr; + int skfd = -1; + int curr; + memset(&ifr, 0, sizeof(ifr)); + + /* ioctl needs a file discriptor, make sure we get this without + * needing super user permissions. + */ + if (( skfd = socket( AF_INET, SOCK_DGRAM, 0 ) ) < 0 ) + { + log_println(0, "revert_coalesce - Socket error: %s", strerror(errno)); + return; + } + + for(curr = 0; curr < MAX_IFACES; curr++){ + /* Check if we are at the last valid entry */ + if(eth_coal_org[curr].name[0] == 0) + break; + + /* Unset coalesce on this interface */ + strncpy(ifr.ifr_name, eth_coal_org[curr].name, + strlen(eth_coal_org[curr].name)); + + eth_coal_org[curr].coal.cmd = ETHTOOL_SCOALESCE; + ifr.ifr_data = (char *) ð_coal_org; + if (ioctl(skfd, SIOCETHTOOL, &ifr)) + { + log_println(0, "I can not undo coalescing settings for %s: %s", + ifr.ifr_name, strerror(errno)); + continue; + } + log_println(6, "Successfully reverted coalesce settings for %s.", ifr.ifr_name); + /* Free the slot */ + eth_coal_org[curr].name[0] = 0; + } + + close(skfd); + return; +} Index: src/web100-pcap.c =================================================================== --- src/web100-pcap.c (revision 796) +++ src/web100-pcap.c (working copy) @@ -90,6 +90,19 @@ pcap_freealldevs(alldevs); } +/** + * Force the pcap_loop to return, this is safe to call from a signal handler. + * Note this will break the loop without a packet being received if + * used from a signal handler due to the EINTR interrupting pcaps 'read'. + * + * This calls pcap_breakloop with the correct capture. + */ +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 +110,7 @@ * @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 +148,6 @@ 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 +185,6 @@ 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 +566,6 @@ 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 +790,7 @@ 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 +1049,11 @@ log_println(5, "pcap_loop exited %s", pcap_geterr(pd)); } + /* Send back results to our parent */ + if(check_signal_flags() == 0){ + log_println(5, "Whatever happened, we should have a sig flag set"); + } + pcap_close(pd); log_println( Index: src/kernel_coalesce.h =================================================================== --- src/kernel_coalesce.h (revision 0) +++ src/kernel_coalesce.h (revision 0) @@ -0,0 +1,14 @@ +/* + * This contains function declaraions for needed by ndt to disable + * packet coalescing on network interfaces. + * + * Author: Richard Sanger + */ + +#ifndef SRC_KERNEL_COALESCE_H_ +#define SRC_KERNEL_COALESCE_H_ + +void disable_coalesce(int autofix); +void revert_coalesce(); + +#endif // SRC_KERNEL_COALESCE_H_ Index: src/test_sfw_srv.c =================================================================== --- src/test_sfw_srv.c (revision 796) +++ src/test_sfw_srv.c (working copy) @@ -120,8 +120,9 @@ * 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; int sfwsockfd, sfwsockport, sockfd, sfwport; @@ -130,9 +131,14 @@ fd_set fds; struct timeval sel_tv; int msgLen, msgType; +#ifdef FORCE_WEB100 web100_var* var; web100_connection* cn; web100_group* group; +#else /* Must be web10g */ + struct tcpe_val value; + int cn; +#endif int maxRTT, maxRTO; char hostname[256]; int rc; @@ -169,26 +175,40 @@ 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)); +#ifdef FORCE_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)); +#else /* Must be web10g */ + 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 +#ifdef FORCE_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)); +#else /* Must be web10g */ + 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) Index: src/web10g-util.c =================================================================== --- src/web10g-util.c (revision 0) +++ src/web10g-util.c (revision 0) @@ -0,0 +1,234 @@ +/* + * 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){ + /* 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); + } + } + } +} + +/** + * Find the web100 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); + if(i == -1) + return 1; + else + return 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 && 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->cid == connid && 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); + + if(remote_name == NULL) + return 0; + else + return 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; +} Index: src/web100clt.c =================================================================== --- src/web100clt.c (revision 796) +++ src/web100clt.c (working copy) @@ -19,6 +19,8 @@ #include "clt_tests.h" #include "strlutils.h" #include "test_results_clt.h" +#include +#include extern int h_errno; @@ -237,6 +239,29 @@ } /** + * 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){ + /* IPv4 */ + inet_ntop(AF_INET, &(((struct sockaddr_in *)addr)->sin_addr), + buf, len); + } +#ifdef AF_INET6 + else if(((struct sockaddr *)addr)->sa_family == AF_INET6 ){ + /* IPv6 */ + 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 +272,14 @@ * 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; int mss; size_t tmpLen; @@ -271,14 +296,27 @@ winssent = atoi(str); str = strtok(NULL, ";"); winsrecv = atoi(str); - - memset(ccip, 0, 64); + + /* Get the our local ip address */ + addr_size = sizeof(addr); + memset(csip, 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); + } + + /* Get the Server ip address */ + addr_size = sizeof(addr); memset(csip, 0, 64); tmpLen = 63; - I2AddrNodeName(peer_addr, csip, &tmpLen); - + 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 +524,6 @@ 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,9 +891,7 @@ 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 @@ -864,9 +899,11 @@ // 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); Index: src/test_meta_srv.c =================================================================== --- src/test_meta_srv.c (revision 796) +++ src/test_meta_srv.c (working copy) @@ -22,7 +22,7 @@ /** * Performs the META test. * @param ctlsockfd Client control socket descriptor - * @param agent Web100 agent used to track the connection + * @param not_usedagent Web100 agent or tcpe client used to track the connection not used * @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 not_usedagent, TestOptions* testOptions, int conn_options) { int j; int msgLen, msgType; Index: src/web100-admin.c =================================================================== --- src/web100-admin.c (revision 796) +++ src/web100-admin.c (working copy) @@ -17,6 +17,7 @@ #include "web100-admin.h" #include "utils.h" #include "strlutils.h" +#include "heuristics.h" /* Initialize the Administrator view. Process the data in the existing log file to * catch up on what's happened before. Index: src/tests_srv.h =================================================================== --- src/tests_srv.h (revision 796) +++ src/tests_srv.h (working copy) @@ -11,19 +11,15 @@ #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_ Index: src/kernel_config.c =================================================================== --- src/kernel_config.c (revision 0) +++ src/kernel_config.c (revision 0) @@ -0,0 +1,250 @@ +/* + * This contains functions used by ndt to tweak kernel settings. + * This uses the /proc/sys interface. + * + * Author: Richard Sanger + */ +#include +#include +#include +#include +#include "logging.h" + +/* Storage for the congestion control method */ +static char oldCongestionControl[128]; + +/* The name for reno that we write to the proc interface */ +#define RENO "reno" + +/** + * Reverses swap_to_reno by changing the congestion control to what + * it was before swap_to_reno was called. + * + * @return 0 if successfully otherwise -1 + */ +int revert_congestion(){ + FILE *fdwrite; + size_t len; + + /* Check if we need to change it back */ + if(oldCongestionControl[0] != 0){ + fdwrite = fopen("/proc/sys/net/ipv4/tcp_congestion_control", "w"); + if(fdwrite == NULL){ + log_println(0, "tcp_congestion_control Cannot open file for writing" + " - probably need to be super user: %s", strerror(errno)); + return -1; + } + /* Write the original value back to tcp_congestion_control */ + len = fwrite(oldCongestionControl, sizeof(char), strlen(oldCongestionControl), fdwrite); + if(len != strlen(oldCongestionControl)){ + log_println(0, "tcp_congestion_control Write failed: %s", + strerror(errno)); + fclose(fdwrite); + return -1; + } + if (fclose(fdwrite)){ + log_println(0, "tcp_congestion_control Write failed: %s", + strerror(errno)); + return -1; + } + oldCongestionControl[0] = 0; + log_println(6, "Successfully reverted tcp_congestion_control to its original value"); + } + return 0; +} + +/** + * Swaps the kernel to reno tcp congestion control. The man pages say + * that reno is a guaranteed tcp congestion control on every linux + * system. + * @param autofix if not 0 this function will try and change the settings + * + * @return 0 if successfully otherwise -1 + */ +int check_kernel(int autofix){ + FILE *fdread, *fdwrite; + size_t len; + fdwrite = fdread = NULL; + + /* Try read the current value, if it is already reno we don't need to change it */ + fdread = fopen("/proc/sys/net/ipv4/tcp_congestion_control", "r"); + if(fdread == NULL){ + log_println(0, "tcp_congestion_control Cannot open file for reading: %s", + strerror(errno)); + goto error_handle; + } + /* Store the current value into oldCongestionControl */ + len = fread((void *)oldCongestionControl, sizeof(char), sizeof(oldCongestionControl), fdread); + if(!feof(fdread)){ + log_println(0, "tcp_congestion_control fread failed: %s", + strerror(errno)); + goto error_handle; + } else { + fclose(fdread); + fdread = NULL; + } + + if(len == sizeof(oldCongestionControl)){ + log_println(0, "ERROR original congestion control string is to long"); + goto error_handle; + } else { + /* Null terminate */ + oldCongestionControl[len] = 0; + } + + /* Check if it's already reno */ + if(strncmp(RENO, oldCongestionControl, sizeof(RENO)-1) == 0){ + log_println(6, "Tcp_congestion_control value is already reno no change needed"); + oldCongestionControl[0] = 0; + return 0; + } + + log_println(6, "The original tcp_congestion_control value is %s", + oldCongestionControl); + + /* We need to change to reno */ + if(!autofix){ + log_println(0, "Warning: tcp_congestion_control should be set to '" + RENO "' ndt results may be incorrect"); + oldCongestionControl[0] = 0; + return 0; + } + + fdwrite = fopen("/proc/sys/net/ipv4/tcp_congestion_control", "w"); + if(fdwrite == NULL){ + log_println(0, "Tcp_congestion_control fopen(write) - probably not super user: %s", strerror(errno)); + goto error_handle; + } + len = fwrite(RENO,sizeof(char), sizeof(RENO)-1, fdwrite); + if(len != sizeof(RENO)-1){ + log_println(0, "Tcp_congestion_control fwrite: %s", strerror(errno)); + goto error_handle; + } + if (fclose(fdwrite)){ + if(errno == ENOENT){ + /* Trying to set a bad value will give us this error */ + log_println(0, "'" RENO "' tcp congestion control not available" + " on this system??: %s", strerror(errno)); + } else { + log_println(0, "tcp congestion control fclose(fdwrite): %s", strerror(errno)); + } + goto error_handle; + } + /* Success - Kernel has accpected and changed to reno */ + log_println(6, "Successfully changed tcp_congestion_control to " RENO); + return 0; + + /* Print warnings and close all the file handles if and error occurs */ +error_handle: + /* We have failed reading */ + if(fdread == NULL && fdwrite == NULL){ + log_println(0, "Warning: Could not determine current tcp_congestion_control" + ", this should be set to 'reno' or else ndt results may be incorrect."); + oldCongestionControl[0] = 0; + return -1; + } + /* Set close the read handle if its still open */ + if(fdread != NULL){ + fclose(fdread); + fdread = NULL; + } + /* We have failed writing */ + if(fdwrite != NULL){ + fclose(fdwrite); + fdwrite = NULL; + return -1; + } + oldCongestionControl[0] = 0; + log_println(0, "Warning: Failed to change congestion tcp_congestion_control to '" + RENO "' ndt results may be incorrect"); + return -1; +} + + +static char module_already_loaded = 1; +#define TCP_ESTATS_MODULE "tcp_estats_nl" + +/** + * Search for the TCP_ESTATS_MODULE in /proc/module aka the list of + * running modules + * + * @return 0 not running, 1 running, -1 error. + */ +static int search_for_module_tcpe(){ + int loaded = 0; + FILE *mods_fd; + char buf[256]; + mods_fd = fopen("/proc/modules", "r"); + + if(mods_fd == NULL){ + log_println(0, "/proc/modules Cannot open file for reading: %s", + strerror(errno)); + return -1; + } + + /* Search for the tcp_estats module line */ + while(fgets(buf, 256, mods_fd)){ + if(strncmp(TCP_ESTATS_MODULE " ", buf , sizeof(TCP_ESTATS_MODULE " ") - 1) + == 0){ + loaded = 1; + break; + } + } + + fclose(mods_fd); + return loaded; +} + +/** + * Check if tcp_estats module is loaded and will load if not. (Only + * relevent to web10G) + * + * @return 0 on success, -1 upon failure either to load the module or + * determine if the module is running. + */ +int start_tcpe(){ + int code = search_for_module_tcpe(); + + if(code == -1) + return -1; + + if(code == 1){ + module_already_loaded = 1; + return 0; + } + module_already_loaded = 0; + /* Module is not loaded try and load it */ + log_println(1, "Warning: tcp_estats module not loaded, attempting to load"); + system("modprobe " TCP_ESTATS_MODULE ); + if(search_for_module_tcpe() == 1) + return 0; + + log_println(0, "Error: tcp_estats module could not be loaded"); + return -1; +} + +/** + * Unload tcp_estats module if it was previously unloaded (Only + * relevent to web10G). If the module was previously loaded + * success code is returned and this function does nothing. + * + * Only should be called after start_tcpe(). + * + * @return 0 on success, -1 upon failure either to unload the module. + */ +int revert_tcpe(){ + if( module_already_loaded ) + return 0; + + /* We had to load the module so unload it*/ + log_println(1, "Warning: tcp_estats needs to be unloaded, attempting to unload"); + system("modprobe -r " TCP_ESTATS_MODULE ); + if( search_for_module_tcpe() == 0){ + log_println(1, "Successfully unloaded tcp_estats "); + return 0; + } + + log_println(0, "Warning: tcp_estats failed to unload '"); + return -1; +} + Index: src/web100-util.c =================================================================== --- src/web100-util.c (revision 796) +++ src/web100-util.c (working copy) @@ -17,6 +17,61 @@ #include "protocol.h" #include "strlutils.h" +struct tcp_name { + char* web100_name; + char* web10g_name; +}; + +/* Must match in-order with tcp_vars in web100srv.h struct */ +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 * beginning @@ -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) { +#ifdef FORCE_WEB100 FILE * fp; char line[256], trimmedline[256]; int count_vars = 0; @@ -54,9 +110,59 @@ log_println(1, "web100_init() read %d variables from file", count_vars); return (count_vars); + +#else /* Must be web10g */ + // Web100 would have setup a table of string's with the variable names + // loaded from an external file + // We already have one of these setup for us in the library itself. + // So we do nothing + 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){ + /* IPv4 */ + inet_ntop(AF_INET, &(((struct sockaddr_in *)addr)->sin_addr), + buf, len); + } +#ifdef AF_INET6 + else if(((struct sockaddr *)addr)->sa_family == AF_INET6 ){ + /* IPv6 */ + 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){ + /* IPv4 */ + snprintf(buf, len, "%hu", ntohs(((struct sockaddr_in *)addr)->sin_port)); + } +#ifdef AF_INET6 + else if(((struct sockaddr *)addr)->sa_family == AF_INET6 ){ + /* IPv6 */ + snprintf(buf, len, "%hu", ntohs(((struct sockaddr_in6 *)addr)->sin6_port)); + } +#endif +} + +/** * Performs part of the middlebox test. * The server sets the maximum value of the * congestion window, and starts a 5 second long @@ -74,11 +180,19 @@ * * */ -void web100_middlebox(int sock, web100_agent* agent, web100_connection* cn, + +void tcp_stat_middlebox(int sock, tcp_stat_agent agent, tcp_stat_connection cn, char *results, size_t results_strlen) { +#ifdef FORCE_WEB100 web100_var* var; web100_group* group; web100_snapshot* snap; + web100_var *LimCwnd; +#else /* Must be web10g */ + struct tcpe_val value; + tcpe_data * data = NULL; +#endif + char buff[8192], line[256]; char* sndbuff; int i, j, k, currentMSSval = 0; @@ -88,12 +202,16 @@ 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; // middlebox test results +#ifdef FORCE_WEB100 static char vars[][255] = { "CurMSS", "WinScaleSent", "WinScaleRecv", }; +#else + static char vars[][255] = { "CurMSS", "WinScaleSent", "WinScaleRcvd", }; +#endif assert(results); @@ -101,16 +219,24 @@ // 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 + saddr_size = sizeof(saddr); + 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,27 +244,35 @@ 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++) { +#ifdef FORCE_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 web100_raw_read(var, cn, buff); - // get current MSS in textual format and append to results // get current MSS value and append to "results" @@ -147,6 +281,14 @@ 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)); +#else /* Must be web10g */ + // read a web10g value + 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 +307,15 @@ * RAC 2/28/06 */ + // set TCP CWND web100 variable to twice the current MSS Value + limcwnd_val = 2 * currentMSSval; +#ifdef FORCE_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); +#else + 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 +339,14 @@ sndbuff[j] = (k++ & 0x7f); } +#ifdef FORCE_WEB100 // get web100 group with name "read" group = web100_group_find(agent, "read"); snap = web100_snapshot_alloc(group, cn); +#else + // Allocating memory + tcpe_data_new(&data); +#endif FD_ZERO(&wfd); FD_SET(sock, &wfd); @@ -205,7 +355,7 @@ while ((ret = select(sock + 1, NULL, &wfd, NULL, &sel_tv)) > 0) { if ((ret == -1) && (errno == EINTR)) /* a signal arrived, ignore it */ continue; - +#ifdef FORCE_WEB100 web100_snap(snap); // get next sequence # to be sent @@ -216,7 +366,16 @@ 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)); - +#else /* Must be web10g */ + // Grab the current snap of this + tcpe_read_vars(data, cn, agent); + // get next sequence # to be sent + web10g_find_val(data, "SndNxt", &value); + SndMax = value.uv32; + // get oldest un-acked sequence number + 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 ] if ((currentMSSval << 4) < (SndMax - SndUna - 1)) { @@ -231,9 +390,16 @@ if (k < 0) // general error writing to socket. quit break; } + +#ifdef FORCE_WEB100 log_println(5, "Finished with web100_middlebox() routine snap-0x%x, " "sndbuff=%x0x", snap, sndbuff); web100_snapshot_free(snap); +#else + tcpe_data_free(&data); + log_println(5, "Finished with web10g_middlebox() routine " + "sndbuff=%x0x", sndbuff); +#endif /* free(sndbuff); */ } @@ -246,12 +412,18 @@ * @param count_vars integer number of web100_variables to get value of * */ -void web100_get_data_recv(int sock, web100_agent* agent, web100_connection* cn, + +void tcp_stat_get_data_recv(int sock, tcp_stat_agent agent, tcp_stat_connection cn, int count_vars) { +#ifdef FORCE_WEB100 + web100_var* var; + web100_group* group; +#else + tcpe_data* data = NULL; +#endif + int i, ok; - web100_var* var; char buf[32], line[256], *ctime(); - web100_group* group; FILE * fp; time_t tt; @@ -263,10 +435,15 @@ fprintf(fp, "%15.15s;", ctime(&tt) + 4); // get values for group, var of IP Address of the Remote host's side of // connection +#ifdef FORCE_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)); +#else /* web10g */ + 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); @@ -274,7 +451,7 @@ ok = 1; // get values for other web100 variables and write to the log file - +#ifdef FORCE_WEB100 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,7 +482,46 @@ } ok = 1; } +#else /* web10g */ + 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) { fprintf(fp, "\n"); @@ -313,6 +529,13 @@ } } +#ifndef FORCE_WEB100 +/* Persistent storage is needed. Replacment for web100 web_vars not very nice TODO */ +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 @@ -324,8 +547,9 @@ * @param count_vars integer number of web100_variables to get value of * */ -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) { +#ifdef FORCE_WEB100 int i; web100_var* var; char buf[32], line[256]; @@ -371,8 +595,170 @@ } log_println(6, "S2C test - Send web100 data to client pid=%d", getpid()); return (0); +#else /* web10g */ + int j; + char line[256]; + 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 + */ + send_msg(ctlsock, TEST_MSG, "-~~~Web100_old_var_names~~~-: 1\n", strlen("-~~~Web100_old_var_names~~~-: 1\n")); + 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, "-~~~Web100_old_var_names~~~-: 1\n", strlen("-~~~Web100_old_var_names~~~-: 1\n")); + + log_println(6, "S2C test - Send web100 data to client pid=%d", getpid()); + return 0; +#endif } + +#ifdef FORCE_WEB100 /** * Calculate Web100 based Round-Trip Time (RTT) value. * @@ -417,7 +803,9 @@ sum = atoi(web100_value_to_text(web100_get_var_type(var), buf)); return (sum / count); } +#endif /* Appears to be unused so no need for web10g version */ + /** * Check if the "Auto Tune Send Buffer" and "Auto Tune Receive Buffer" options * are enabled and return status on each @@ -434,8 +822,8 @@ * 22 Cannot find X_SBufMode or X_RBufMode web100_variable's var/group. * 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) { +#ifdef FORCE_WEB100 web100_var* var; char buf[32]; web100_group* group; @@ -476,8 +864,13 @@ if (i == 0) j |= 0x02; return (j); +#else /* web10g */ + return 0x03; /* Disabled, well web10g doesn't autotune the kernel does though */ +#endif } + +#ifdef FORCE_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,7 +894,7 @@ * 35 - cannot read value of RcvWinScale web100 variable. * */ -int web100_setbuff(int sock, web100_agent* agent, web100_connection* cn, +int tcp_stat_setbuff(int sock, tcp_stat_agent agent, tcp_stat_connection cn, int autotune) { web100_var* var; char buf[32]; @@ -566,114 +959,81 @@ return (0); } +#endif /* Not used so don't need to make web10g version */ /** - * @param sock integer socket file descriptor indicating data recipient - * @param pointers to local copies of web100 variables + * @param tcp_vars to local copies of web100 variables + * @param count_vars the number of web100 vars loaded * @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) +{ +#ifdef FORCE_WEB100 + int a,b; + + for (a = 0; a < (sizeof(struct tcp_vars) / sizeof(tcp_stat_var)); a++) { + if(tcp_names[a].web100_name == NULL) + break; + + /* Find the corresponding value */ + for (b = 0; ;b++){ + if(b == (count_vars + 1)){ + log_println(1,"WARNING: Couldn't Find web100 var %s", tcp_names[a].web100_name); + break; + } + if(strcmp(web_vars[b].name, tcp_names[a].web100_name) == 0){ + ((tcp_stat_var *) vars)[a] = atoi(web_vars[b].value); + log_println(5, "Found %s : %i", tcp_names[a].web100_name, ((tcp_stat_var *) vars)[a]); + break; + } + + } - 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); } + return 0; +#else /* web10g */ + int a,b; + + /* Set it to zero so we know what we are comparing to later */ + vars->MaxCwnd = 0; + + for (a = 0; a < (sizeof(struct tcp_vars) / sizeof(tcp_stat_var)); a++) { + if(tcp_names[a].web10g_name == NULL) + continue; + + /* Find the corresponding value */ + for (b = 0; ; b++){ + if(b == ARRAYSIZE(dataDumpSave->val)){ + log_println(1, "WARNING: Couldn't Find web10g var %s", tcp_names[a].web10g_name); + break; + } - return (0); + if (dataDumpSave->val[b].mask) continue; + if(strcmp(tcpe_var_array[b].name, tcp_names[a].web10g_name) == 0){ + ((tcp_stat_var *) vars)[a] = dataDumpSave->val[b].uv32; + log_println(5, "Found %s : %i", tcp_names[a].web10g_name, ((tcp_stat_var *) vars)[a]); + break; + } + } + + } + + /* Now lets deal to those things which are no longer in web10g */ + vars->AckPktsOut = 0; + vars->Sndbuf = X_Sndbuf; + vars->MaxCwnd = MAX(vars->MaxSsCwnd,vars->MaxCaCwnd); + + /* Free the data */ + tcpe_data_free(&dataDumpSave); + dataDumpSave = NULL; + return 0; +#endif } + + +#ifdef FORCE_WEB100 /** * Routine to read snaplog file and determine the number of times the * congestion window is reduced. @@ -687,7 +1047,7 @@ * @return Integer, 0 on success, -1 on failure */ -int CwndDecrease(web100_agent* agent, char* logname, u_int32_t *dec_cnt, +int CwndDecrease(tcp_stat_agent agent, char* logname, u_int32_t *dec_cnt, u_int32_t *same_cnt, u_int32_t *inc_cnt) { web100_var* var; char buff[256]; @@ -751,7 +1111,9 @@ *inc_cnt, *dec_cnt, *same_cnt); return (0); } +#endif /* web10g TODO when logging is do-able*/ +#ifdef FORCE_WEB100 /** * Generate TCP/IP checksum for our packet * @@ -939,3 +1301,4 @@ return (-1); return (0); } +#endif Index: src/kernel_config.h =================================================================== --- src/kernel_config.h (revision 0) +++ src/kernel_config.h (revision 0) @@ -0,0 +1,16 @@ +/* + * This contains functions declaractions used by ndt to tweak kernel settings. + * This uses the /proc/sys interface. + * + * Author: Richard Sanger + */ + +#ifndef SRC_KERNEL_CONFIG_H_ +#define SRC_KERNEL_CONFIG_H_ + +int check_kernel(int autofix); +int revert_congestion(); +int start_tcpe(); +int revert_tcpe(); + +#endif // SRC_KERNEL_CONFIG_H_ Index: src/test_c2s_srv.c =================================================================== --- src/test_c2s_srv.c (revision 796) +++ src/test_c2s_srv.c (working copy) @@ -61,10 +61,13 @@ * -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; + /* Group only used for web100 */ + 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 @@ 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; +#ifdef FORCE_WEB100 snapArgs.log = NULL; +#endif snapArgs.delay = options->snapDelay; wait_sig = 0; @@ -253,7 +254,7 @@ I2Addr src_addr = I2AddrByLocalSockFD(get_errhandle(), recvsfd, 0); // Get web100 connection. Used to collect web100 variable statistics - conn = web100_connection_from_socket(agent, recvsfd); + conn = tcp_stat_connection_from_socket(agent, recvsfd); // set up packet tracing. Collected data is used for bottleneck link // calculations @@ -281,10 +282,13 @@ &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 */ } // Get data collected from packet tracing into the C2S "ndttrace" file + /* What is this actually doing? Its seems to be waiting for + * "Ready" to come through on the pipe ?? */ memset(tmpstr, 0, 256); for (i = 0; i < 5; i++) { msgretvalue = read(mon_pipe1[0], tmpstr, 128); @@ -292,7 +296,7 @@ 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", @@ -331,6 +335,7 @@ } start_snap_worker(&snapArgs, agent, NULL, options->snaplog, &workerThreadId, meta.c2s_snaplog, options->c2s_logname, conn, group); + // Wait on listening socket and read data once ready. tmptime = secs(); sel_tv.tv_sec = 11; // time out after 11 seconds @@ -375,14 +380,20 @@ // 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); + /*close(recvsfd); + close(testOptions->c2ssockfd);*/ + // Lets move these :) + // Next, send speed-chk a flag to retrieve the data it collected. // Skip this step if speed-chk isn't running. + // Now close sockets once data is recevied + close(recvsfd); + close(testOptions->c2ssockfd); + if (getuid() == 0) { log_println(1, "Signal USR1(%d) sent to child [%d]", SIGUSR1, c2s_childpid); @@ -434,7 +445,7 @@ } } } - + // An empty TEST_FINALIZE message is sent to conclude the test send_msg(ctlsockfd, TEST_FINALIZE, "", 0); Index: src/test_s2c_srv.c =================================================================== --- src/test_s2c_srv.c (revision 796) +++ src/test_s2c_srv.c (working copy) @@ -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 @@ * @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,26 @@ * -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) { +#ifdef FORCE_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; +#else /* web10g */ + tcpe_data* snap; +#endif + tcp_stat_connection conn; + /* Just a holder for web10g */ + tcp_stat_group group; int ret; // ctrl protocol read/write return status int j, k, n; int xmitsfd; // transmit (i.e server) socket fd @@ -101,16 +117,6 @@ 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 +130,9 @@ SnapArgs snapArgs; snapArgs.snap = NULL; +#ifdef FORCE_WEB100 snapArgs.log = NULL; +#endif snapArgs.delay = options->snapDelay; wait_sig = 0; @@ -224,7 +232,7 @@ 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,8 +284,9 @@ } } 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 if (xmitsfd > 0) { @@ -326,8 +335,9 @@ /* experimental code, delete when finished */ setCwndlimit(conn, group, agent, options); + /* End of test code */ - + // create directory to write web100 snaplog trace create_client_logdir((struct sockaddr *) &cli_addr, clilen, options->s2c_logname, sizeof(options->s2c_logname), @@ -340,10 +350,15 @@ // system("/sbin/sysctl -w net.ipv4.route.flush=1"); system("echo 1 > /proc/sys/net/ipv4/route/flush"); } +#ifdef FORCE_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); +#else /* Web10g */ + /* One data snap includes all 'groups' in web10g */ + tcpe_data_new(&snap); +#endif // fill send buffer with random printable data for throughput test bytes_written = 0; @@ -392,6 +407,7 @@ if (options->avoidSndBlockUp) { // Do not block send buffers pthread_mutex_lock(&mainmutex); +#ifdef FORCE_WEB100 // get details of next sequence # to be sent and fetch value from // snap file web100_agent_find_var_and_group(agent, "SndNxt", &group, @@ -407,6 +423,16 @@ lastunackedseq = atoi( web100_value_to_text(web100_get_var_type(var), tmpstr)); +#else /* web10g */ + struct tcpe_val value; + // get details of next sequence # to be sent and fetch value from + // snap file + web10g_find_val(snapArgs.snap, "SndNxt", &value); + nextseqtosend = value.uv32; + // get oldest un-acked sequence number + 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 @@ -462,9 +488,12 @@ log_println(6, "S2C test - failed to send test message to pid=%d", s2c_childpid); - +#ifdef FORCE_WEB100 web100_snap(rsnap); web100_snap(tsnap); +#else /* web10g */ + tcpe_read_vars(snap, conn, agent); +#endif log_println(1, "sent %d bytes to client in %0.2f seconds", (int) bytes_written, tx_duration); @@ -545,13 +574,18 @@ /* alarm(30); */ // 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); + s2c_childpid); +#ifdef FORCE_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); +#else /* web10g*/ + 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) { Index: src/testoptions.c =================================================================== --- src/testoptions.c (revision 796) +++ src/testoptions.c (working copy) @@ -24,11 +24,12 @@ // 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; // web_100/10g agent pointer CwndPeaks* peaks; // data indicating Cwnd values int writeSnap; // enable writing snaplog } WorkerArgs; + int workerLoop = 0; pthread_mutex_t mainmutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t maincond = PTHREAD_COND_INITIALIZER; @@ -45,16 +46,28 @@ * @param snap Web100 snapshot structure */ +#ifdef FORCE_WEB100 void findCwndPeaks(web100_agent* agent, CwndPeaks* peaks, web100_snapshot* snap) { web100_group* group; web100_var* var; + char tmpstr[256]; +#else /* Must be web10g */ +void findCwndPeaks(struct tcpe_client * client, CwndPeaks* peaks, + tcpe_data* snap) { + struct tcpe_val value; +#endif int CurCwnd; - char tmpstr[256]; + +#ifdef FORCE_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)); +#else /* Must be web10g */ + web10g_find_val(snap, "CurCwnd", &value); + CurCwnd = value.uv32; +#endif if (slowStart) { if (CurCwnd < prevCWNDval) { @@ -108,9 +121,12 @@ void* snapWorker(void* arg) { + /* WARNING void* arg i.e workerArgs is on the stack of the function + * below and doesn't exist forever start_snap_worker and is valid for + * a very short time*/ 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 +152,7 @@ pthread_mutex_unlock(&mainmutex); break; } +#ifdef FORCE_WEB100 web100_snap(snapArgs->snap); if (peaks) { findCwndPeaks(agent, peaks, snapArgs->snap); @@ -143,6 +160,15 @@ if (writeSnap) { web100_log_write(snapArgs->log, snapArgs->snap); } +#else /* Must be web10g */ + 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); } @@ -258,21 +284,26 @@ * @param web100_connection connection pointer * @param web100_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; workerArgs.snapArgs = snaparg; - workerArgs.agent = agentarg; workerArgs.peaks = peaks; workerArgs.writeSnap = snaplogenabled; - + workerArgs.agent = agentarg; + snaparg->conn = conn; // Not actaully used by web100 +#ifdef FORCE_WEB100 group = web100_group_find(agentarg, "read"); snaparg->snap = web100_snapshot_alloc(group, conn); +#else /* web10g */ + tcpe_data_new(&snaparg->snap); +#endif if (snaplogenabled) { // memcpy(metafilevariablename, metafilename, strlen(metafilename)); @@ -280,7 +311,9 @@ // just the file name, but full filename is needed to open the log file fplocal = fopen(get_logfile(), "a"); +#ifdef FORCE_WEB100 snaparg->log = web100_log_open_write(metafilename, conn, group); +#endif /* TODO web10g logging */ if (fplocal == NULL) { log_println( 0, @@ -302,10 +335,16 @@ pthread_mutex_lock(&mainmutex); workerLoop= 1; // obtain web100 snap into "snaparg.snap" +#ifdef FORCE_WEB100 web100_snap(snaparg->snap); if (snaplogenabled) { web100_log_write(snaparg->log, snaparg->snap); } +#else /* web10g */ + tcpe_read_vars(snaparg->snap, conn, agentarg); + /* TODO logging */ +#endif + pthread_cond_wait(&maincond, &mainmutex); pthread_mutex_unlock(&mainmutex); } @@ -325,11 +364,17 @@ pthread_join(*workerThreadId, NULL); } // close writing snaplog, if snaplog recording is enabled +#ifdef FORCE_WEB100 if (snaplogenabled) { web100_log_close_write(snapArgs_ptr->log); } +#endif /* TODO web10g */ +#ifdef FORCE_WEB100 web100_snapshot_free(snapArgs_ptr->snap); +#else /* web10g */ + tcpe_data_free(&snapArgs_ptr->snap); +#endif } /** @@ -415,9 +460,14 @@ * @param group_arg web100 group pointer * @param agentarg web100 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) { +#ifdef FORCE_WEB100 web100_var *LimRwin, *yar; +#else /* web10g */ + struct tcpe_val LimRwin, yar; +#endif u_int32_t limrwin_val; char yuff[32]; @@ -427,6 +477,7 @@ if (connarg != NULL) { log_println(1, "Got web100 connection pointer for recvsfd socket\n"); +#ifdef FORCE_WEB100 web100_agent_find_var_and_group(agentarg, "CurMSS", &grouparg, &yar); web100_raw_read(yar, connarg, yuff); @@ -442,6 +493,15 @@ log_print(1, "now write %d to limit the Receive window", limrwin_val); web100_raw_write(LimRwin, connarg, &limrwin_val); +#else /* web10g */ + 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"); } } Index: src/testoptions.h =================================================================== --- src/testoptions.h (revision 796) +++ src/testoptions.h (working copy) @@ -47,11 +47,13 @@ // Snap log characteristics typedef struct snapArgs { - web100_snapshot* snap; // web_100 snapshot indicator - web100_log* log; // web_100 log + tcp_stat_connection conn; // Only needed by web10g + tcp_stat_snap snap; // web_100 snapshot indicator + tcp_stat_log log; // web_100 log (TODO - not used by 10g yet) int delay; // periodicity, in ms, of collecting snap } SnapArgs; + int wait_sig; int initialize_tests(int ctlsockfd, TestOptions* testOptions, @@ -59,27 +61,24 @@ 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 not_usedagent, TestOptions* testOptions, int conn_options); +void start_snap_worker(SnapArgs *snaparg, tcp_stat_agent agentarg, + CwndPeaks* peaks, char snaplogenabled, + pthread_t *wrkrthreadidarg, char *metafilevariablename, + char *metafilename, tcp_stat_connection conn, + tcp_stat_group group); +void setCwndlimit(tcp_stat_connection connarg, tcp_stat_group grouparg, + tcp_stat_agent agentarg, Options* optionsarg); int getCurrentTest(); void setCurrentTest(int testId); -// void start_snap_worker(SnapArgs *snaparg, web100_agent *agentarg, -void start_snap_worker(SnapArgs *snaparg, web100_agent *agentarg, - CwndPeaks* peaks, char snaplogenabled, - pthread_t *wrkrthreadidarg, char *metafilevariablename, - char *metafilename, web100_connection* conn, - web100_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); - int is_buffer_clogged(int nextseqtosend, int lastunackedseq); void stop_packet_trace(int *monpipe_arr); Index: src/test_mid_srv.c =================================================================== --- src/test_mid_srv.c (revision 796) +++ src/test_mid_srv.c (working copy) @@ -9,7 +9,7 @@ * Author: kkumar */ -#include +#include #include #include #include @@ -48,8 +48,7 @@ * 3 Ð Received message is invalid * */ - -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 +65,9 @@ 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 @@ -236,7 +237,7 @@ buff[0] = '\0'; // get web100 connection data - if ((conn = web100_connection_from_socket(agent, midsfd)) == NULL) { + if ((conn = tcp_stat_connection_from_socket(agent, midsfd)) == 0) { log_println( 0, "!!!!!!!!!!! test_mid() failed to get web100 connection data, rc=%d", @@ -246,7 +247,7 @@ } // 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)); Index: src/usage.c =================================================================== --- src/usage.c (revision 796) +++ src/usage.c (working copy) @@ -69,6 +69,7 @@ printf(" -L, --log_dir DIR - specify the base directory for snaplog and tcpdump files\n"); printf(" (default %s/serverdata)\n", BASEDIR); printf(" -S, --logfacility #F - specify syslog facility name\n"); + printf(" -k, --kernelconfig - Automatically configure kernel settings for best results\n"); printf(" Note: this doesn't enable 'syslog'\n\n"); #ifdef EXPERIMENTAL_ENABLED printf(" Experimental code:\n\n"); Index: src/Makefile.am =================================================================== --- src/Makefile.am (revision 796) +++ src/Makefile.am (working copy) @@ -25,7 +25,7 @@ if HAVE_WEB100 bin_PROGRAMS = web100clt analyze viewtrace tr-mkmap genplot if HAVE_PCAP_H -sbin_PROGRAMS = fakewww web100srv +sbin_PROGRAMS = fakewww web100srv else sbin_PROGRAMS = fakewww endif @@ -33,6 +33,22 @@ bin_PROGRAMS = web100clt endif +if HAVE_TCPE +if HAVE_WEB100 +if HAVE_PCAP_H +sbin_PROGRAMS += web10gsrv +endif +endif +endif + +if HAVE_TCPE +if !HAVE_WEB100 +if HAVE_PCAP_H +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 +62,7 @@ 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 @@ -56,15 +72,24 @@ web100srv_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 + test_c2s_srv.c test_s2c_srv.c test_mid_srv.c kernel_coalesce.c kernel_config.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 kernel_coalesce.c kernel_config.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) @@ -88,5 +113,5 @@ EXTRA_DIST = clt_tests.h logging.h mrange.h network.h protocol.h testoptions.h test_sfw.h test_meta.h \ troute.h tr-tree.h usage.h utils.h varinfo.h web100-admin.h web100srv.h ndt_odbc.h runningtest.h ndtptestconstants.h \ - heuristics.h strlutils.h test_results_clt.h tests_srv.h + heuristics.h strlutils.h test_results_clt.h tests_srv.h kernel_coalesce.h kernel_config.h Index: src/web100srv.c =================================================================== --- src/web100srv.c (revision 796) +++ src/web100srv.c (working copy) @@ -86,6 +86,8 @@ #include "strlutils.h" #include "heuristics.h" #include "tests_srv.h" +#include "kernel_coalesce.h" +#include "kernel_config.h" static char lgfn[FILENAME_SIZE]; // log file name static char wvfn[FILENAME_SIZE]; // file name of web100-variables list @@ -166,6 +168,7 @@ { "record", 0, 0, 'r' }, { "syslog", 0, 0, 's' }, { "tcpdump", 0, 0, 't' }, { "version", 0, 0, 'v' }, { "gzip", 0, 0, 'z' }, { "config", 1, 0, 'c' }, + { "kernelconfig", 0, 0, 'k'}, #ifdef EXPERIMENTAL_ENABLED { "avoidsndblockup", 0, 0, 306}, { "snaplog", 0, 0, 307}, @@ -457,6 +460,13 @@ exit(-2); break; case SIGINT: + if(getpid() == ndtpid){ + revert_coalesce(); + revert_congestion(); +#ifndef FORCE_WEB100 + revert_tcpe(); +#endif + } exit(0); case SIGTERM: if (getpid() == ndtpid) { @@ -466,19 +476,28 @@ ndtpid); break; } + if(getpid() == ndtpid){ + revert_coalesce(); + revert_congestion(); +#ifndef FORCE_WEB100 + revert_tcpe(); +#endif + } exit(0); case SIGUSR1: + /* SIGUSR1 is used exclusively by C2S, to interrupt the pcap capture*/ log_println(6, - "DEBUG, caught SIGUSR1, setting sig1 flag to force exit"); + "DEBUG, caught SIGUSR1, setting sig1 flag and calling force_breakloop"); + force_breakloop(); sig1 = 1; - /* check_signal_flags(); */ break; case SIGUSR2: + /* SIGUSR2 is used exclusively by S2C, to interrupt the pcap capture*/ log_println(6, - "DEBUG, caught SIGUSR2, setting sig2 flag to force exit"); + "DEBUG, caught SIGUSR2, setting sig2 flag and calling force_breakloop"); + force_breakloop(); sig2 = 1; - /* check_signal_flags(); */ break; case SIGALRM: @@ -552,8 +571,7 @@ 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. * At this point read the existing log file and generate the necessary @@ -628,8 +646,12 @@ set_debuglvl(atoi(val)); continue; } else if (strncasecmp(key, "variable_file", 6) == 0) { +#ifdef FORCE_WEB100 snprintf(wvfn, sizeof(wvfn), "%s", val); VarFileName = wvfn; +#else + log_println(0, "WEB10G doesn't need a variable file, ignoring"); +#endif continue; } else if (strncasecmp(key, "log_file", 3) == 0) { snprintf(lgfn, sizeof(lgfn), "%s", val); @@ -834,12 +856,6 @@ 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) { @@ -899,8 +915,9 @@ * @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; char date[32]; // date indicator char spds[4][256]; // speed "bin" array containing counters for speeds char logstr1[4096], logstr2[1024]; // log @@ -908,18 +925,10 @@ 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; + + /* TCP variables used in calculations */ + 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 +983,6 @@ 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()); @@ -989,11 +996,11 @@ for (ret = 0; ret < 256; ret++) spds[spd_index][ret] = 0x00; 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); send_msg(ctlsockfd, MSG_LOGIN, buff, strlen(buff)); @@ -1086,75 +1093,70 @@ // Get web100 vars // ...determine number of times congestion window has been changed +#ifdef FORCE_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 +/* TODO remove #ifdef once CwndDecrease has a web10g version + * looks like these variables dec_cnt ... are only used here and logged.*/ + // ...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); @@ -1175,8 +1177,8 @@ 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 +1215,7 @@ // 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,12 +1224,12 @@ 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, + if (detect_DSLCablelink(vars.SndLimTimeSender, vars.SndLimTransSender, realthruput, bw_theortcl, link)) link = LINK_DSLORCABLE; @@ -1238,7 +1240,7 @@ // ...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 +1274,7 @@ 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 +1297,15 @@ 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 +1316,15 @@ 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, + 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,39 +1344,39 @@ 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, + 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( @@ -1382,19 +1384,19 @@ "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 +1405,7 @@ "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,14 +1423,14 @@ * 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, + 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, MinRTT, PktsRetrans, Timeouts, - Sndbuf, MaxRwinRcvd, CurrentCwnd, mismatch, bad_cable, totalcnt, + 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); @@ -1444,16 +1446,22 @@ * @param argc Number of arguments * @param argv string command line arguments * */ -int main(int argc, char** argv) { + int main(int argc, char** argv) { +#ifndef FORCE_WEB100 + /* web10g */ + struct tcpe_error* err = NULL; +#endif + tcp_stat_agent agent = NULL; pid_t chld_pid = -1; int retcode; int tpid, mwaiting = 0; int ctlsockfd = -1; int c, chld_pipe[2]; int i, loopcnt, t_opts = 0; + int kernel_config = 0; struct sockaddr_storage cli_addr; struct sigaction new; - web100_agent* agent; + char *lbuf = NULL, *ctime(); char buff[32], tmpstr[256]; char test_suite[16]; @@ -1464,7 +1472,6 @@ struct ndtchild *tmp_ptr = NULL, *new_child = NULL, *mchild = NULL; time_t tt; socklen_t clilen; - I2Addr listenaddr = NULL; int listenfd; char* srcname = NULL; @@ -1555,7 +1562,7 @@ argc, argv, GETOPT_LONG_INET6( - GETOPT_LONG_EXP("adhmoqrstvzc:x:b:f:i:l:u:e:p:T:A:S:")), + GETOPT_LONG_EXP("adhmoqrstvzc:x:b:f:i:l:u:e:p:T:A:S:k")), long_options, 0)) != -1) { switch (c) { case '4': @@ -1616,7 +1623,11 @@ admin_view = 1; break; case 'f': +#ifdef FORCE_WEB100 VarFileName = optarg; +#else /* Web10G */ + log_println(2, "WEB10g doesn't need a varfile, ignored"); +#endif break; case 'i': device = optarg; @@ -1715,6 +1726,9 @@ case '?': short_usage(argv[0], ""); break; + case 'k': + kernel_config = 1; + break; } } @@ -1817,11 +1831,17 @@ err_sys("server: CreateListenSocket failed"); } listenfd = I2AddrFD(listenaddr); - + + if(listenfd == -1){ + /* If socket isn't opened this will segfault at FDSET for the select */ + log_println(0, "ERROR: Socket already in use this wont work"); + return 0; + } log_println(1, "server ready on port %s", port); - // Initialize Web100 structures - count_vars = web100_init(VarFileName); + /* Initialize Web100 structures */ + count_vars = tcp_stat_init(VarFileName); + if (count_vars == -1) { log_println(0, "No web100 variables file found, terminating program"); exit(-5); @@ -1889,7 +1909,18 @@ // RAC 7/14/09 get_iflist(); + disable_coalesce(kernel_config); + check_kernel(kernel_config); +#ifndef FORCE_WEB100 + if(start_tcpe() == -1){ + log_println(0, "FATAL: Web10G module cannot be loaded into kernel\n" + "\t - Either sudo modprobe tcp_estats_nl yourself\n" + "\t - or run this program as superuser\n"); + return 1; + } +#endif + for (i = 0; iflist.speed[i] > 0; i++) log_println(4, "Generated iflist with device=%s and if_speed=%d", iflist.name[i], iflist.speed[i]); @@ -1923,11 +1954,6 @@ "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); @@ -2099,7 +2125,7 @@ mclients); } } - + FD_ZERO(&rfd); FD_SET(listenfd, &rfd); if (waiting > 0) { // there are clients waiting @@ -2599,11 +2625,18 @@ "pid=%d", chld_pipe[0], chld_pipe[1], chld_pid); close(listenfd); close(chld_pipe[1]); +#ifdef FORCE_WEB100 if ((agent = web100_attach(WEB100_AGENT_TYPE_LOCAL, NULL)) == NULL) { web100_perror("web100_attach"); return 1; } +#else + 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 +2760,11 @@ child_sig(0); } close(ctlsockfd); +#ifdef FORCE_WEB100 web100_detach(agent); +#else + tcpe_client_destroy(&agent); +#endif log_free(); if (cputime && workerThreadId) { @@ -2755,6 +2792,11 @@ break; } } + revert_coalesce(); + revert_congestion(); +#ifndef FORCE_WEB100 + revert_tcpe(); +#endif } /** Index: configure.ac =================================================================== --- configure.ac (revision 796) +++ configure.ac (working copy) @@ -145,6 +145,18 @@ 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 @@ ]) -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 "" +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 @@ 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_WEB10GSRV" = "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 "" Index: Applet/Tcpbw100.java =================================================================== --- Applet/Tcpbw100.java (revision 796) +++ Applet/Tcpbw100.java (working copy) @@ -2746,7 +2746,13 @@ _sEmailText += sSysvar + " " + sStrval + "\n%0A"; if (sStrval.indexOf(".") == -1) { // no decimal point, hence // integer - iSysval = Integer.parseInt(sStrval); + try{ + iSysval = Integer.parseInt(sStrval); + // If it fails as an int it's probably to big since the values are often unsigned + } catch (Exception e) { + System.out.println("Exception occured reading a web100 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,7 +3379,7 @@ _txtStatistics.append("\n" + _resBundDisplayMsgs.getString("web100tcpOpts") + " \n"); _txtStatistics.append("RFC 2018 Selective Acknowledgment: "); - if (_iSACKEnabled == iZero) + if (_iSACKEnabled == 0) _txtStatistics.append(_resBundDisplayMsgs.getString("off") + "\n"); else @@ -3381,29 +3387,31 @@ + "\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"); - + /* TODO - Ideally print who disabled it - but need translations */ + _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"); - + /* TODO - Ideally print who disabled it - but need translations */ + _txtStatistics.append("RFC 1323 Window Scaling: "); if (_iMaxRwinRcvd < NDTConstants.TCP_MAX_RECV_WIN_SIZE) _iWinScaleRcvd = 0; //Max rec window size lesser than TCP's max value, @@ -3592,12 +3600,16 @@ // get client side IP String sClientSideClientIp = tokens.nextToken(); - k = sClientSideServerIp.indexOf("/"); - sClientSideServerIp = sClientSideServerIp.substring(k + 1); - + System.out.println("IP --" + sClientSideClientIp ); + k = sClientSideClientIp.indexOf("/"); + System.out.println("k is: " + k ); + sClientSideClientIp = sClientSideClientIp.substring(k + 1); + System.out.println("IP --" + sClientSideClientIp ); // 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"); Index: Applet/NDTConstants.java =================================================================== --- Applet/NDTConstants.java (revision 796) +++ Applet/NDTConstants.java (working copy) @@ -98,9 +98,25 @@ public static final String RTT_STR = "rtt"; // round trip time // Section: RFC 1323 options ( Seems like 0/1/2/3 are the options available) + // Not sure 0 is available maybe really old web100? - public static final int RFC_1323_DISABLED = 0; + 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 Index: Applet/Tcpbw100_msgs_en_US.properties =================================================================== --- Applet/Tcpbw100_msgs_en_US.properties (revision 796) +++ Applet/Tcpbw100_msgs_en_US.properties (working copy) @@ -32,7 +32,7 @@ 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 Index: WEB10G README =================================================================== --- WEB10G README (revision 0) +++ WEB10G README (revision 0) @@ -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 there 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??