/** * Given a snap (likely read from a log) read a value as a double. * Upon failure will exit the program with error code EXIT_FAILURE. * * * @param name The name of the variable to read in Web100/Web10G. * @param snap A Web100/Web10G snap * @param group A Web100 group - ignored by Web10G should be NULL * @param agent A Web100 agent - ignored by Web10G should be NULL * * @return The value of 'name' covnerted to a double. */ double tcp_stat_read_double(const char * name, tcp_stat_snap* snap, tcp_stat_group* group, tcp_stat_agent* agent) { #if USE_WEB100 web100_var* var; char buf[256]; #elif USE_WEB10G estats_val val; #endif #if USE_WEB100 if ((web100_agent_find_var_and_group(agent, name, &group, &var)) != WEB100_ERR_SUCCESS) { web100_perror("web100_agent_find_var_and_group"); exit(EXIT_FAILURE); } if ((web100_snap_read(var, snap, buf)) != WEB100_ERR_SUCCESS) { web100_perror("web100_snap_read"); exit(EXIT_FAILURE); } return atof( web100_value_to_text(web100_get_var_type(var), buf)); #elif USE_WEB10G int vartype = ESTATS_UNSIGNED32; /* ELAPSED_TIME not working in kernel patch, so use time on the * snap */ if (strcmp(name, ELAPSED_TIME) == 0) { val.masked = 0; val.uv32 = snap->tv.sec * 1000000 + snap->tv.usec - start_time; } else { vartype = web10g_find_val(snap, name, &val); if (vartype == -1) { printf("Bad vartype tcp_stat_read_double %s\n", name); exit(EXIT_FAILURE); } } switch (vartype) { case ESTATS_UNSIGNED64: return (double) val.uv64; case ESTATS_UNSIGNED32: return (double) val.uv32; case ESTATS_SIGNED32: return (double) val.sv32; case ESTATS_UNSIGNED16: return (double) val.uv16; case ESTATS_UNSIGNED8: return (double) val.uv8; } fprintf(stderr, "Bad vartype tcp_stat_read_double %s\n", name); exit(EXIT_FAILURE); #endif }
/** * Count the CWND peaks from a snapshot and record the minimal and maximum one. * Also record the number of transitions between increasing or decreasing * trends of the values. * @param agent Web100 agent used to track the connection * @param peaks Structure containing CWND peaks information * @param snap Web100 snapshot structure */ void findCwndPeaks(tcp_stat_agent* agent, CwndPeaks* peaks, tcp_stat_snap* snap) { int CurCwnd; #if USE_WEB100 web100_group* group; web100_var* var; char tmpstr[256]; #elif USE_WEB10G struct estats_val value; #endif #if USE_WEB100 web100_agent_find_var_and_group(agent, "CurCwnd", &group, &var); web100_snap_read(var, snap, tmpstr); CurCwnd = atoi(web100_value_to_text(web100_get_var_type(var), tmpstr)); #elif USE_WEB10G web10g_find_val(snap, "CurCwnd", &value); CurCwnd = value.uv32; #endif if (slowStart) { if (CurCwnd < prevCWNDval) { slowStart = 0; peaks->max = prevCWNDval; peaks->amount = 1; decreasing = 1; } } else { // current congestion window < previous value, so, decreasing if (CurCwnd < prevCWNDval) { // update values based on actual values if (prevCWNDval > peaks->max) { peaks->max = prevCWNDval; } if (!decreasing) { peaks->amount += 1; } decreasing = 1; // current congestion window size > previous value, } else if (CurCwnd > prevCWNDval) { // not decreasing. if ((peaks->min == -1) || (prevCWNDval < peaks->min)) { peaks->min = prevCWNDval; } decreasing = 0; } } prevCWNDval = CurCwnd; }
int main(int argc, char *argv[]) { web100_agent* agent; web100_connection* conn; web100_group* group; web100_var* var; char buf[256]; int cid; char** arg; argv0 = argv[0]; if (argc < 3) { usage(); exit(EXIT_FAILURE); } cid = atoi(argv[1]); if ((agent = web100_attach(WEB100_AGENT_TYPE_LOCAL, NULL)) == NULL) { web100_perror("web100_attach"); exit(EXIT_FAILURE); } if ((conn = web100_connection_lookup(agent, cid)) == NULL) { web100_perror("web100_connection_lookup"); exit(EXIT_FAILURE); } for (arg=&argv[2]; *arg; arg++) { if ((web100_agent_find_var_and_group(agent, *arg, &group, &var)) != WEB100_ERR_SUCCESS) { web100_perror("web100_agent_find_var_and_group"); exit(EXIT_FAILURE); } if ((web100_raw_read(var, conn, buf)) != WEB100_ERR_SUCCESS) { web100_perror("web100_raw_read"); exit(EXIT_FAILURE); } printf("%-20s: %s\n", *arg, web100_value_to_text(web100_get_var_type(var), buf)); } web100_detach(agent); return 0; }
/** * Get the title info from the snap. That is local address:port remote * address:port. * * For Web10G this also logs the start_time because this is expected * to be the first snap captured. * * @param snap A Web100/Web10G snap * @param agent A Web100 agent - ignored by Web10G should be NULL * @param group A Web100 group - ignored by Web10G should be NULL * @param title Upon return contains the string * "<localaddr>:<localport> --> <remoteaddr>" * @param remport Upon return contains the remote port as a string */ void get_title(tcp_stat_snap* snap, tcp_stat_agent* agent, tcp_stat_group* group, char* title, char* remport) { #if USE_WEB100 web100_var* var; char buf[128]; if ((web100_agent_find_var_and_group(agent, "LocalAddress", &group, &var)) != WEB100_ERR_SUCCESS) { web100_perror("web100_agent_find_var_and_group"); exit(EXIT_FAILURE); } if ((web100_snap_read(var, snap, buf)) != WEB100_ERR_SUCCESS) { web100_perror("web100_snap_read"); exit(EXIT_FAILURE); } strcpy(title, web100_value_to_text(web100_get_var_type(var), buf)); strncat(title, ":", 1); if ((web100_agent_find_var_and_group(agent, "LocalPort", &group, &var)) != WEB100_ERR_SUCCESS) { web100_perror("web100_agent_find_var_and_group"); exit(EXIT_FAILURE); } if ((web100_snap_read(var, snap, buf)) != WEB100_ERR_SUCCESS) { web100_perror("web100_snap_read"); exit(EXIT_FAILURE); } strcat(title, web100_value_to_text(web100_get_var_type(var), buf)); strncat(title, " --> ", 5); if ((web100_agent_find_var_and_group(agent, "RemAddress", &group, &var)) != WEB100_ERR_SUCCESS) { web100_perror("web100_agent_find_var_and_group"); exit(EXIT_FAILURE); } if ((web100_snap_read(var, snap, buf)) != WEB100_ERR_SUCCESS) { web100_perror("web100_snap_read"); exit(EXIT_FAILURE); } strcat(title, web100_value_to_text(web100_get_var_type(var), buf)); if ((web100_agent_find_var_and_group(agent, "RemPort", &group, &var)) != WEB100_ERR_SUCCESS) { web100_perror("web100_agent_find_var_and_group"); exit(EXIT_FAILURE); } if ((web100_snap_read(var, snap, buf)) != WEB100_ERR_SUCCESS) { web100_perror("web100_snap_read"); exit(EXIT_FAILURE); } strcpy(remport, web100_value_to_text(web100_get_var_type(var), buf)); /* printf("%s:%s\n", title, remport); */ #elif USE_WEB10G estats_error* err = NULL; struct estats_connection_tuple_ascii tuple_ascii; /* Quite a convenient little function we have */ if ((err = estats_connection_tuple_as_strings(&tuple_ascii, &snap->tuple)) != NULL) { /* If using the 3.5 kernel to make snaps it appears that the * address isn't filled in, so continue with unknown */ fprintf(stderr, "WARNING estats_connection_tuple_as_string has" " failed this could be due to using the 3.5 kernel patch which" " doesn't log this information!!!!"); estats_error_print(stderr, err); estats_error_free(&err); sprintf(title, "unknown:unknown --> unknown"); sprintf(remport, "unknown"); // exit(EXIT_FAILURE); } sprintf(title, "%s:%s --> %s", tuple_ascii.local_addr, tuple_ascii.local_port, tuple_ascii.rem_addr); sprintf(remport, "%s", tuple_ascii.rem_port); /* Notes the time fo this the first snap in the global start_time * because ElapsedTimeMicroSec is unimplemented in the kernel patch */ start_time = snap->tv.sec * 1000000 + snap->tv.usec; #endif }
/** * Set Cwnd limit * @param connarg tcp_stat_connection pointer * @param group_arg tcp_stat group pointer * @param agentarg tcp_stat agent pointer * */ void setCwndlimit(tcp_stat_connection connarg, tcp_stat_group* grouparg, tcp_stat_agent* agentarg, Options* optionsarg) { #if USE_WEB100 web100_var *LimRwin, *yar; #elif USE_WEB10G struct estats_val yar; #endif u_int32_t limrwin_val; if (optionsarg->limit > 0) { log_print(1, "Setting Cwnd limit - "); #if USE_WEB100 if (connarg != NULL) { log_println(1, "Got web100 connection pointer for recvsfd socket\n"); char yuff[32]; web100_agent_find_var_and_group(agentarg, "CurMSS", &grouparg, &yar); web100_raw_read(yar, connarg, yuff); log_println(1, "MSS = %s, multiplication factor = %d", web100_value_to_text(web100_get_var_type(yar), yuff), optionsarg->limit); limrwin_val = optionsarg->limit * (atoi( web100_value_to_text(web100_get_var_type(yar), yuff))); web100_agent_find_var_and_group(agentarg, "LimRwin", &grouparg, &LimRwin); log_print(1, "now write %d to limit the Receive window", limrwin_val); web100_raw_write(LimRwin, connarg, &limrwin_val); #elif USE_WEB10G if (connarg != -1) { log_println(1, "Got web10g connection for recvsfd socket\n"); web10g_get_val(agentarg, connarg, "CurMSS", &yar); log_println(1, "MSS = %s, multiplication factor = %d", yar.uv32, optionsarg->limit); limrwin_val = optionsarg->limit * yar.uv32; log_print(1, "now write %d to limit the Receive window", limrwin_val); estats_write_var("LimRwin", limrwin_val, connarg, agentarg); #endif log_println(1, " --- Done"); } } } /** * Check if receiver is clogged and use decision to temporarily * stop sending packets. * @param nextseqtosend integer indicating the Next Sequence Number To Be Sent * @param lastunackedseq integer indicating the oldest un-acked sequence number * @return integer indicating whether buffer is clogged * */ int is_buffer_clogged(int nextseqtosend, int lastunackedseq) { int recclog = 0; if ((RECLTH << 2) < (nextseqtosend - lastunackedseq - 1)) { recclog = 1; } return recclog; }