diff -r 7ffec3fab548 tools/xenstat/libxenstat/src/xenstat_linux.c --- a/tools/xenstat/libxenstat/src/xenstat_linux.c Wed Dec 02 08:52:50 2009 +0000 +++ b/tools/xenstat/libxenstat/src/xenstat_linux.c Wed Dec 02 12:34:49 2009 +0100 @@ -66,180 +66,182 @@ static const char PROCNETDEV_HEADER[] = /* Use excludeName parameter to avoid adding bridges we don't care about, eg. virbr0 */ char *getBridge(char *excludeName) { - struct dirent *de; - DIR *d; - - char tmp[256] = { 0 }, *bridge; - - bridge = (char *)malloc(16 * sizeof(char)); - - d = opendir("/sys/class/net"); - while ((de = readdir(d)) != NULL) { - if ((strlen(de->d_name) > 0) && (de->d_name[0] != '.') - && (strstr(de->d_name, excludeName) == NULL)) { - sprintf(tmp, "/sys/class/net/%s/bridge", de->d_name); - - if (access(tmp, F_OK) == 0) - bridge = de->d_name; - } - } - closedir(d); - - return bridge; + struct dirent *de; + DIR *d; + + char tmp[256] = { 0 }, *bridge; + + bridge = (char *)malloc(16 * sizeof(char)); + + d = opendir("/sys/class/net"); + while ((de = readdir(d)) != NULL) { + if ((strlen(de->d_name) > 0) && (de->d_name[0] != '.') + && (strstr(de->d_name, excludeName) == NULL)) { + sprintf(tmp, "/sys/class/net/%s/bridge", de->d_name); + + if (access(tmp, F_OK) == 0) + bridge = de->d_name; + } + } + + closedir(d); + + return bridge; } /* parseNetLine provides regular expression based parsing for lines from /proc/net/dev, all the */ /* information are parsed but not all are used in our case, ie. for xenstat */ int parseNetDevLine(char *line, char *iface, unsigned long long *rxBytes, unsigned long long *rxPackets, - unsigned long long *rxErrs, unsigned long long *rxDrops, unsigned long long *rxFifo, - unsigned long long *rxFrames, unsigned long long *rxComp, unsigned long long *rxMcast, - unsigned long long *txBytes, unsigned long long *txPackets, unsigned long long *txErrs, - unsigned long long *txDrops, unsigned long long *txFifo, unsigned long long *txColls, - unsigned long long *txCarrier, unsigned long long *txComp) -{ - /* Temporary/helper variables */ - int ret; - char *tmp; - int i = 0, x = 0, col = 0; - regex_t r; - regmatch_t matches[19]; - int num = 19; - - /* Regular exception to parse all the information from /proc/net/dev line */ - char *regex = "([^:]*):([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)" - "[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*" - "([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)"; - - /* Initialize all variables called has passed as non-NULL to zeros */ - if (iface != NULL) - memset(iface, 0, sizeof(iface)); - if (rxBytes != NULL) - *rxBytes = 0; - if (rxPackets != NULL) - *rxPackets = 0; - if (rxErrs != NULL) - *rxErrs = 0; - if (rxDrops != NULL) - *rxDrops = 0; - if (rxFifo != NULL) - *rxFifo = 0; - if (rxFrames != NULL) - *rxFrames = 0; - if (rxPackets != NULL) - *rxPackets = 0; - if (rxComp != NULL) - *rxComp = 0; - if (txBytes != NULL) - *txBytes = 0; - if (txPackets != NULL) - *txPackets = 0; - if (txErrs != NULL) - *txErrs = 0; - if (txDrops != NULL) - *txDrops = 0; - if (txFifo != NULL) - *txFifo = 0; - if (txColls != NULL) - *txColls = 0; - if (txCarrier != NULL) - *txCarrier = 0; - if (txComp != NULL) - *txComp = 0; - - if ((ret = regcomp(&r, regex, REG_EXTENDED))) { - regfree(&r); - return ret; - } - - tmp = (char *)malloc( sizeof(char) ); - if (regexec (&r, line, num, matches, REG_EXTENDED) == 0){ - for (i = 1; i < num; i++) { - /* The expression matches are empty sometimes so we need to check it first */ - if (matches[i].rm_eo - matches[i].rm_so > 0) { - /* Col variable contains current id of non-empty match */ - col++; - tmp = (char *)realloc(tmp, (matches[i].rm_eo - matches[i].rm_so + 1) * sizeof(char)); - for (x = matches[i].rm_so; x < matches[i].rm_eo; x++) - tmp[x - matches[i].rm_so] = line[x]; - - /* We populate all the fields from /proc/net/dev line */ - if (i > 1) { - unsigned long long ullTmp = strtoull(tmp, NULL, 10); - - switch (col) { - case 2: if (rxBytes != NULL) - *rxBytes = ullTmp; - break; - case 3: if (rxPackets != NULL) - *rxPackets = ullTmp; - break; - case 4: if (rxErrs != NULL) - *rxErrs = ullTmp; - break; - case 5: if (rxDrops != NULL) - *rxDrops = ullTmp; - break; - case 6: if (rxFifo != NULL) - *rxFifo = ullTmp; - break; - case 7: if (rxFrames != NULL) - *rxFrames = ullTmp; - break; - case 8: if (rxComp != NULL) - *rxComp = ullTmp; - break; - case 9: if (rxMcast != NULL) - *rxMcast = ullTmp; - break; - case 10: if (txBytes != NULL) - *txBytes = ullTmp; - break; - case 11: if (txPackets != NULL) - *txPackets = ullTmp; - break; - case 12: if (txErrs != NULL) - *txErrs = ullTmp; - case 13: if (txDrops != NULL) - *txDrops = ullTmp; - break; - case 14: if (txFifo != NULL) - *txFifo = ullTmp; - break; - case 15: if (txColls != NULL) - *txColls = ullTmp; - break; - case 16: if (txCarrier != NULL) - *txCarrier = ullTmp; - break; - case 17: if (txComp != NULL) - *txComp = ullTmp; - break; - } - } - else - /* There were errors when parsing this directly in RE. strpbrk() helps */ - if (iface != NULL) - strcpy(iface, strpbrk(tmp, "abcdefghijklmnopqrstvuwxyz0123456789")); - - memset(tmp, 0, matches[i].rm_eo - matches[i].rm_so); - } - } - } - - free(tmp); - regfree(&r); - - return 0; + unsigned long long *rxErrs, unsigned long long *rxDrops, unsigned long long *rxFifo, + unsigned long long *rxFrames, unsigned long long *rxComp, unsigned long long *rxMcast, + unsigned long long *txBytes, unsigned long long *txPackets, unsigned long long *txErrs, + unsigned long long *txDrops, unsigned long long *txFifo, unsigned long long *txColls, + unsigned long long *txCarrier, unsigned long long *txComp) +{ + /* Temporary/helper variables */ + int ret; + char *tmp; + int i = 0, x = 0, col = 0; + regex_t r; + regmatch_t matches[19]; + int num = 19; + + /* Regular exception to parse all the information from /proc/net/dev line */ + char *regex = "([^:]*):([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)" + "[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*" + "([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)"; + + /* Initialize all variables called has passed as non-NULL to zeros */ + if (iface != NULL) + memset(iface, 0, sizeof(iface)); + if (rxBytes != NULL) + *rxBytes = 0; + if (rxPackets != NULL) + *rxPackets = 0; + if (rxErrs != NULL) + *rxErrs = 0; + if (rxDrops != NULL) + *rxDrops = 0; + if (rxFifo != NULL) + *rxFifo = 0; + if (rxFrames != NULL) + *rxFrames = 0; + if (rxPackets != NULL) + *rxPackets = 0; + if (rxComp != NULL) + *rxComp = 0; + if (txBytes != NULL) + *txBytes = 0; + if (txPackets != NULL) + *txPackets = 0; + if (txErrs != NULL) + *txErrs = 0; + if (txDrops != NULL) + *txDrops = 0; + if (txFifo != NULL) + *txFifo = 0; + if (txColls != NULL) + *txColls = 0; + if (txCarrier != NULL) + *txCarrier = 0; + if (txComp != NULL) + *txComp = 0; + + if ((ret = regcomp(&r, regex, REG_EXTENDED))) { + regfree(&r); + return ret; + } + + tmp = (char *)malloc( sizeof(char) ); + if (regexec (&r, line, num, matches, REG_EXTENDED) == 0){ + for (i = 1; i < num; i++) { + /* The expression matches are empty sometimes so we need to check it first */ + if (matches[i].rm_eo - matches[i].rm_so > 0) { + /* Col variable contains current id of non-empty match */ + col++; + tmp = (char *)realloc(tmp, (matches[i].rm_eo - + matches[i].rm_so + 1) * sizeof(char)); + for (x = matches[i].rm_so; x < matches[i].rm_eo; x++) + tmp[x - matches[i].rm_so] = line[x]; + + /* We populate all the fields from /proc/net/dev line */ + if (i > 1) { + unsigned long long ullTmp = strtoull(tmp, NULL, 10); + + switch (col) { + case 2: if (rxBytes != NULL) + *rxBytes = ullTmp; + break; + case 3: if (rxPackets != NULL) + *rxPackets = ullTmp; + break; + case 4: if (rxErrs != NULL) + *rxErrs = ullTmp; + break; + case 5: if (rxDrops != NULL) + *rxDrops = ullTmp; + break; + case 6: if (rxFifo != NULL) + *rxFifo = ullTmp; + break; + case 7: if (rxFrames != NULL) + *rxFrames = ullTmp; + break; + case 8: if (rxComp != NULL) + *rxComp = ullTmp; + break; + case 9: if (rxMcast != NULL) + *rxMcast = ullTmp; + break; + case 10: if (txBytes != NULL) + *txBytes = ullTmp; + break; + case 11: if (txPackets != NULL) + *txPackets = ullTmp; + break; + case 12: if (txErrs != NULL) + *txErrs = ullTmp; + break; + case 13: if (txDrops != NULL) + *txDrops = ullTmp; + break; + case 14: if (txFifo != NULL) + *txFifo = ullTmp; + break; + case 15: if (txColls != NULL) + *txColls = ullTmp; + break; + case 16: if (txCarrier != NULL) + *txCarrier = ullTmp; + break; + case 17: if (txComp != NULL) + *txComp = ullTmp; + break; + } + } + else + /* There were errors when parsing this directly in RE. strpbrk() helps */ + if (iface != NULL) + strcpy(iface, strpbrk(tmp, "abcdefghijklmnopqrstvuwxyz0123456789")); + + memset(tmp, 0, matches[i].rm_eo - matches[i].rm_so); + } + } + } + + free(tmp); + regfree(&r); + + return 0; } /* Collect information about networks */ int xenstat_collect_networks(xenstat_node * node) { - /* Helper variables for parseNetDevLine() function defined above */ - int i; - char line[512] = { 0 }, iface[16] = { 0 }, devBridge[16] = { 0 }, devNoBridge[16] = { 0 }; - unsigned long long rxBytes, rxPackets, rxErrs, rxDrops, rxFifo, rxFrames, rxComp, rxMcast; - unsigned long long txBytes, txPackets, txErrs, txDrops, txFifo, txColls, txCarrier, txComp; + /* Helper variables for parseNetDevLine() function defined above */ + int i; + char line[512] = { 0 }, iface[16] = { 0 }, devBridge[16] = { 0 }, devNoBridge[16] = { 0 }; + unsigned long long rxBytes, rxPackets, rxErrs, rxDrops, txBytes, txPackets, txErrs, txDrops; struct priv_data *priv = get_priv_data(node->handle); @@ -276,46 +278,50 @@ int xenstat_collect_networks(xenstat_nod fseek(priv->procnetdev, sizeof(PROCNETDEV_HEADER) - 1, SEEK_SET); - /* We get the bridge devices for use with bonding interface to get bonding interface stats */ - snprintf(devBridge, 16, "%s", getBridge("vir")); - snprintf(devNoBridge, 16, "p%s", devBridge); - - while (fgets(line, 512, priv->procnetdev)) { - xenstat_domain *domain; - xenstat_network net; - unsigned int domid; - - parseNetDevLine(line, iface, &rxBytes, &rxPackets, &rxErrs, &rxDrops, &rxFifo, &rxFrames, &rxComp, - &rxMcast, &txBytes, &txPackets, &txErrs, &txDrops, &txFifo, &txColls, &txCarrier, &txComp); - - /* If the device parsed is network bridge and both tx & rx packets are zero, we are most */ - /* likely using bonding so we alter the configuration for dom0 to have bridge stats */ - if ((strstr(iface, devBridge) != NULL) && (strstr(iface, devNoBridge) == NULL)) { - domain = xenstat_node_domain(node, 0); - for (i = 0; i < domain->num_networks; i++) { - if ((domain->networks[i].id == 0) && (domain->networks[i].tbytes == 0) - && (domain->networks[i].rbytes == 0)) { - domain->networks[i].tbytes = txBytes; - domain->networks[i].tpackets = txPackets; - domain->networks[i].rbytes = rxBytes; - domain->networks[i].rpackets = rxPackets; - } - } - } - else /* Otherwise we need to preserve old behaviour */ - if (strstr(iface, "vif") != NULL) { - sscanf(iface, "vif%u.%u", &domid, &net.id); - - net.tbytes = txBytes; - net.tpackets = txPackets; - net.terrs = txErrs; - net.tdrop = txDrops; - net.rbytes = rxBytes; - net.rpackets = rxPackets; - net.rerrs = rxErrs; - net.rdrop = rxDrops; - - /* FIXME: this does a search for the domid */ + /* We get the bridge devices for use with bonding interface to get bonding interface stats */ + snprintf(devBridge, 16, "%s", getBridge("vir")); + snprintf(devNoBridge, 16, "p%s", devBridge); + + while (fgets(line, 512, priv->procnetdev)) { + xenstat_domain *domain; + xenstat_network net; + unsigned int domid; + + parseNetDevLine(line, iface, &rxBytes, &rxPackets, &rxErrs, &rxDrops, NULL, NULL, NULL, + NULL, &txBytes, &txPackets, &txErrs, &txDrops, NULL, NULL, NULL, NULL); + + /* If the device parsed is network bridge and both tx & rx packets are zero, we are most */ + /* likely using bonding so we alter the configuration for dom0 to have bridge stats */ + if ((strstr(iface, devBridge) != NULL) && (strstr(iface, devNoBridge) == NULL)) { + domain = xenstat_node_domain(node, 0); + for (i = 0; i < domain->num_networks; i++) { + if ((domain->networks[i].id == 0) && (domain->networks[i].tbytes == 0) + && (domain->networks[i].rbytes == 0)) { + domain->networks[i].tbytes = txBytes; + domain->networks[i].tpackets = txPackets; + domain->networks[i].terrs = txErrs; + domain->networks[i].tdrop = txDrops; + domain->networks[i].rbytes = rxBytes; + domain->networks[i].rpackets = rxPackets; + domain->networks[i].rerrs = rxErrs; + domain->networks[i].rdrop = rxDrops; + } + } + } + else /* Otherwise we need to preserve old behaviour */ + if (strstr(iface, "vif") != NULL) { + sscanf(iface, "vif%u.%u", &domid, &net.id); + + net.tbytes = txBytes; + net.tpackets = txPackets; + net.terrs = txErrs; + net.tdrop = txDrops; + net.rbytes = rxBytes; + net.rpackets = rxPackets; + net.rerrs = rxErrs; + net.rdrop = rxDrops; + + /* FIXME: this does a search for the domid */ domain = xenstat_node_domain(node, domid); if (domain == NULL) { fprintf(stderr,