[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH] Implement VBD and VIF handling on Solaris for libxenstat
# HG changeset patch # User john.levon@xxxxxxx # Date 1170985988 28800 # Node ID c2eb82b28b7d685cca993fd3fb2865051006ffc8 # Parent 546eef87339a3864af25a390457801dad737bf68 Implement VBD and VIF handling on Solaris for libxenstat. Also, fix up a confusion with ERR that was breaking xentop. Signed-off-by: John Levon <john.levon@xxxxxxx> diff --git a/tools/xenstat/libxenstat/Makefile b/tools/xenstat/libxenstat/Makefile --- a/tools/xenstat/libxenstat/Makefile +++ b/tools/xenstat/libxenstat/Makefile @@ -14,7 +14,6 @@ XEN_ROOT=../../.. include $(XEN_ROOT)/tools/Rules.mk -LINUX_ROOT := $(XEN_ROOT)/linux-2.6-xen-sparse prefix=/usr includedir=$(prefix)/include @@ -29,26 +28,40 @@ LIB=src/libxenstat.a LIB=src/libxenstat.a SHLIB=src/libxenstat.so.$(MAJOR).$(MINOR) SHLIB_LINKS=src/libxenstat.so.$(MAJOR) src/libxenstat.so -OBJECTS=src/xenstat.o +OBJECTS-y=src/xenstat.o +OBJECTS-$(CONFIG_Linux) += src/xenstat_linux.o +OBJECTS-$(CONFIG_SunOS) += src/xenstat_solaris.o SONAME_FLAGS=-Wl,$(SONAME_LDFLAG) -Wl,libxenstat.so.$(MAJOR) WARN_FLAGS=-Wall -Werror CFLAGS+=-Isrc -I$(XEN_LIBXC) -I$(XEN_XENSTORE) LDFLAGS+=-Lsrc -L$(XEN_XENSTORE)/ -L$(XEN_LIBXC)/ +LDLIBS-y = -lxenstore -lxenctrl +LDLIBS-$(CONFIG_SunOS) += -lkstat +ARLIBS-y = $(XEN_XENSTORE)/libxenstore.so $(XEN_LIBXC)/libxenctrl.so +ARLIBS-x86_64 = /usr/lib/amd64/libkstat.so +ARLIBS-x86_32 = /usr/lib/libkstat.so +ARLIBS-$(CONFIG_SunOS) += $(ARLIBS-$(XEN_TARGET_ARCH)) .PHONY: all all: $(LIB) -$(LIB): $(OBJECTS) - $(AR) rc $@ $^ $(XEN_XENSTORE)/libxenstore.so $(XEN_LIBXC)/libxenctrl.so +$(LIB): $(OBJECTS-y) + $(AR) rc $@ $^ $(ARLIBS-y) $(RANLIB) $@ -$(SHLIB): $(OBJECTS) - $(CC) $(CFLAGS) $(LDFLAGS) $(SONAME_FLAGS) $(SHLIB_CFLAGS) -o $@ $(OBJECTS) \ - -lxenstore -lxenctrl +$(SHLIB): $(OBJECTS-y) + $(CC) $(CFLAGS) $(LDFLAGS) $(SONAME_FLAGS) $(SHLIB_CFLAGS) -o $@ \ + $(OBJECTS-y) $(LDLIBS-y) -src/xenstat.o: src/xenstat.c src/xenstat.h +src/xenstat.o: src/xenstat.c src/xenstat.h src/xenstat_priv.h + $(CC) $(CFLAGS) $(WARN_FLAGS) -c -o $@ $< + +src/xenstat_linux.o: src/xenstat_linux.c src/xenstat_priv.h + $(CC) $(CFLAGS) $(WARN_FLAGS) -c -o $@ $< + +src/xenstat_solaris.o: src/xenstat_solaris.c src/xenstat_priv.h $(CC) $(CFLAGS) $(WARN_FLAGS) -c -o $@ $< src/libxenstat.so.$(MAJOR): $(LIB) @@ -140,5 +153,5 @@ endif .PHONY: clean clean: - rm -f $(LIB) $(SHLIB) $(SHLIB_LINKS) $(OBJECTS) \ + rm -f $(LIB) $(SHLIB) $(SHLIB_LINKS) $(OBJECTS-y) \ $(BINDINGS) $(BINDINGSRC) diff --git a/tools/xenstat/libxenstat/src/xenstat.c b/tools/xenstat/libxenstat/src/xenstat.c --- a/tools/xenstat/libxenstat/src/xenstat.c +++ b/tools/xenstat/libxenstat/src/xenstat.c @@ -15,89 +15,17 @@ * Lesser General Public License for more details. */ -#include <limits.h> +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + #include <stdlib.h> +#include <string.h> #include <stdio.h> -#include <string.h> #include <unistd.h> -#include <fcntl.h> -#include <dirent.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <xs.h> -#include "xenstat.h" - -#include "xenctrl.h" - -/* - * Types - */ -#define SHORT_ASC_LEN 5 /* length of 65535 */ -#define VERSION_SIZE (2 * SHORT_ASC_LEN + 1 + sizeof(xen_extraversion_t) + 1) - -struct xenstat_handle { - int xc_handle; - struct xs_handle *xshandle; /* xenstore handle */ - int page_size; - FILE *procnetdev; - DIR *sysfsvbd; - char xen_version[VERSION_SIZE]; /* xen version running on this node */ -}; - -struct xenstat_node { - xenstat_handle *handle; - unsigned int flags; - unsigned long long cpu_hz; - unsigned int num_cpus; - unsigned long long tot_mem; - unsigned long long free_mem; - unsigned int num_domains; - xenstat_domain *domains; /* Array of length num_domains */ -}; - -struct xenstat_domain { - unsigned int id; - char *name; - unsigned int state; - unsigned long long cpu_ns; - unsigned int num_vcpus; /* No. vcpus configured for domain */ - xenstat_vcpu *vcpus; /* Array of length num_vcpus */ - unsigned long long cur_mem; /* Current memory reservation */ - unsigned long long max_mem; /* Total memory allowed */ - unsigned int ssid; - unsigned int num_networks; - xenstat_network *networks; /* Array of length num_networks */ - unsigned int num_vbds; - xenstat_vbd *vbds; -}; - -struct xenstat_vcpu { - unsigned int online; - unsigned long long ns; -}; - -struct xenstat_network { - unsigned int id; - /* Received */ - unsigned long long rbytes; - unsigned long long rpackets; - unsigned long long rerrs; - unsigned long long rdrop; - /* Transmitted */ - unsigned long long tbytes; - unsigned long long tpackets; - unsigned long long terrs; - unsigned long long tdrop; -}; - -struct xenstat_vbd { - unsigned int dev; - unsigned long long oo_reqs; - unsigned long long rd_reqs; - unsigned long long wr_reqs; -}; -#define SYSFS_VBD_PATH "/sys/devices/xen-backend/" - + +#include "xenstat_priv.h" /* * Data-collection types @@ -125,17 +53,13 @@ typedef struct xenstat_collector { } xenstat_collector; static int xenstat_collect_vcpus(xenstat_node * node); -static int xenstat_collect_networks(xenstat_node * node); static int xenstat_collect_xen_version(xenstat_node * node); -static int xenstat_collect_vbds(xenstat_node * node); static void xenstat_free_vcpus(xenstat_node * node); static void xenstat_free_networks(xenstat_node * node); static void xenstat_free_xen_version(xenstat_node * node); static void xenstat_free_vbds(xenstat_node * node); static void xenstat_uninit_vcpus(xenstat_handle * handle); -static void xenstat_uninit_networks(xenstat_handle * handle); static void xenstat_uninit_xen_version(xenstat_handle * handle); -static void xenstat_uninit_vbds(xenstat_handle * handle); static char *xenstat_get_domain_name(xenstat_handle * handle, unsigned int domain_id); static void xenstat_prune_domain(xenstat_node *node, unsigned int entry); @@ -202,6 +126,7 @@ void xenstat_uninit(xenstat_handle * han collectors[i].uninit(handle); xc_interface_close(handle->xc_handle); xs_daemon_close(handle->xshandle); + free(handle->priv); free(handle); } } @@ -586,110 +511,12 @@ unsigned long long xenstat_vcpu_ns(xenst * Network functions */ -/* Expected format of /proc/net/dev */ -static const char PROCNETDEV_HEADER[] = - "Inter-| Receive |" - " Transmit\n" - " face |bytes packets errs drop fifo frame compressed multicast|" - "bytes packets errs drop fifo colls carrier compressed\n"; - -/* Collect information about networks */ -static int xenstat_collect_networks(xenstat_node * node) -{ - /* Open and validate /proc/net/dev if we haven't already */ - if (node->handle->procnetdev == NULL) { - char header[sizeof(PROCNETDEV_HEADER)]; - node->handle->procnetdev = fopen("/proc/net/dev", "r"); - if (node->handle->procnetdev == NULL) { - perror("Error opening /proc/net/dev"); - return 0; - } - - /* Validate the format of /proc/net/dev */ - if (fread(header, sizeof(PROCNETDEV_HEADER) - 1, 1, - node->handle->procnetdev) != 1) { - perror("Error reading /proc/net/dev header"); - return 0; - } - header[sizeof(PROCNETDEV_HEADER) - 1] = '\0'; - if (strcmp(header, PROCNETDEV_HEADER) != 0) { - fprintf(stderr, - "Unexpected /proc/net/dev format\n"); - return 0; - } - } - - /* Fill in networks */ - /* FIXME: optimize this */ - fseek(node->handle->procnetdev, sizeof(PROCNETDEV_HEADER) - 1, - SEEK_SET); - while (1) { - xenstat_domain *domain; - xenstat_network net; - unsigned int domid; - int ret = fscanf(node->handle->procnetdev, - "vif%u.%u:%llu%llu%llu%llu%*u%*u%*u%*u" - "%llu%llu%llu%llu%*u%*u%*u%*u\n", - &domid, &net.id, - &net.tbytes, &net.tpackets, &net.terrs, - &net.tdrop, - &net.rbytes, &net.rpackets, &net.rerrs, - &net.rdrop); - if (ret == EOF) - break; - if (ret != 10) { - unsigned int c; - do { - c = fgetc(node->handle->procnetdev); - } while (c != '\n' && c != EOF); - if (c == EOF) - break; - continue; - } - - /* FIXME: this does a search for the domid */ - domain = xenstat_node_domain(node, domid); - if (domain == NULL) { - fprintf(stderr, - "Found interface vif%u.%u but domain %u" - " does not exist.\n", domid, net.id, - domid); - continue; - } - if (domain->networks == NULL) { - domain->num_networks = 1; - domain->networks = malloc(sizeof(xenstat_network)); - } else { - struct xenstat_network *tmp; - domain->num_networks++; - tmp = realloc(domain->networks, - domain->num_networks * - sizeof(xenstat_network)); - if (tmp == NULL) - free(domain->networks); - domain->networks = tmp; - } - if (domain->networks == NULL) - return 0; - domain->networks[domain->num_networks - 1] = net; - } - - return 1; -} - /* Free network information */ static void xenstat_free_networks(xenstat_node * node) { unsigned int i; for (i = 0; i < node->num_domains; i++) free(node->domains[i].networks); -} - -/* Free network information in handle */ -static void xenstat_uninit_networks(xenstat_handle * handle) -{ - if(handle->procnetdev) - fclose(handle->procnetdev); } /* Get the network ID */ @@ -790,109 +617,12 @@ static void xenstat_uninit_xen_version(x * VBD functions */ -static int read_attributes_vbd(const char *vbd_directory, const char *what, char *ret, int cap) -{ - static char file_name[80]; - int fd, num_read; - - sprintf(file_name, "%s/%s/%s", SYSFS_VBD_PATH, vbd_directory, what); - fd = open(file_name, O_RDONLY, 0); - if (fd==-1) return -1; - num_read = read(fd, ret, cap - 1); - close(fd); - if (num_read<=0) return -1; - ret[num_read] = '\0'; - return num_read; -} - -/* Collect information about VBDs */ -static int xenstat_collect_vbds(xenstat_node * node) -{ - struct dirent *dp; - - if (node->handle->sysfsvbd == NULL) { - node->handle->sysfsvbd = opendir(SYSFS_VBD_PATH); - if (node->handle->sysfsvbd == NULL) { - perror("Error opening " SYSFS_VBD_PATH); - return 0; - } - } - - rewinddir(node->handle->sysfsvbd); - - for(dp = readdir(node->handle->sysfsvbd); dp != NULL ; - dp = readdir(node->handle->sysfsvbd)) { - xenstat_domain *domain; - xenstat_vbd vbd; - unsigned int domid; - int ret; - char buf[256]; - - - ret = sscanf(dp->d_name, "vbd-%u-%u", &domid, &vbd.dev); - if (ret != 2) { - continue; - } - printf("%s is VBD.\n",dp->d_name); - - domain = xenstat_node_domain(node, domid); - if (domain == NULL) { - fprintf(stderr, - "Found interface vbd-%u-%u but domain %u" - " does not exist.\n", - domid, vbd.dev, domid); - continue; - } - - if((read_attributes_vbd(dp->d_name, "statistics/oo_req", buf, 256)<=0) - || ((ret = sscanf(buf, "%llu", &vbd.oo_reqs)) != 1)) - { - continue; - } - - if((read_attributes_vbd(dp->d_name, "statistics/rd_req", buf, 256)<=0) - || ((ret = sscanf(buf, "%llu", &vbd.rd_reqs)) != 1)) - { - continue; - } - - if((read_attributes_vbd(dp->d_name, "statistics/wr_req", buf, 256)<=0) - || ((ret = sscanf(buf, "%llu", &vbd.wr_reqs)) != 1)) - { - continue; - } - - - if (domain->vbds == NULL) { - domain->num_vbds = 1; - domain->vbds = malloc(sizeof(xenstat_vbd)); - } else { - domain->num_vbds++; - domain->vbds = realloc(domain->vbds, - domain->num_vbds * - sizeof(xenstat_vbd)); - } - if (domain->vbds == NULL) - return 0; - domain->vbds[domain->num_vbds - 1] = vbd; - } - - return 1; -} - /* Free VBD information */ static void xenstat_free_vbds(xenstat_node * node) { unsigned int i; for (i = 0; i < node->num_domains; i++) free(node->domains[i].vbds); -} - -/* Free VBD information in handle */ -static void xenstat_uninit_vbds(xenstat_handle * handle) -{ - if (handle->sysfsvbd) - closedir(handle->sysfsvbd); } /* Get the major number of VBD device */ @@ -948,4 +678,3 @@ static void xenstat_prune_domain(xenstat strictly necessary but safer! */ memset(&node->domains[node->num_domains], 0, sizeof(xenstat_domain)); } - diff --git a/tools/xenstat/libxenstat/src/xenstat.h b/tools/xenstat/libxenstat/src/xenstat.h --- a/tools/xenstat/libxenstat/src/xenstat.h +++ b/tools/xenstat/libxenstat/src/xenstat.h @@ -16,6 +16,9 @@ */ /* libxenstat API */ + +#ifndef XENSTAT_H +#define XENSTAT_H /* Opaque handles */ typedef struct xenstat_handle xenstat_handle; @@ -176,3 +179,5 @@ unsigned long long xenstat_vbd_oo_reqs(x unsigned long long xenstat_vbd_oo_reqs(xenstat_vbd * vbd); unsigned long long xenstat_vbd_rd_reqs(xenstat_vbd * vbd); unsigned long long xenstat_vbd_wr_reqs(xenstat_vbd * vbd); + +#endif /* XENSTAT_H */ diff --git a/tools/xenstat/libxenstat/src/xenstat_linux.c b/tools/xenstat/libxenstat/src/xenstat_linux.c new file mode 100644 --- /dev/null +++ b/tools/xenstat/libxenstat/src/xenstat_linux.c @@ -0,0 +1,265 @@ +/* libxenstat: statistics-collection library for Xen + * Copyright (C) International Business Machines Corp., 2005 + * Authors: Josh Triplett <josht@xxxxxxxxxx> + * Judy Fischbach <jfisch@xxxxxxxxxx> + * David Hendricks <dhendrix@xxxxxxxxxx> + * + * 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. + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include <fcntl.h> +#include <dirent.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "xenstat_priv.h" + +#define SYSFS_VBD_PATH "/sys/devices/xen-backend/" + +struct priv_data { + FILE *procnetdev; + DIR *sysfsvbd; +}; + +static struct priv_data * +get_priv_data(xenstat_handle *handle) +{ + if (handle->priv != NULL) + return handle->priv; + + handle->priv = malloc(sizeof(struct priv_data)); + if (handle->priv == NULL) + return (NULL); + + ((struct priv_data *)handle->priv)->procnetdev = NULL; + ((struct priv_data *)handle->priv)->sysfsvbd = NULL; + + return handle->priv; +} + +/* Expected format of /proc/net/dev */ +static const char PROCNETDEV_HEADER[] = + "Inter-| Receive |" + " Transmit\n" + " face |bytes packets errs drop fifo frame compressed multicast|" + "bytes packets errs drop fifo colls carrier compressed\n"; + +/* Collect information about networks */ +int xenstat_collect_networks(xenstat_node * node) +{ + struct priv_data *priv = get_priv_data(node->handle); + + if (priv == NULL) { + perror("Allocation error"); + return 0; + } + + /* Open and validate /proc/net/dev if we haven't already */ + if (priv->procnetdev == NULL) { + char header[sizeof(PROCNETDEV_HEADER)]; + priv->procnetdev = fopen("/proc/net/dev", "r"); + if (priv->procnetdev == NULL) { + perror("Error opening /proc/net/dev"); + return 0; + } + + /* Validate the format of /proc/net/dev */ + if (fread(header, sizeof(PROCNETDEV_HEADER) - 1, 1, + priv->procnetdev) != 1) { + perror("Error reading /proc/net/dev header"); + return 0; + } + header[sizeof(PROCNETDEV_HEADER) - 1] = '\0'; + if (strcmp(header, PROCNETDEV_HEADER) != 0) { + fprintf(stderr, + "Unexpected /proc/net/dev format\n"); + return 0; + } + } + + /* Fill in networks */ + /* FIXME: optimize this */ + fseek(priv->procnetdev, sizeof(PROCNETDEV_HEADER) - 1, + SEEK_SET); + while (1) { + xenstat_domain *domain; + xenstat_network net; + unsigned int domid; + int ret = fscanf(priv->procnetdev, + "vif%u.%u:%llu%llu%llu%llu%*u%*u%*u%*u" + "%llu%llu%llu%llu%*u%*u%*u%*u\n", + &domid, &net.id, + &net.tbytes, &net.tpackets, &net.terrs, + &net.tdrop, + &net.rbytes, &net.rpackets, &net.rerrs, + &net.rdrop); + if (ret == EOF) + break; + if (ret != 10) { + unsigned int c; + do { + c = fgetc(priv->procnetdev); + } while (c != '\n' && c != EOF); + if (c == EOF) + break; + continue; + } + + /* FIXME: this does a search for the domid */ + domain = xenstat_node_domain(node, domid); + if (domain == NULL) { + fprintf(stderr, + "Found interface vif%u.%u but domain %u" + " does not exist.\n", domid, net.id, + domid); + continue; + } + if (domain->networks == NULL) { + domain->num_networks = 1; + domain->networks = malloc(sizeof(xenstat_network)); + } else { + struct xenstat_network *tmp; + domain->num_networks++; + tmp = realloc(domain->networks, + domain->num_networks * + sizeof(xenstat_network)); + if (tmp == NULL) + free(domain->networks); + domain->networks = tmp; + } + if (domain->networks == NULL) + return 0; + domain->networks[domain->num_networks - 1] = net; + } + + return 1; +} + +/* Free network information in handle */ +void xenstat_uninit_networks(xenstat_handle * handle) +{ + struct priv_data *priv = get_priv_data(handle); + if (priv != NULL && priv->procnetdev != NULL) + fclose(priv->procnetdev); +} + +static int read_attributes_vbd(const char *vbd_directory, const char *what, char *ret, int cap) +{ + static char file_name[80]; + int fd, num_read; + + sprintf(file_name, "%s/%s/%s", SYSFS_VBD_PATH, vbd_directory, what); + fd = open(file_name, O_RDONLY, 0); + if (fd==-1) return -1; + num_read = read(fd, ret, cap - 1); + close(fd); + if (num_read<=0) return -1; + ret[num_read] = '\0'; + return num_read; +} + +/* Collect information about VBDs */ +int xenstat_collect_vbds(xenstat_node * node) +{ + struct dirent *dp; + struct priv_data *priv = get_priv_data(node->handle); + + if (priv == NULL) { + perror("Allocation error"); + return 0; + } + + if (priv->sysfsvbd == NULL) { + priv->sysfsvbd = opendir(SYSFS_VBD_PATH); + if (priv->sysfsvbd == NULL) { + perror("Error opening " SYSFS_VBD_PATH); + return 0; + } + } + + rewinddir(priv->sysfsvbd); + + for(dp = readdir(priv->sysfsvbd); dp != NULL ; + dp = readdir(priv->sysfsvbd)) { + xenstat_domain *domain; + xenstat_vbd vbd; + unsigned int domid; + int ret; + char buf[256]; + + + ret = sscanf(dp->d_name, "vbd-%u-%u", &domid, &vbd.dev); + if (ret != 2) { + continue; + } + printf("%s is VBD.\n",dp->d_name); + + domain = xenstat_node_domain(node, domid); + if (domain == NULL) { + fprintf(stderr, + "Found interface vbd-%u-%u but domain %u" + " does not exist.\n", + domid, vbd.dev, domid); + continue; + } + + if((read_attributes_vbd(dp->d_name, "statistics/oo_req", buf, 256)<=0) + || ((ret = sscanf(buf, "%llu", &vbd.oo_reqs)) != 1)) + { + continue; + } + + if((read_attributes_vbd(dp->d_name, "statistics/rd_req", buf, 256)<=0) + || ((ret = sscanf(buf, "%llu", &vbd.rd_reqs)) != 1)) + { + continue; + } + + if((read_attributes_vbd(dp->d_name, "statistics/wr_req", buf, 256)<=0) + || ((ret = sscanf(buf, "%llu", &vbd.wr_reqs)) != 1)) + { + continue; + } + + + if (domain->vbds == NULL) { + domain->num_vbds = 1; + domain->vbds = malloc(sizeof(xenstat_vbd)); + } else { + domain->num_vbds++; + domain->vbds = realloc(domain->vbds, + domain->num_vbds * + sizeof(xenstat_vbd)); + } + if (domain->vbds == NULL) + return 0; + domain->vbds[domain->num_vbds - 1] = vbd; + } + + return 1; +} + +/* Free VBD information in handle */ +void xenstat_uninit_vbds(xenstat_handle * handle) +{ + struct priv_data *priv = get_priv_data(handle); + if (priv != NULL && priv->sysfsvbd != NULL) + closedir(priv->sysfsvbd); +} diff --git a/tools/xenstat/libxenstat/src/xenstat_priv.h b/tools/xenstat/libxenstat/src/xenstat_priv.h new file mode 100644 --- /dev/null +++ b/tools/xenstat/libxenstat/src/xenstat_priv.h @@ -0,0 +1,101 @@ +/* libxenstat: statistics-collection library for Xen + * Copyright (C) International Business Machines Corp., 2005 + * Authors: Josh Triplett <josht@xxxxxxxxxx> + * Judy Fischbach <jfisch@xxxxxxxxxx> + * David Hendricks <dhendrix@xxxxxxxxxx> + * + * 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. + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef XENSTAT_PRIV_H +#define XENSTAT_PRIV_H + +#include <sys/types.h> +#include <xs.h> +#include "xenstat.h" + +#include "xenctrl.h" + +#define SHORT_ASC_LEN 5 /* length of 65535 */ +#define VERSION_SIZE (2 * SHORT_ASC_LEN + 1 + sizeof(xen_extraversion_t) + 1) + +struct xenstat_handle { + int xc_handle; + struct xs_handle *xshandle; /* xenstore handle */ + int page_size; + void *priv; + char xen_version[VERSION_SIZE]; /* xen version running on this node */ +}; + +struct xenstat_node { + xenstat_handle *handle; + unsigned int flags; + unsigned long long cpu_hz; + unsigned int num_cpus; + unsigned long long tot_mem; + unsigned long long free_mem; + unsigned int num_domains; + xenstat_domain *domains; /* Array of length num_domains */ +}; + +struct xenstat_domain { + unsigned int id; + char *name; + unsigned int state; + unsigned long long cpu_ns; + unsigned int num_vcpus; /* No. vcpus configured for domain */ + xenstat_vcpu *vcpus; /* Array of length num_vcpus */ + unsigned long long cur_mem; /* Current memory reservation */ + unsigned long long max_mem; /* Total memory allowed */ + unsigned int ssid; + unsigned int num_networks; + xenstat_network *networks; /* Array of length num_networks */ + unsigned int num_vbds; + xenstat_vbd *vbds; +}; + +struct xenstat_vcpu { + unsigned int online; + unsigned long long ns; +}; + +struct xenstat_network { + unsigned int id; + /* Received */ + unsigned long long rbytes; + unsigned long long rpackets; + unsigned long long rerrs; + unsigned long long rdrop; + /* Transmitted */ + unsigned long long tbytes; + unsigned long long tpackets; + unsigned long long terrs; + unsigned long long tdrop; +}; + +struct xenstat_vbd { + unsigned int dev; + unsigned long long oo_reqs; + unsigned long long rd_reqs; + unsigned long long wr_reqs; +}; + +extern int xenstat_collect_networks(xenstat_node * node); +extern void xenstat_uninit_networks(xenstat_handle * handle); +extern int xenstat_collect_vbds(xenstat_node * node); +extern void xenstat_uninit_vbds(xenstat_handle * handle); + +#endif /* XENSTAT_PRIV_H */ diff --git a/tools/xenstat/libxenstat/src/xenstat_solaris.c b/tools/xenstat/libxenstat/src/xenstat_solaris.c new file mode 100644 --- /dev/null +++ b/tools/xenstat/libxenstat/src/xenstat_solaris.c @@ -0,0 +1,431 @@ +/* libxenstat: statistics-collection library for Xen + * + * 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. + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include <strings.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> +#include <kstat.h> + +#include "xenstat_priv.h" + +#define DEVICE_NIC 1 +#define DEVICE_XDB 2 + +typedef struct stdevice { + int domid; + int used; + int type; + char name[256]; + int instance; + uint64_t stats[2][8]; + struct stdevice *next; +} stdevice_t; + +typedef struct priv_data { + kstat_ctl_t *kc; + stdevice_t *devs; +} priv_data_t; + +static priv_data_t *get_priv_data(xenstat_handle *handle) +{ + priv_data_t *priv = handle->priv; + + if (priv == NULL) { + priv = malloc(sizeof (priv_data_t)); + if (priv == NULL) + return NULL; + priv->devs = NULL; + priv->kc = NULL; + } + + if (priv->kc == NULL) { + if ((priv->kc = kstat_open()) == NULL) { + free(priv); + return NULL; + } + } + + handle->priv = priv; + return handle->priv; +} + +static int kstat_get(kstat_t *ksp, const char *name, uint64_t *val) +{ + kstat_named_t *ksn = kstat_data_lookup(ksp, (char *)name); + if (ksn == NULL) + return 0; + *val = ksn->value.ui64; + return 1; +} + +static void gc_devs(priv_data_t *priv, int type) +{ + stdevice_t *start = NULL; + stdevice_t *dev; + stdevice_t *tmp; + + for (dev = priv->devs; dev != NULL; dev = tmp) { + tmp = dev->next; + + if (dev->used || dev->type != type) { + dev->next = start; + start = dev; + } else { + free(dev); + } + } + + priv->devs = start; +} + +static void xenstat_uninit_devs(xenstat_handle *handle, int type) +{ + priv_data_t *priv = get_priv_data(handle); + stdevice_t *dev; + + if (priv == NULL) + return; + + for (dev = priv->devs; dev != NULL; dev = dev->next) + dev->used = 0; + + gc_devs(priv, type); + + if (priv->kc != NULL) + kstat_close(priv->kc); + priv->kc = NULL; +} + +static int parse_nic(const char *nic, char *module, int *instance) +{ + const char *c; + + for (c = &nic[strlen(nic) - 1]; c != nic && isdigit(*c); c--) + ; + + if (c == nic) + return 0; + + c++; + + if (sscanf(c, "%d", instance) != 1) + return 0; + + strncpy(module, nic, c - nic); + module[c - nic] = '\0'; + return 1; +} + +static int update_dev_stats(priv_data_t *priv, stdevice_t *dev) +{ + char mod[256]; + const char *name; + int inst; + kstat_t *ksp; + + if (dev->type == DEVICE_NIC) { + if (!parse_nic(dev->name, mod, &inst)) + return 0; + name = "mac"; + } else { + strcpy(mod, "xdb"); + inst = dev->instance; + name = "req_statistics"; + } + + if (kstat_chain_update(priv->kc) == -1) + return 0; + + ksp = kstat_lookup(priv->kc, mod, inst, (char *)name); + if (ksp == NULL) + return 0; + if (kstat_read(priv->kc, ksp, NULL) == -1) + return 0; + + dev->used = 1; + + bcopy(&(dev->stats[1][0]), &(dev->stats[0][0]), sizeof(dev->stats[0])); + + if (dev->type == DEVICE_NIC) { + if (!kstat_get(ksp, "rbytes64", &dev->stats[1][0]) || + !kstat_get(ksp, "ipackets64", &dev->stats[1][1]) || + !kstat_get(ksp, "ierrors", &dev->stats[1][2]) || + !kstat_get(ksp, "obytes64", &dev->stats[1][3]) || + !kstat_get(ksp, "opackets64", &dev->stats[1][4]) || + !kstat_get(ksp, "oerrors", &dev->stats[1][5])) + return 0; + + dev->stats[1][6] = 0; + dev->stats[1][7] = 0; + } else { + if (!kstat_get(ksp, "rd_reqs", &dev->stats[1][0]) || + !kstat_get(ksp, "wr_reqs", &dev->stats[1][1]) || + !kstat_get(ksp, "oo_reqs", &dev->stats[1][2])) + return 0; + } + + return 1; +} + +static int init_dev(priv_data_t *priv, int type, const char *name, + int instance, int domid) +{ + stdevice_t *dev; + + if (!(dev = malloc(sizeof(*dev)))) + return 0; + + bzero(dev, sizeof(*dev)); + dev->type = type; + if (name != NULL) + strcpy(dev->name, name); + dev->instance = instance; + dev->domid = domid; + dev->next = priv->devs; + priv->devs = dev; + + /* + * Update twice to avoid delta-since-boot. + */ + if (!update_dev_stats(priv, dev)) + return 0; + return update_dev_stats(priv, dev); +} + +static int update_nic(priv_data_t *priv, xenstat_domain *dom, + xenstat_network *net, const char *name) +{ + stdevice_t *dev; + + for (dev = priv->devs; dev != NULL; dev = dev->next) { + if (dev->type == DEVICE_NIC && dev->domid == dom->id && + strcmp(name, dev->name) == 0) { + if (!update_dev_stats(priv, dev)) + return 0; + net->rbytes = dev->stats[1][0] - dev->stats[0][0]; + net->rpackets = dev->stats[1][1] - dev->stats[0][1]; + net->rerrs = dev->stats[1][2] - dev->stats[0][2]; + net->tbytes = dev->stats[1][3] - dev->stats[0][3]; + net->tpackets = dev->stats[1][4] - dev->stats[0][4]; + net->terrs = dev->stats[1][5] - dev->stats[0][5]; + net->rdrop = dev->stats[1][6] - dev->stats[0][6]; + net->tdrop = dev->stats[1][7] - dev->stats[0][7]; + return 1; + } + } + + return init_dev(priv, DEVICE_NIC, name, 0, dom->id); +} + +static int +collect_dom_networks(xenstat_node *node, priv_data_t *priv, xenstat_domain *dom) +{ + char path[PATH_MAX]; + char **vifs; + int ret = 1; + int nr; + int i; + + snprintf(path, sizeof(path), "/local/domain/%d/device/vif", dom->id); + + dom->num_networks = 0; + free(dom->networks); + dom->networks = NULL; + + vifs = xs_directory(node->handle->xshandle, XBT_NULL, path, &nr); + if (vifs == NULL) + goto out; + + dom->num_networks = nr; + dom->networks = calloc(nr, sizeof(xenstat_network)); + + for (i = 0; i < dom->num_networks; i++) { + char *tmp; + + snprintf(path, sizeof(path), + "/local/domain/%d/device/vif/%d/backend", dom->id, i); + + tmp = xs_read(node->handle->xshandle, XBT_NULL, path, NULL); + + if (tmp == NULL) + goto out; + + snprintf(path, sizeof(path), "%s/nic", tmp); + free(tmp); + + tmp = xs_read(node->handle->xshandle, XBT_NULL, path, NULL); + + if (tmp == NULL || tmp[0] == '\0') { + free(tmp); + goto out; + } + + if (!(ret = update_nic(priv, dom, &dom->networks[i], tmp))) { + free(tmp); + goto out; + } + + free(tmp); + } + + ret = 1; +out: + free(vifs); + return ret; +} + +int xenstat_collect_networks(xenstat_node * node) +{ + int i; + priv_data_t *priv = get_priv_data(node->handle); + stdevice_t *dev; + + if (priv == NULL) + return 0; + + for (dev = priv->devs; dev != NULL; dev = dev->next) + dev->used = 0; + + for (i = 0; i < node->num_domains; i++) { + if (node->domains[i].id == 0) + continue; + if (!collect_dom_networks(node, priv, &node->domains[i])) + return 0; + } + + gc_devs(priv, DEVICE_NIC); + + return 1; +} + +void xenstat_uninit_networks(xenstat_handle *handle) +{ + xenstat_uninit_devs(handle, DEVICE_NIC); +} + +static int update_xdb(priv_data_t *priv, xenstat_domain *dom, + xenstat_vbd *vbd, int instance) +{ + stdevice_t *dev; + + for (dev = priv->devs; dev != NULL; dev = dev->next) { + if (dev->type == DEVICE_XDB && dev->domid == dom->id && + dev->instance == instance) { + if (!update_dev_stats(priv, dev)) + return 0; + vbd->dev = dev->instance; + vbd->rd_reqs = dev->stats[1][0] - dev->stats[0][0]; + vbd->wr_reqs = dev->stats[1][1] - dev->stats[0][1]; + vbd->oo_reqs = dev->stats[1][2] - dev->stats[0][2]; + return 1; + } + } + + return init_dev(priv, DEVICE_XDB, NULL, instance, dom->id); +} + +static int +collect_dom_vbds(xenstat_node *node, priv_data_t *priv, xenstat_domain *dom) +{ + char path[PATH_MAX]; + char **vbds; + int ret = 1; + int nr; + int i; + + snprintf(path, sizeof(path), "/local/domain/%d/device/vbd", dom->id); + + dom->num_vbds = 0; + free(dom->vbds); + dom->vbds = NULL; + + vbds = xs_directory(node->handle->xshandle, XBT_NULL, path, &nr); + if (vbds == NULL) + goto out; + + dom->num_vbds = nr; + dom->vbds = calloc(nr, sizeof(xenstat_vbd)); + + for (i = 0; i < dom->num_vbds; i++) { + char *tmp; + int inst; + + snprintf(path, sizeof(path), + "/local/domain/%d/device/vbd/%s/backend", dom->id, vbds[i]); + + tmp = xs_read(node->handle->xshandle, XBT_NULL, path, NULL); + + if (tmp == NULL) + goto out; + + snprintf(path, sizeof(path), "%s/instance", tmp); + free(tmp); + + tmp = xs_read(node->handle->xshandle, XBT_NULL, path, NULL); + + /* + * Fails when connection is not completed; mark it clearly with + * a -1. + */ + if (tmp == NULL || sscanf(tmp, "%d", &inst) != 1) { + dom->vbds[i].dev = -1; + free(tmp); + goto out; + } + + free(tmp); + + if (!(ret = update_xdb(priv, dom, &dom->vbds[i], inst))) + goto out; + } + +out: + free(vbds); + return ret; +} + +int xenstat_collect_vbds(xenstat_node * node) +{ + int i; + priv_data_t *priv = get_priv_data(node->handle); + stdevice_t *dev; + + if (priv == NULL) + return 0; + + for (dev = priv->devs; dev != NULL; dev = dev->next) + dev->used = 0; + + for (i = 0; i < node->num_domains; i++) { + if (node->domains[i].id == 0) + continue; + if (!collect_dom_vbds(node, priv, &node->domains[i])) + return 0; + } + + gc_devs(priv, DEVICE_XDB); + + return 1; +} + +void xenstat_uninit_vbds(xenstat_handle * handle) +{ + xenstat_uninit_devs(handle, DEVICE_XDB); +} diff --git a/tools/xenstat/xentop/xentop.c b/tools/xenstat/xentop/xentop.c --- a/tools/xenstat/xentop/xentop.c +++ b/tools/xenstat/xentop/xentop.c @@ -52,7 +52,11 @@ #define KEY_ESCAPE '\x1B' #ifdef HOST_SunOS -/* Old curses library on Solaris takes non-const strings. */ +/* Old curses library on Solaris takes non-const strings. Also, ERR interferes + * with curse's definition. + */ +#undef ERR +#define ERR (-1) #define curses_str_t char * #else #define curses_str_t const char * @@ -924,7 +928,7 @@ void do_vbd(xenstat_domain *domain) xenstat_vbd_rd_reqs(vbd), xenstat_vbd_wr_reqs(vbd)); #else - print("VBD %4u OO: %8llu RD: %8llu WR: %8llu\n", + print("VBD %4d OO: %8llu RD: %8llu WR: %8llu\n", xenstat_vbd_dev(vbd), xenstat_vbd_oo_reqs(vbd), xenstat_vbd_rd_reqs(vbd), _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |