2007-11-14 11:58:36 +00:00
|
|
|
/*
|
2012-12-13 15:14:15 +00:00
|
|
|
* virstatslinux.c: Linux block and network stats.
|
2007-11-14 11:58:36 +00:00
|
|
|
*
|
2010-03-01 23:38:28 +00:00
|
|
|
* Copyright (C) 2007-2010 Red Hat, Inc.
|
2007-11-14 11:58:36 +00:00
|
|
|
*
|
2012-07-27 09:39:53 +00:00
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-27 09:39:53 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2007-11-14 11:58:36 +00:00
|
|
|
*
|
|
|
|
* Richard W.M. Jones <rjones@redhat.com>
|
|
|
|
*/
|
|
|
|
|
2008-01-29 18:15:54 +00:00
|
|
|
#include <config.h>
|
2007-11-14 11:58:36 +00:00
|
|
|
|
|
|
|
/* This file only applies on Linux. */
|
|
|
|
#ifdef __linux__
|
|
|
|
|
2010-03-09 18:22:22 +00:00
|
|
|
# include <stdio.h>
|
|
|
|
# include <stdlib.h>
|
|
|
|
# include <fcntl.h>
|
|
|
|
# include <string.h>
|
|
|
|
# include <unistd.h>
|
|
|
|
# include <regex.h>
|
|
|
|
|
|
|
|
# include "virterror_internal.h"
|
|
|
|
# include "datatypes.h"
|
2012-12-13 17:44:57 +00:00
|
|
|
# include "virutil.h"
|
2012-12-13 15:14:15 +00:00
|
|
|
# include "virstatslinux.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
# include "viralloc.h"
|
2011-07-19 18:32:58 +00:00
|
|
|
# include "virfile.h"
|
2010-03-09 18:22:22 +00:00
|
|
|
|
|
|
|
# define VIR_FROM_THIS VIR_FROM_STATS_LINUX
|
|
|
|
|
2007-11-14 11:58:36 +00:00
|
|
|
|
|
|
|
/*-------------------- interface stats --------------------*/
|
|
|
|
/* Just reads the named interface, so not Xen or QEMU-specific.
|
|
|
|
* NB. Caller must check that libvirt user is trying to query
|
|
|
|
* the interface of a domain they own. We do no such checking.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
2010-02-04 23:02:10 +00:00
|
|
|
linuxDomainInterfaceStats(const char *path,
|
|
|
|
struct _virDomainInterfaceStats *stats)
|
2007-11-14 11:58:36 +00:00
|
|
|
{
|
|
|
|
int path_len;
|
|
|
|
FILE *fp;
|
2007-11-15 17:45:44 +00:00
|
|
|
char line[256], *colon;
|
2007-11-14 11:58:36 +00:00
|
|
|
|
2012-10-17 09:23:12 +00:00
|
|
|
fp = fopen("/proc/net/dev", "r");
|
2007-11-14 11:58:36 +00:00
|
|
|
if (!fp) {
|
2010-02-04 23:02:10 +00:00
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Could not open /proc/net/dev"));
|
2007-11-14 11:58:36 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-10-17 09:23:12 +00:00
|
|
|
path_len = strlen(path);
|
2007-11-14 11:58:36 +00:00
|
|
|
|
2012-10-17 09:23:12 +00:00
|
|
|
while (fgets(line, sizeof(line), fp)) {
|
2007-11-14 11:58:36 +00:00
|
|
|
long long dummy;
|
|
|
|
long long rx_bytes;
|
|
|
|
long long rx_packets;
|
|
|
|
long long rx_errs;
|
|
|
|
long long rx_drop;
|
|
|
|
long long tx_bytes;
|
|
|
|
long long tx_packets;
|
|
|
|
long long tx_errs;
|
|
|
|
long long tx_drop;
|
|
|
|
|
2007-11-15 17:45:44 +00:00
|
|
|
/* The line looks like:
|
|
|
|
* " eth0:..."
|
|
|
|
* Split it at the colon.
|
|
|
|
*/
|
2012-10-17 09:23:12 +00:00
|
|
|
colon = strchr(line, ':');
|
2007-11-15 17:45:44 +00:00
|
|
|
if (!colon) continue;
|
|
|
|
*colon = '\0';
|
|
|
|
if (colon-path_len >= line &&
|
2012-10-17 09:23:12 +00:00
|
|
|
STREQ(colon-path_len, path)) {
|
2007-11-14 11:58:36 +00:00
|
|
|
/* IMPORTANT NOTE!
|
|
|
|
* /proc/net/dev vif<domid>.nn sees the network from the point
|
|
|
|
* of view of dom0 / hypervisor. So bytes TRANSMITTED by dom0
|
|
|
|
* are bytes RECEIVED by the domain. That's why the TX/RX fields
|
|
|
|
* appear to be swapped here.
|
|
|
|
*/
|
2012-10-17 09:23:12 +00:00
|
|
|
if (sscanf(colon+1,
|
|
|
|
"%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld",
|
|
|
|
&tx_bytes, &tx_packets, &tx_errs, &tx_drop,
|
|
|
|
&dummy, &dummy, &dummy, &dummy,
|
|
|
|
&rx_bytes, &rx_packets, &rx_errs, &rx_drop,
|
|
|
|
&dummy, &dummy, &dummy, &dummy) != 16)
|
2007-11-14 11:58:36 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
stats->rx_bytes = rx_bytes;
|
|
|
|
stats->rx_packets = rx_packets;
|
|
|
|
stats->rx_errs = rx_errs;
|
|
|
|
stats->rx_drop = rx_drop;
|
|
|
|
stats->tx_bytes = tx_bytes;
|
|
|
|
stats->tx_packets = tx_packets;
|
|
|
|
stats->tx_errs = tx_errs;
|
|
|
|
stats->tx_drop = tx_drop;
|
2012-10-17 09:23:12 +00:00
|
|
|
VIR_FORCE_FCLOSE(fp);
|
2007-11-14 11:58:36 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2010-11-17 02:13:29 +00:00
|
|
|
VIR_FORCE_FCLOSE(fp);
|
2007-11-14 11:58:36 +00:00
|
|
|
|
2012-07-18 10:26:24 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("/proc/net/dev: Interface not found"));
|
2007-11-14 11:58:36 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* __linux__ */
|