mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
xenstat: Fixes for 20528:e6e3bf767d16 (stats for dom0 network bonding)
In above c/s I introduced dom0 statistics for case we use network
bonding. The indentation was not good for xenstat C codebase and also
some modifications were done to the logic, mainly not using the parsed
variables we don't care about (as we care only about
{tx|rx}{bytes,packets,errs,drops} and no other variable from
/proc/net/dev) by passing NULLs to variables we don't care about. Also
dom0 statistics alteration was fixed to include {tx|rx}{drop,errs} for
dom0 (previous version of my patch was not having this code applied).
Signed-off-by: Michal Novotny <minovotn@redhat.com>
This commit is contained in:
1 parent
fe356defec
commit
80d4e9ca77
1 file changed
+191
-185
@@ -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;
|
||||
struct dirent *de;
|
||||
DIR *d;
|
||||
|
||||
char tmp[256] = { 0 }, *bridge;
|
||||
char tmp[256] = { 0 }, *bridge;
|
||||
|
||||
bridge = (char *)malloc(16 * sizeof(char));
|
||||
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);
|
||||
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);
|
||||
if (access(tmp, F_OK) == 0)
|
||||
bridge = de->d_name;
|
||||
}
|
||||
}
|
||||
|
||||
return bridge;
|
||||
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)
|
||||
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;
|
||||
/* 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 = "([^:]*):([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)"
|
||||
"[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*"
|
||||
"([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)[ ]*([^ ]*)";
|
||||
/* 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;
|
||||
/* 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;
|
||||
}
|
||||
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];
|
||||
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);
|
||||
/* 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"));
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
memset(tmp, 0, matches[i].rm_eo - matches[i].rm_so);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(tmp);
|
||||
regfree(&r);
|
||||
free(tmp);
|
||||
regfree(&r);
|
||||
|
||||
return 0;
|
||||
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_node * node)
|
||||
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);
|
||||
/* 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;
|
||||
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);
|
||||
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].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);
|
||||
/* 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 */
|
||||
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,
|
||||
|
||||