/* * virstatslinux.c: Linux block and network stats. * * Copyright (C) 2007-2010 Red Hat, Inc. * * 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 * License along with this library. If not, see * . * * Richard W.M. Jones */ #include /* This file only applies on Linux. */ #ifdef __linux__ # include # include # include # include # include # include # include "virerror.h" # include "datatypes.h" # include "virstatslinux.h" # include "viralloc.h" # include "virfile.h" # define VIR_FROM_THIS VIR_FROM_STATS_LINUX /*-------------------- 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 linuxDomainInterfaceStats(const char *path, struct _virDomainInterfaceStats *stats) { int path_len; FILE *fp; char line[256], *colon; fp = fopen("/proc/net/dev", "r"); if (!fp) { virReportSystemError(errno, "%s", _("Could not open /proc/net/dev")); return -1; } path_len = strlen(path); while (fgets(line, sizeof(line), fp)) { 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; /* The line looks like: * " eth0:..." * Split it at the colon. */ colon = strchr(line, ':'); if (!colon) continue; *colon = '\0'; if (colon-path_len >= line && STREQ(colon-path_len, path)) { /* IMPORTANT NOTE! * /proc/net/dev vif.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. */ 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) 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; VIR_FORCE_FCLOSE(fp); return 0; } } VIR_FORCE_FCLOSE(fp); virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("/proc/net/dev: Interface not found")); return -1; } #endif /* __linux__ */