# HG changeset patch # User josht@xxxxxxxxxx # Node ID d39cf132a00a91e65c0ad4640c5bd17f722788b7 # Parent 822566f5cfddce3b641b5a1a119dfd592ec69158 Add xenstat framework. diff -r 822566f5cfdd -r d39cf132a00a tools/Makefile --- a/tools/Makefile Thu Aug 11 22:18:27 2005 +++ b/tools/Makefile Fri Aug 12 17:00:35 2005 @@ -14,6 +14,7 @@ SUBDIRS += firmware SUBDIRS += security SUBDIRS += console +SUBDIRS += xenstat .PHONY: all install clean check check_clean ioemu eioemuinstall ioemuclean diff -r 822566f5cfdd -r d39cf132a00a tools/Rules.mk --- a/tools/Rules.mk Thu Aug 11 22:18:27 2005 +++ b/tools/Rules.mk Fri Aug 12 17:00:35 2005 @@ -6,6 +6,7 @@ XEN_LIBXC = $(XEN_ROOT)/tools/libxc XEN_XCS = $(XEN_ROOT)/tools/xcs XEN_XENSTORE = $(XEN_ROOT)/tools/xenstore +XEN_LIBXENSTAT = $(XEN_ROOT)/tools/xenstat/libxenstat/src ifeq ($(XEN_TARGET_ARCH),x86_32) CFLAGS += -m32 -march=i686 diff -r 822566f5cfdd -r d39cf132a00a tools/xenstat/Makefile --- /dev/null Thu Aug 11 22:18:27 2005 +++ b/tools/xenstat/Makefile Fri Aug 12 17:00:35 2005 @@ -0,0 +1,13 @@ +XEN_ROOT = ../.. +include $(XEN_ROOT)/tools/Rules.mk + +SUBDIRS := +SUBDIRS += libxenstat +SUBDIRS += vm-top + +.PHONY: all install clean + +all install clean: + @set -e; for subdir in $(SUBDIRS); do \ + $(MAKE) -C $$subdir $@; \ + done diff -r 822566f5cfdd -r d39cf132a00a tools/xenstat/libxenstat/COPYING --- /dev/null Thu Aug 11 22:18:27 2005 +++ b/tools/xenstat/libxenstat/COPYING Fri Aug 12 17:00:35 2005 @@ -0,0 +1,510 @@ + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations +below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it +becomes a de-facto standard. To achieve this, non-free programs must +be allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control +compilation and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at least + three years, to give the same user the materials specified in + Subsection 6a, above, for a charge no more than the cost of + performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply, and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License +may add an explicit geographical distribution limitation excluding those +countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms +of the ordinary General Public License). + + To apply these terms, attach the following notices to the library. +It is safest to attach them to the start of each source file to most +effectively convey the exclusion of warranty; and each file should +have at least the "copyright" line and a pointer to where the full +notice is found. + + + + Copyright (C) + + 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, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or +your school, if any, to sign a "copyright disclaimer" for the library, +if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James + Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff -r 822566f5cfdd -r d39cf132a00a tools/xenstat/libxenstat/Makefile --- /dev/null Thu Aug 11 22:18:27 2005 +++ b/tools/xenstat/libxenstat/Makefile Fri Aug 12 17:00:35 2005 @@ -0,0 +1,120 @@ +# libxenstat: statistics-collection library for Xen +# Copyright (C) International Business Machines Corp., 2005 +# Author: Josh Triplett +# +# 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. + +XEN_ROOT=../../.. +include $(XEN_ROOT)/tools/Rules.mk +LINUX_ROOT := $(XEN_ROOT)/linux-2.6-xen-sparse + +INSTALL = install +INSTALL_PROG = $(INSTALL) -m0755 -D +INSTALL_DATA = $(INSTALL) -m0644 -D + +prefix=/usr +includedir=$(prefix)/include +libdir=$(prefix)/lib + +LDCONFIG=ldconfig +MAKE_LINK=ln -sf + +MAJOR=0 +MINOR=0 + +LIB=src/libxenstat.so.$(MAJOR).$(MINOR) +LINKS=src/libxenstat.so.$(MAJOR) src/libxenstat.so +OBJECTS=src/xenstat.o src/xen-interface.o +SONAME_FLAGS=-Wl,-soname -Wl,libxenstat.so.$(MAJOR) + +WARN_FLAGS=-Wall -Werror + +CFLAGS+=-Isrc +CFLAGS+=-I$(XEN_ROOT)/xen/include/public +CFLAGS+=-I$(LINUX_ROOT)/include/asm-xen/linux-public/ +LDFLAGS+=-Lsrc + +# Note that the bindings are not built by default, because they require a +# number of external dependencies. +all: $(LIB) $(LINKS) + +$(LIB): $(OBJECTS) + $(CC) $(LDFLAGS) $(SONAME_FLAGS) -shared -o $@ $(OBJECTS) + +src/xenstat.o: src/xenstat.c src/xenstat.h src/xen-interface.h + $(CC) $(CFLAGS) $(WARN_FLAGS) -c -o $@ $< + +src/xen-interface.o: src/xen-interface.c src/xen-interface.h + $(CC) $(CFLAGS) $(WARN_FLAGS) -c -o $@ $< + +src/libxenstat.so.$(MAJOR): $(LIB) + $(MAKE_LINK) $( + * Judy Fischbach + * + * 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. + */ + +#include "xen-interface.h" +#include +#include +#include +#include +#include +#include +#include "privcmd.h" +#include "xen.h" + +struct xi_handle { + int fd; +}; + +/* Initialize for xen-interface. Returns a handle to be used with subsequent + * calls to the xen-interface functions or NULL if an error occurs. */ +xi_handle *xi_init() +{ + xi_handle *handle; + + handle = (xi_handle *)calloc(1, sizeof(xi_handle)); + if (handle == NULL) + return NULL; + + handle->fd = open("/proc/xen/privcmd", O_RDWR); + if (handle->fd < 0) { + perror("Couldn't open /proc/xen/privcmd"); + free(handle); + return NULL; + } + + return handle; +} + +/* Release the handle to libxc, free resources, etc. */ +void xi_uninit(xi_handle *handle) +{ + close (handle->fd); + free (handle); +} + +/* Make Xen hypervisor call */ +int xi_make_dom0_op(xi_handle *handle, dom0_op_t *op, int opcode) +{ + privcmd_hypercall_t privcmd; + int ret = 0; + + /* set up for doing hypercall */ + privcmd.op = __HYPERVISOR_dom0_op; + privcmd.arg[0] = (unsigned long)op; + op->cmd = opcode; + op->interface_version = DOM0_INTERFACE_VERSION; + + if (mlock( &privcmd, sizeof(privcmd_hypercall_t)) < 0) { + perror("Failed to mlock privcmd structure"); + return -1; + } + + if (mlock( op, sizeof(dom0_op_t)) < 0) { + perror("Failed to mlock dom0_op structure"); + munlock( &privcmd, sizeof(privcmd_hypercall_t)); + return -1; + } + + if (ioctl( handle->fd, IOCTL_PRIVCMD_HYPERCALL, &privcmd) < 0) { + perror("Hypercall failed"); + ret = -1; + } + + munlock( &privcmd, sizeof(privcmd_hypercall_t)); + munlock( op, sizeof(dom0_op_t)); + + return ret; +} + +/* Obtain domain data from dom0 */ +int xi_get_physinfo(xi_handle *handle, dom0_physinfo_t *physinfo) +{ + dom0_op_t op; + + if (xi_make_dom0_op(handle, &op, DOM0_PHYSINFO) < 0) { + perror("DOM0_PHYSINFO Hypercall failed"); + return -1; + } + + *physinfo = op.u.physinfo; + return 0; +} + +/* Obtain domain data from dom0 */ +int xi_get_domaininfolist(xi_handle *handle, dom0_getdomaininfo_t *info, + unsigned int first_domain, unsigned int max_domains) +{ + dom0_op_t op; + op.u.getdomaininfolist.first_domain = first_domain; + op.u.getdomaininfolist.max_domains = max_domains; + op.u.getdomaininfolist.buffer = info; + + if (mlock( info, max_domains * sizeof(dom0_getdomaininfo_t)) < 0) { + perror("Failed to mlock domaininfo array"); + return -1; + } + + if (xi_make_dom0_op(handle, &op, DOM0_GETDOMAININFOLIST) < 0) { + perror("DOM0_GETDOMAININFOLIST Hypercall failed"); + return -1; + } + + return op.u.getdomaininfolist.num_domains; +} + +/* Returns cpu usage data from dom0 */ +long long xi_get_vcpu_usage(xi_handle *handle, unsigned int domain, + unsigned int vcpu) +{ + dom0_op_t op; + op.u.getvcpucontext.domain = domain; + op.u.getvcpucontext.vcpu = vcpu; + op.u.getvcpucontext.ctxt = NULL; + + if (xi_make_dom0_op(handle, &op, DOM0_GETVCPUCONTEXT) < 0) { + perror("DOM0_GETVCPUCONTEXT Hypercall failed"); + return -1; + } + + return op.u.getvcpucontext.cpu_time; +} diff -r 822566f5cfdd -r d39cf132a00a tools/xenstat/libxenstat/src/xen-interface.h --- /dev/null Thu Aug 11 22:18:27 2005 +++ b/tools/xenstat/libxenstat/src/xen-interface.h Fri Aug 12 17:00:35 2005 @@ -0,0 +1,49 @@ +/* xen-interface.h + * + * Copyright (C) International Business Machines Corp., 2005 + * Authors: Josh Triplett + * Judy Fischbach + * + * 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. + */ + +#include + +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +#include "dom0_ops.h" + +/* Opaque handles */ +typedef struct xi_handle xi_handle; + +/* Initialize for xen-interface. Returns a handle to be used with subsequent + * calls to the xen-interface functions or NULL if an error occurs. */ +xi_handle *xi_init(); + +/* Release the handle to libxc, free resources, etc. */ +void xi_uninit(xi_handle *handle); + +/* Obtain physinfo data from dom0 */ +int xi_get_physinfo(xi_handle *, dom0_physinfo_t *); + +/* Obtain domain data from dom0 */ +int xi_get_domaininfolist(xi_handle *, dom0_getdomaininfo_t *, unsigned int, + unsigned int); + +/* Returns cpu usage data from dom0 */ +long long xi_get_vcpu_usage(xi_handle *, unsigned int, unsigned int); diff -r 822566f5cfdd -r d39cf132a00a tools/xenstat/libxenstat/src/xenstat.c --- /dev/null Thu Aug 11 22:18:27 2005 +++ b/tools/xenstat/libxenstat/src/xenstat.c Fri Aug 12 17:00:35 2005 @@ -0,0 +1,620 @@ +/* libxenstat: statistics-collection library for Xen + * Copyright (C) International Business Machines Corp., 2005 + * Authors: Josh Triplett + * Judy Fischbach + * David Hendricks + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include "xenstat.h" + +/* + * Types + */ +struct xenstat_handle { + xi_handle *xihandle; + int page_size; + FILE *procnetdev; +}; + +struct xenstat_node { + 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; + unsigned int state; + unsigned long long cpu_ns; + unsigned int num_vcpus; + 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 */ +}; + +struct xenstat_vcpu { + 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; +}; + +/* + * Data-collection types + */ +/* Called to collect the information for the node and all the domains on + * it. When called, the domain information has already been collected. */ +typedef int (*xenstat_collect_func)(xenstat_handle * handle, + xenstat_node * node); +/* Called to free the information collected by the collect function. The free + * function will only be called on a xenstat_node if that node includes + * information collected by the corresponding collector. */ +typedef void (*xenstat_free_func)(xenstat_node * node); +/* Called to free any information stored in the handle. Note the lack of a + * matching init function; the collect functions should initialize on first + * use. Also, the uninit function must handle the case that the collector has + * never been initialized. */ +typedef void (*xenstat_uninit_func)(xenstat_handle * handle); +typedef struct xenstat_collector { + unsigned int flag; + xenstat_collect_func collect; + xenstat_free_func free; + xenstat_uninit_func uninit; +} xenstat_collector; + +static int xenstat_collect_vcpus(xenstat_handle * handle, + xenstat_node * node); +static int xenstat_collect_networks(xenstat_handle * handle, + xenstat_node * node); +static void xenstat_free_vcpus(xenstat_node * node); +static void xenstat_free_networks(xenstat_node * node); +static void xenstat_uninit_vcpus(xenstat_handle * handle); +static void xenstat_uninit_networks(xenstat_handle * handle); + +static xenstat_collector collectors[] = { + { XENSTAT_VCPU, xenstat_collect_vcpus, + xenstat_free_vcpus, xenstat_uninit_vcpus }, + { XENSTAT_NETWORK, xenstat_collect_networks, + xenstat_free_networks, xenstat_uninit_networks } +}; + +#define NUM_COLLECTORS (sizeof(collectors)/sizeof(xenstat_collector)) + +/* + * libxenstat API + */ +xenstat_handle *xenstat_init() +{ + xenstat_handle *handle; + + handle = (xenstat_handle *) calloc(1, sizeof(xenstat_handle)); + if (handle == NULL) + return NULL; + +#if defined(PAGESIZE) + handle->page_size = PAGESIZE; +#elif defined(PAGE_SIZE) + handle->page_size = PAGE_SIZE; +#else + handle->page_size = sysconf(_SC_PAGE_SIZE); + if (handle->page_size < 0) { + perror("Failed to retrieve page size."); + free(handle); + return NULL; + } +#endif + + handle->xihandle = xi_init(); + if (handle->xihandle == NULL) { + perror("xi_init"); + free(handle); + return NULL; + } + + return handle; +} + +void xenstat_uninit(xenstat_handle * handle) +{ + unsigned int i; + if (handle) { + for (i = 0; i < NUM_COLLECTORS; i++) + collectors[i].uninit(handle); + xi_uninit(handle->xihandle); + free(handle); + } +} + +xenstat_node *xenstat_get_node(xenstat_handle * handle, unsigned int flags) +{ +#define DOMAIN_CHUNK_SIZE 256 + xenstat_node *node; + dom0_physinfo_t physinfo; + dom0_getdomaininfo_t domaininfo[DOMAIN_CHUNK_SIZE]; + unsigned int num_domains, new_domains; + unsigned int i; + + /* Create the node */ + node = (xenstat_node *) calloc(1, sizeof(xenstat_node)); + if (node == NULL) + return NULL; + + /* Get information about the physical system */ + if (xi_get_physinfo(handle->xihandle, &physinfo) < 0) { + free(node); + return NULL; + } + + node->cpu_hz = ((unsigned long long)physinfo.cpu_khz) * 1000ULL; + node->num_cpus = + (physinfo.threads_per_core * physinfo.cores_per_socket * + physinfo.sockets_per_node * physinfo.nr_nodes); + node->tot_mem = ((unsigned long long)physinfo.total_pages) + * handle->page_size; + node->free_mem = ((unsigned long long)physinfo.free_pages) + * handle->page_size; + + /* malloc(0) is not portable, so allocate a single domain. This will + * be resized below. */ + node->domains = malloc(sizeof(xenstat_domain)); + if (node->domains == NULL) { + free(node); + return NULL; + } + + num_domains = 0; + do { + xenstat_domain *domain; + + new_domains = xi_get_domaininfolist(handle->xihandle, + domaininfo, num_domains, + DOMAIN_CHUNK_SIZE); + + node->domains = realloc(node->domains, + (num_domains + new_domains) + * sizeof(xenstat_domain)); + if (node->domains == NULL) { + free(node); + return NULL; + } + + domain = node->domains + num_domains; + + for (i = 0; i < new_domains; i++) { + /* Fill in domain using domaininfo[i] */ + domain->id = domaininfo[i].domain; + domain->state = domaininfo[i].flags; + domain->cpu_ns = domaininfo[i].cpu_time; + domain->num_vcpus = domaininfo[i].n_vcpu; + domain->vcpus = NULL; + domain->cur_mem = + ((unsigned long long)domaininfo[i].tot_pages) + * handle->page_size; + domain->max_mem = + domaininfo[i].max_pages == UINT_MAX + ? (unsigned long long)-1 + : (unsigned long long)(domaininfo[i].max_pages + * handle->page_size); + domain->ssid = domaininfo[i].ssidref; + domain->num_networks = 0; + domain->networks = NULL; + + domain++; + } + num_domains += new_domains; + } while (new_domains == DOMAIN_CHUNK_SIZE); + node->num_domains = num_domains; + + /* Run all the extra data collectors requested */ + node->flags = 0; + for (i = 0; i < NUM_COLLECTORS; i++) { + if ((flags & collectors[i].flag) == collectors[i].flag) { + node->flags |= collectors[i].flag; + if(collectors[i].collect(handle, node) == 0) { + xenstat_free_node(node); + return NULL; + } + } + } + + return node; +} + +void xenstat_free_node(xenstat_node * node) +{ + int i; + + if (node) { + if (node->domains) { + for (i = 0; i < NUM_COLLECTORS; i++) + if((node->flags & collectors[i].flag) + == collectors[i].flag) + collectors[i].free(node); + free(node->domains); + } + free(node); + } +} + +xenstat_domain *xenstat_node_domain(xenstat_node * node, unsigned int domid) +{ + unsigned int i; + + /* FIXME: binary search */ + /* Find the appropriate domain entry in the node struct. */ + for (i = 0; i < node->num_domains; i++) { + if (node->domains[i].id == domid) + return &(node->domains[i]); + } + return NULL; +} + +xenstat_domain *xenstat_node_domain_by_index(xenstat_node * node, + unsigned int index) +{ + if (0 <= index && index < node->num_domains) + return &(node->domains[index]); + return NULL; +} + +unsigned long long xenstat_node_tot_mem(xenstat_node * node) +{ + return node->tot_mem; +} + +unsigned long long xenstat_node_free_mem(xenstat_node * node) +{ + return node->free_mem; +} + +unsigned int xenstat_node_num_domains(xenstat_node * node) +{ + return node->num_domains; +} + +unsigned int xenstat_node_num_cpus(xenstat_node * node) +{ + return node->num_cpus; +} + +/* Get information about the CPU speed */ +unsigned long long xenstat_node_cpu_hz(xenstat_node * node) +{ + return node->cpu_hz; +} + +/* Get the domain ID for this domain */ +unsigned xenstat_domain_id(xenstat_domain * domain) +{ + return domain->id; +} + +/* Get information about how much CPU time has been used */ +unsigned long long xenstat_domain_cpu_ns(xenstat_domain * domain) +{ + return domain->cpu_ns; +} + +/* Find the number of VCPUs allocated to a domain */ +unsigned int xenstat_domain_num_vcpus(xenstat_domain * domain) +{ + return domain->num_vcpus; +} + +xenstat_vcpu *xenstat_domain_vcpu(xenstat_domain * domain, unsigned int vcpu) +{ + if (0 <= vcpu && vcpu < domain->num_vcpus) + return &(domain->vcpus[vcpu]); + return NULL; +} + +/* Find the current memory reservation for this domain */ +unsigned long long xenstat_domain_cur_mem(xenstat_domain * domain) +{ + return domain->cur_mem; +} + +/* Find the maximum memory reservation for this domain */ +unsigned long long xenstat_domain_max_mem(xenstat_domain * domain) +{ + return domain->max_mem; +} + +/* Find the domain's SSID */ +unsigned int xenstat_domain_ssid(xenstat_domain * domain) +{ + return domain->ssid; +} + +/* Get domain states */ +unsigned int xenstat_domain_dying(xenstat_domain * domain) +{ + return (domain->state & DOMFLAGS_DYING) == DOMFLAGS_DYING; +} + +unsigned int xenstat_domain_crashed(xenstat_domain * domain) +{ + return ((domain->state & DOMFLAGS_SHUTDOWN) == DOMFLAGS_SHUTDOWN) + && (((domain->state >> DOMFLAGS_SHUTDOWNSHIFT) + & DOMFLAGS_SHUTDOWNMASK) == SHUTDOWN_crash); +} + +unsigned int xenstat_domain_shutdown(xenstat_domain * domain) +{ + return ((domain->state & DOMFLAGS_SHUTDOWN) == DOMFLAGS_SHUTDOWN) + && (((domain->state >> DOMFLAGS_SHUTDOWNSHIFT) + & DOMFLAGS_SHUTDOWNMASK) != SHUTDOWN_crash); +} + +unsigned int xenstat_domain_paused(xenstat_domain * domain) +{ + return (domain->state & DOMFLAGS_PAUSED) == DOMFLAGS_PAUSED; +} + +unsigned int xenstat_domain_blocked(xenstat_domain * domain) +{ + return (domain->state & DOMFLAGS_BLOCKED) == DOMFLAGS_BLOCKED; +} + +unsigned int xenstat_domain_running(xenstat_domain * domain) +{ + return (domain->state & DOMFLAGS_RUNNING) == DOMFLAGS_RUNNING; +} + +/* Get the number of networks for a given domain */ +unsigned int xenstat_domain_num_networks(xenstat_domain * domain) +{ + return domain->num_networks; +} + +/* Get the network handle to obtain network stats */ +xenstat_network *xenstat_domain_network(xenstat_domain * domain, + unsigned int network) +{ + if (domain->networks && 0 <= network && network < domain->num_networks) + return &(domain->networks[network]); + return NULL; +} + +/* + * VCPU functions + */ +/* Collect information about VCPUs */ +static int xenstat_collect_vcpus(xenstat_handle * handle, xenstat_node * node) +{ + unsigned int i, vcpu; + /* Fill in VCPU information */ + for (i = 0; i < node->num_domains; i++) { + node->domains[i].vcpus = malloc(node->domains[i].num_vcpus + * sizeof(xenstat_vcpu)); + if (node->domains[i].vcpus == NULL) + return 0; + + for (vcpu = 0; vcpu < node->domains[i].num_vcpus; vcpu++) { + /* FIXME: need to be using a more efficient mechanism*/ + long long vcpu_time; + vcpu_time = + xi_get_vcpu_usage(handle->xihandle, + node->domains[i].id, + vcpu); + if (vcpu_time < 0) + return 0; + node->domains[i].vcpus[vcpu].ns = vcpu_time; + } + } + return 1; +} + +/* Free VCPU information */ +static void xenstat_free_vcpus(xenstat_node * node) +{ + unsigned int i; + for (i = 0; i < node->num_domains; i++) + free(node->domains[i].vcpus); +} + +/* Free VCPU information in handle - nothing to do */ +static void xenstat_uninit_vcpus(xenstat_handle * handle) +{ +} + +/* Get VCPU usage */ +unsigned long long xenstat_vcpu_ns(xenstat_vcpu * vcpu) +{ + return vcpu->ns; +} + +/* + * 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_handle * handle, + xenstat_node * node) +{ + /* Open and validate /proc/net/dev if we haven't already */ + if (handle->procnetdev == NULL) { + char header[sizeof(PROCNETDEV_HEADER)]; + handle->procnetdev = fopen("/proc/net/dev", "r"); + if (handle->procnetdev == NULL) { + perror("Error opening /proc/net/dev"); + return 1; + } + + /* Validate the format of /proc/net/dev */ + if (fread(header, sizeof(PROCNETDEV_HEADER) - 1, 1, + handle->procnetdev) != 1) { + perror("Error reading /proc/net/dev header"); + return 1; + } + header[sizeof(PROCNETDEV_HEADER) - 1] = '\0'; + if (strcmp(header, PROCNETDEV_HEADER) != 0) { + fprintf(stderr, + "Unexpected /proc/net/dev format\n"); + return 1; + } + } + + /* Fill in networks */ + /* FIXME: optimize this */ + fseek(handle->procnetdev, sizeof(PROCNETDEV_HEADER) - 1, SEEK_SET); + while (1) { + xenstat_domain *domain; + xenstat_network net; + unsigned int domid; + int ret = fscanf(handle->procnetdev, + "vif%u.%u:%llu%llu%llu%llu%*u%*u%*u%*u" + "%llu%llu%llu%llu%*u%*u%*u%*u", + &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(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 { + domain->num_networks++; + domain->networks = + realloc(domain->networks, + domain->num_networks * + sizeof(xenstat_network)); + } + if (domain->networks == NULL) + return 1; + 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 */ +unsigned int xenstat_network_id(xenstat_network * network) +{ + return network->id; +} + +/* Get the number of receive bytes */ +unsigned long long xenstat_network_rbytes(xenstat_network * network) +{ + return network->rbytes; +} + +/* Get the number of receive packets */ +unsigned long long xenstat_network_rpackets(xenstat_network * network) +{ + return network->rpackets; +} + +/* Get the number of receive errors */ +unsigned long long xenstat_network_rerrs(xenstat_network * network) +{ + return network->rerrs; +} + +/* Get the number of receive drops */ +unsigned long long xenstat_network_rdrop(xenstat_network * network) +{ + return network->rdrop; +} + +/* Get the number of transmit bytes */ +unsigned long long xenstat_network_tbytes(xenstat_network * network) +{ + return network->tbytes; +} + +/* Get the number of transmit packets */ +unsigned long long xenstat_network_tpackets(xenstat_network * network) +{ + return network->tpackets; +} + +/* Get the number of transmit errors */ +unsigned long long xenstat_network_terrs(xenstat_network * network) +{ + return network->terrs; +} + +/* Get the number of transmit dropped packets */ +unsigned long long xenstat_network_tdrop(xenstat_network * network) +{ + return network->tdrop; +} diff -r 822566f5cfdd -r d39cf132a00a tools/xenstat/libxenstat/src/xenstat.h --- /dev/null Thu Aug 11 22:18:27 2005 +++ b/tools/xenstat/libxenstat/src/xenstat.h Fri Aug 12 17:00:35 2005 @@ -0,0 +1,148 @@ +/* libxenstat: statistics-collection library for Xen + * Copyright (C) International Business Machines Corp., 2005 + * Authors: Josh Triplett + * Judy Fischbach + * David Hendricks + * + * 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. + */ + +/* libxenstat API */ + +/* Opaque handles */ +typedef struct xenstat_handle xenstat_handle; +typedef struct xenstat_domain xenstat_domain; +typedef struct xenstat_node xenstat_node; +typedef struct xenstat_vcpu xenstat_vcpu; +typedef struct xenstat_network xenstat_network; + +/* Initialize the xenstat library. Returns a handle to be used with + * subsequent calls to the xenstat library, or NULL if an error occurs. */ +xenstat_handle *xenstat_init(); + +/* Release the handle to libxc, free resources, etc. */ +void xenstat_uninit(xenstat_handle * handle); + +/* Get all available information about a node */ +#define XENSTAT_VCPU 0x1 +#define XENSTAT_NETWORK 0x2 +#define XENSTAT_ALL (XENSTAT_VCPU|XENSTAT_NETWORK) +xenstat_node *xenstat_get_node(xenstat_handle * handle, unsigned int flags); + +/* Free the information */ +void xenstat_free_node(xenstat_node * node); + +/* + * Node functions - extract information from a xenstat_node + */ + +/* Get information about the domain with the given domain ID */ +xenstat_domain *xenstat_node_domain(xenstat_node * node, + unsigned int domid); + +/* Get the domain with the given index; used to loop over all domains. */ +xenstat_domain *xenstat_node_domain_by_index(xenstat_node * node, + unsigned index); + +/* Get amount of total memory on a node */ +unsigned long long xenstat_node_tot_mem(xenstat_node * node); + +/* Get amount of free memory on a node */ +unsigned long long xenstat_node_free_mem(xenstat_node * node); + +/* Find the number of domains existing on a node */ +unsigned int xenstat_node_num_domains(xenstat_node * node); + +/* Find the number of CPUs existing on a node */ +unsigned int xenstat_node_num_cpus(xenstat_node * node); + +/* Get information about the CPU speed */ +unsigned long long xenstat_node_cpu_hz(xenstat_node * node); + +/* + * Domain functions - extract information from a xenstat_domain + */ + +/* Get the domain ID for this domain */ +unsigned xenstat_domain_id(xenstat_domain * domain); + +/* Get information about how much CPU time has been used */ +unsigned long long xenstat_domain_cpu_ns(xenstat_domain * domain); + +/* Find the number of VCPUs allocated to a domain */ +unsigned int xenstat_domain_num_vcpus(xenstat_domain * domain); + +/* Get the VCPU handle to obtain VCPU stats */ +xenstat_vcpu *xenstat_domain_vcpu(xenstat_domain * domain, + unsigned int vcpu); + +/* Find the current memory reservation for this domain */ +unsigned long long xenstat_domain_cur_mem(xenstat_domain * domain); + +/* Find the maximum memory reservation for this domain */ +unsigned long long xenstat_domain_max_mem(xenstat_domain * domain); + +/* Find the domain's SSID */ +unsigned int xenstat_domain_ssid(xenstat_domain * domain); + +/* Get domain states */ +unsigned int xenstat_domain_dying(xenstat_domain * domain); +unsigned int xenstat_domain_crashed(xenstat_domain * domain); +unsigned int xenstat_domain_shutdown(xenstat_domain * domain); +unsigned int xenstat_domain_paused(xenstat_domain * domain); +unsigned int xenstat_domain_blocked(xenstat_domain * domain); +unsigned int xenstat_domain_running(xenstat_domain * domain); + +/* Get the number of networks for a given domain */ +unsigned int xenstat_domain_num_networks(xenstat_domain *); + +/* Get the network handle to obtain network stats */ +xenstat_network *xenstat_domain_network(xenstat_domain * domain, + unsigned int network); + +/* + * VCPU functions - extract information from a xenstat_vcpu + */ + +/* Get VCPU usage */ +unsigned long long xenstat_vcpu_ns(xenstat_vcpu * vcpu); + + +/* + * Network functions - extract information from a xenstat_network + */ + +/* Get the ID for this network */ +unsigned int xenstat_network_id(xenstat_network * network); + +/* Get the number of receive bytes for this network */ +unsigned long long xenstat_network_rbytes(xenstat_network * network); + +/* Get the number of receive packets for this network */ +unsigned long long xenstat_network_rpackets(xenstat_network * network); + +/* Get the number of receive errors for this network */ +unsigned long long xenstat_network_rerrs(xenstat_network * network); + +/* Get the number of receive drops for this network */ +unsigned long long xenstat_network_rdrop(xenstat_network * network); + +/* Get the number of transmit bytes for this network */ +unsigned long long xenstat_network_tbytes(xenstat_network * network); + +/* Get the number of transmit packets for this network */ +unsigned long long xenstat_network_tpackets(xenstat_network * network); + +/* Get the number of transmit errors for this network */ +unsigned long long xenstat_network_terrs(xenstat_network * network); + +/* Get the number of transmit drops for this network */ +unsigned long long xenstat_network_tdrop(xenstat_network * network); diff -r 822566f5cfdd -r d39cf132a00a tools/xenstat/vm-top/Makefile --- /dev/null Thu Aug 11 22:18:27 2005 +++ b/tools/xenstat/vm-top/Makefile Fri Aug 12 17:00:35 2005 @@ -0,0 +1,47 @@ +# Copyright (C) International Business Machines Corp., 2005 +# Author: Josh Triplett +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; under version 2 of the License. +# +# This program 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 General Public License for more details. + +ifneq (,$(shell [ -e /usr/include/curses.h ] || echo no)) +all vm-top: + @echo "***********************************************************" + @echo "WARNING: Install ncurses to build vm-top." + @echo "***********************************************************" +else + +XEN_ROOT=../../.. +include $(XEN_ROOT)/tools/Rules.mk + +INSTALL = install +INSTALL_PROG = $(INSTALL) -m0755 -D +INSTALL_DATA = $(INSTALL) -m0644 -D + +prefix=/usr +mandir=$(prefix)/share/man +man1dir=$(mandir)/man1 +sbindir=$(prefix)/sbin + +CFLAGS += -DGCC_PRINTF -Wall -Werror -I$(XEN_LIBXENSTAT) +LDFLAGS += -L$(XEN_LIBXENSTAT) -lxenstat -lcurses + +all: vm-top + +vm-top: vm-top.o + +endif + +install: vm-top vm-top.1 + [ -f vm-top ] && $(INSTALL_PROG) vm-top $(DESTDIR)$(sbindir)/vm-top + [ -f vm-top.1 ] && \ + $(INSTALL_DATA) vm-top.1 $(DESTDIR)$(man1dir)/vm-top.1 + +clean: + rm -f vm-top vm-top.o diff -r 822566f5cfdd -r d39cf132a00a tools/xenstat/vm-top/TODO --- /dev/null Thu Aug 11 22:18:27 2005 +++ b/tools/xenstat/vm-top/TODO Fri Aug 12 17:00:35 2005 @@ -0,0 +1,37 @@ +Inefficient about how it handles newlines in vm-top +for proc/net/dev. Fix. + +Display error messages on the help line after bad input at a prompt. +Fractional delay times +Use prompting to search for domains +Better line editing? + +* Make CPU in % more accurate +* Domain total network TX % and RX % + +Like Top, f feature, field select of domain columns, toggle the display of +field by typing the letter associated with field, if displayed it shows in +bold and the letter is Capitalized along with a leading asterisk for the +field, if not selected for display letter is lowercase, no leading asterisk +and field is not bolded. + +Like Top, ordering of domain columns, o feature Capital letter shifts left, +lowercase letter shifts right? + +Color +Full management: pause, destroy, create domains + +Add support for Virtual Block Devices (vbd) + +To think about: +Support for one than one node display (distributed monitoring +from any node of all other nodes in a cluster) +Bottom line option (Switch node, Search node [tab completion?]) + +Capture/Logging of resource information generated during a time interval. +-b batch mode dump snapshots to standard output (used with -n) +-n number of iterations to dump to standard output (unlimited if not specified) +-d monitor DomIDs as -dD1,-dD2 or -dD1,D2... + Monitor only domains with specified domain IDs +-m monitor nodeIDs as -mN1,-mN2 or -mN1,N2... + Monitor only domains with specified node IDs diff -r 822566f5cfdd -r d39cf132a00a tools/xenstat/vm-top/vm-top.1 --- /dev/null Thu Aug 11 22:18:27 2005 +++ b/tools/xenstat/vm-top/vm-top.1 Fri Aug 12 17:00:35 2005 @@ -0,0 +1,88 @@ +.\" Copyright (C) International Business Machines Corp., 2005 +.\" Author: Josh Triplett +.\" +.\" This program is free software; you can redistribute it and/or modify +.\" it under the terms of the GNU General Public License as published by +.\" the Free Software Foundation; under version 2 of the License. +.\" +.\" This program 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 General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public License +.\" along with this program; if not, write to the Free Software +.\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +.TH vm-top 1 "August 2005" +.SH NAME +\fBvm-top\fR \- displays real-time information about a Xen system and domains + +.SH SYNOPSIS +.B vm-top +[\fB\-h\fR] +[\fB\-V\fR] +[\fB\-d\fRSECONDS] +[\fB\-n\fR] +[\fB\-r\fR] +[\fB\-v\fR] + +.SH DESCRIPTION +\fBvm-top\fR displays information about the Xen system and domains, in a +continually-updating manner. Command-line options and interactive commands +can change the detail and format of the information displayed by \fBvm-top\fR. + +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +display help and exit +.TP +\fB\-V\fR, \fB\-\-version\fR +output version information and exit +.TP +\fB\-d\fR, \fB\-\-delay\fR=\fISECONDS\fR +seconds between updates (default 1) +.TP +\fB\-n\fR, \fB\-\-networks\fR +output network information +.TP +\fB\-r\fR, \fB\-\-repeat\-header\fR +repeat table header before each domain +.TP +\fB\-v\fR, \fB\-\-vcpus\fR +output VCPU data + +.SH "INTERACTIVE COMMANDS" +All interactive commands are case-insensitive. +.TP +.B D +set delay between updates +.TP +.B N +toggle display of network information +.TP +.B Q, Esc +quit +.TP +.B R +toggle table header before each domain +.TP +.B S +cycle sort order +.TP +.B V +toggle display of VCPU information +.TP +.B Arrows +scroll domain display + +.SH AUTHORS +Written by Judy Fischbach, David Hendricks, and Josh Triplett + +.SH "REPORTING BUGS" +Report bugs to . + +.SH COPYRIGHT +Copyright \(co 2005 International Business Machines Corp +.br +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff -r 822566f5cfdd -r d39cf132a00a tools/xenstat/vm-top/vm-top.c --- /dev/null Thu Aug 11 22:18:27 2005 +++ b/tools/xenstat/vm-top/vm-top.c Fri Aug 12 17:00:35 2005 @@ -0,0 +1,880 @@ +/* + * Copyright (C) International Business Machines Corp., 2005 + * Author(s): Judy Fischbach + * David Hendricks + * Josh Triplett + * based on code from Anthony Liguori + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 2 of the License. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define VM_TOP_VERSION "1.0" + +#define VM_TOP_DISCLAIMER \ +"Copyright (C) 2005 International Business Machines Corp\n"\ +"This is free software; see the source for copying conditions.There is NO\n"\ +"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" +#define VM_TOP_BUGSTO "Report bugs to .\n" + +#define _GNU_SOURCE +#include + +#if !defined(__GNUC__) && !defined(__GNUG__) +#define __attribute__(arg) /* empty */ +#endif + +#define KEY_ESCAPE '\x1B' + +/* + * Function prototypes + */ +/* Utility functions */ +static void usage(const char *); +static void version(void); +static void cleanup(void); +static void fail(const char *); +static int current_row(void); +static int lines(void); +static void print(const char *, ...) __attribute__((format(printf,1,2))); +static void attr_addstr(int attr, const char *str); +static void set_delay(char *value); +static void set_prompt(char *new_prompt, void (*func)(char *)); +static int handle_key(int); +static int compare(unsigned long long, unsigned long long); +static int compare_domains(xenstat_domain **, xenstat_domain **); +static unsigned long long tot_net_bytes( xenstat_domain *, int); + +/* Field functions */ +static int compare_domid(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_domid(xenstat_domain *domain); +static int compare_state(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_state(xenstat_domain *domain); +static int compare_cpu(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_cpu(xenstat_domain *domain); +static int compare_cpu_pct(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_cpu_pct(xenstat_domain *domain); +static int compare_mem(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_mem(xenstat_domain *domain); +static void print_mem_pct(xenstat_domain *domain); +static int compare_maxmem(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_maxmem(xenstat_domain *domain); +static void print_max_pct(xenstat_domain *domain); +static int compare_vcpus(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_vcpus(xenstat_domain *domain); +static int compare_nets(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_nets(xenstat_domain *domain); +static int compare_net_tx(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_net_tx(xenstat_domain *domain); +static int compare_net_rx(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_net_rx(xenstat_domain *domain); +static int compare_ssid(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_ssid(xenstat_domain *domain); + +/* Section printing functions */ +static void do_summary(void); +static void do_header(void); +static void do_bottom_line(void); +static void do_domain(xenstat_domain *); +static void do_vcpu(xenstat_domain *); +static void do_network(xenstat_domain *); +static void top(void); + +/* Field types */ +typedef enum field_id { + FIELD_DOMID, + FIELD_STATE, + FIELD_CPU, + FIELD_CPU_PCT, + FIELD_MEM, + FIELD_MEM_PCT, + FIELD_MAXMEM, + FIELD_MAX_PCT, + FIELD_VCPUS, + FIELD_NETS, + FIELD_NET_TX, + FIELD_NET_RX, + FIELD_SSID +} field_id; + +typedef struct field { + field_id num; + const char *header; + unsigned int default_width; + int (*compare)(xenstat_domain *domain1, xenstat_domain *domain2); + void (*print)(xenstat_domain *domain); +} field; + +field fields[] = { + { FIELD_DOMID, "DOMID", 5, compare_domid, print_domid }, + { FIELD_STATE, "STATE", 6, compare_state, print_state }, + { FIELD_CPU, "CPU(sec)", 10, compare_cpu, print_cpu }, + { FIELD_CPU_PCT, "CPU(%)", 6, compare_cpu_pct, print_cpu_pct }, + { FIELD_MEM, "MEM(k)", 10, compare_mem, print_mem }, + { FIELD_MEM_PCT, "MEM(%)", 6, compare_mem, print_mem_pct }, + { FIELD_MAXMEM, "MAXMEM(k)", 10, compare_maxmem, print_maxmem }, + { FIELD_MAX_PCT, "MAXMEM(%)", 9, compare_maxmem, print_max_pct }, + { FIELD_VCPUS, "VCPUS", 5, compare_vcpus, print_vcpus }, + { FIELD_NETS, "NETS", 4, compare_nets, print_nets }, + { FIELD_NET_TX, "NETTX(k)", 8, compare_net_tx, print_net_tx }, + { FIELD_NET_RX, "NETRX(k)", 8, compare_net_rx, print_net_rx }, + { FIELD_SSID, "SSID", 4, compare_ssid, print_ssid } +}; + +const unsigned int NUM_FIELDS = sizeof(fields)/sizeof(field); + +/* Globals */ +struct timeval curtime, oldtime; +xenstat_handle *xhandle = NULL; +xenstat_node *prev_node = NULL; +xenstat_node *cur_node = NULL; +field_id sort_field = FIELD_DOMID; +unsigned int first_domain_index = 0; +unsigned int delay = 1; +int show_vcpus = 0; +int show_networks = 0; +int repeat_header = 0; +#define PROMPT_VAL_LEN 80 +char *prompt = NULL; +char prompt_val[PROMPT_VAL_LEN]; +int prompt_val_len = 0; +void (*prompt_complete_func)(char *); + +/* + * Function definitions + */ + +/* Utility functions */ + +/* Print usage message, using given program name */ +static void usage(const char *program) +{ + printf("Usage: %s [OPTION]\n" + "Displays ongoing information about xen vm resources \n\n" + "-h, --help display this help and exit\n" + "-V, --version output version information and exit\n" + "-d, --delay=SECONDS seconds between updates (default 1)\n" + "-n, --networks output vif network data\n" + "-r, --repeat-header repeat table header before each domain\n" + "-v, --vcpus output vcpu data\n" + "\n" VM_TOP_BUGSTO, + program); + return; +} + +/* Print program version information */ +static void version(void) +{ + printf("vm-top " VM_TOP_VERSION "\n" + "Written by Judy Fischbach, David Hendricks, Josh Triplett\n" + "\n" VM_TOP_DISCLAIMER); +} + +/* Clean up any open resources */ +static void cleanup(void) +{ + if(!isendwin()) + endwin(); + if(prev_node != NULL) + xenstat_free_node(prev_node); + if(cur_node != NULL) + xenstat_free_node(cur_node); + if(xhandle != NULL) + xenstat_uninit(xhandle); +} + +/* Display the given message and gracefully exit */ +static void fail(const char *str) +{ + if(!isendwin()) + endwin(); + fprintf(stderr, str); + exit(1); +} + +/* Return the row containing the cursor. */ +static int current_row(void) +{ + int y, x; + getyx(stdscr, y, x); + return y; +} + +/* Return the number of lines on the screen. */ +static int lines(void) +{ + int y, x; + getmaxyx(stdscr, y, x); + return y; +} + +/* printf-style print function which calls printw, but only if the cursor is + * not on the last line. */ +static void print(const char *fmt, ...) +{ + va_list args; + + if(current_row() < lines()-1) { + va_start(args, fmt); + vw_printw(stdscr, fmt, args); + va_end(args); + } +} + +/* Print a string with the given attributes set. */ +static void attr_addstr(int attr, const char *str) +{ + attron(attr); + addstr(str); + attroff(attr); +} + +/* Handle setting the delay from the user-supplied value in prompt_val */ +static void set_delay(char *value) +{ + int new_delay; + new_delay = atoi(prompt_val); + if(new_delay > 0) + delay = new_delay; +} + +/* Enable prompting mode with the given prompt string; call the given function + * when a value is available. */ +static void set_prompt(char *new_prompt, void (*func)(char *)) +{ + prompt = new_prompt; + prompt_val[0] = '\0'; + prompt_val_len = 0; + prompt_complete_func = func; +} + +/* Handle user input, return 0 if the program should quit, or 1 if not */ +static int handle_key(int ch) +{ + if(prompt == NULL) { + /* Not prompting for input; handle interactive commands */ + switch(ch) { + case 'n': case 'N': + show_networks ^= 1; + break; + case 'r': case 'R': + repeat_header ^= 1; + break; + case 's': case 'S': + sort_field = (sort_field + 1) % NUM_FIELDS; + break; + case 'v': case 'V': + show_vcpus ^= 1; + break; + case KEY_DOWN: + first_domain_index++; + break; + case KEY_UP: + if(first_domain_index > 0) + first_domain_index--; + break; + case 'd': case 'D': + set_prompt("Delay(sec)", set_delay); + break; + case 'q': case 'Q': case KEY_ESCAPE: + return 0; + } + } else { + /* Prompting for input; handle line editing */ + switch(ch) { + case '\r': + prompt_complete_func(prompt_val); + set_prompt(NULL, NULL); + break; + case KEY_ESCAPE: + set_prompt(NULL, NULL); + break; + case KEY_BACKSPACE: + if(prompt_val_len > 0) + prompt_val[--prompt_val_len] = '\0'; + default: + if((prompt_val_len+1) < PROMPT_VAL_LEN + && isprint(ch)) { + prompt_val[prompt_val_len++] = (char)ch; + prompt_val[prompt_val_len] = '\0'; + } + } + } + + return 1; +} + +/* Compares two integers, returning -1,0,1 for <,=,> */ +static int compare(unsigned long long i1, unsigned long long i2) +{ + if(i1 < i2) + return -1; + if(i1 > i2) + return 1; + return 0; +} + +/* Comparison function for use with qsort. Compares two domains using the + * current sort field. */ +static int compare_domains(xenstat_domain **domain1, xenstat_domain **domain2) +{ + return fields[sort_field].compare(*domain1, *domain2); +} + +/* Field functions */ + +/* Compares domain ids of two domains, returning -1,0,1 for <,=,> */ +int compare_domid(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return compare(xenstat_domain_id(domain1), xenstat_domain_id(domain2)); +} + +/* Prints domain identification number */ +void print_domid(xenstat_domain *domain) +{ + print("%5u", xenstat_domain_id(domain)); +} + +struct { + unsigned int (*get)(xenstat_domain *); + char ch; +} state_funcs[] = { + { xenstat_domain_dying, 'd' }, + { xenstat_domain_shutdown, 's' }, + { xenstat_domain_blocked, 'b' }, + { xenstat_domain_crashed, 'c' }, + { xenstat_domain_paused, 'p' }, + { xenstat_domain_running, 'r' } +}; +const unsigned int NUM_STATES = sizeof(state_funcs)/sizeof(*state_funcs); + +/* Compare states of two domains, returning -1,0,1 for <,=,> */ +static int compare_state(xenstat_domain *domain1, xenstat_domain *domain2) +{ + unsigned int i, d1s, d2s; + for(i = 0; i < NUM_STATES; i++) { + d1s = state_funcs[i].get(domain1); + d2s = state_funcs[i].get(domain2); + if(d1s && !d2s) + return -1; + if(d2s && !d1s) + return 1; + } + return 0; +} + +/* Prints domain state in abbreviated letter format */ +static void print_state(xenstat_domain *domain) +{ + unsigned int i; + for(i = 0; i < NUM_STATES; i++) + print("%c", state_funcs[i].get(domain) ? state_funcs[i].ch + : '-'); +} + +/* Compares cpu usage of two domains, returning -1,0,1 for <,=,> */ +static int compare_cpu(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(xenstat_domain_cpu_ns(domain1), + xenstat_domain_cpu_ns(domain2)); +} + +/* Prints domain cpu usage in seconds */ +static void print_cpu(xenstat_domain *domain) +{ + print("%10llu", xenstat_domain_cpu_ns(domain)/1000000000); +} + +/* Computes the CPU percentage used for a specified domain */ +static double get_cpu_pct(xenstat_domain *domain) +{ + xenstat_domain *old_domain; + double us_elapsed; + + /* Can't calculate CPU percentage without a previous sample. */ + if(prev_node == NULL) + return 0.0; + + old_domain = xenstat_node_domain(prev_node, xenstat_domain_id(domain)); + if(old_domain == NULL) + return 0.0; + + /* Calculate the time elapsed in microseconds */ + us_elapsed = ((curtime.tv_sec-oldtime.tv_sec)*1000000.0 + +(curtime.tv_usec - oldtime.tv_usec)); + + /* In the following, nanoseconds must be multiplied by 1000.0 to + * convert to microseconds, then divided by 100.0 to get a percentage, + * resulting in a multiplication by 10.0 */ + return ((xenstat_domain_cpu_ns(domain) + -xenstat_domain_cpu_ns(old_domain))/10.0)/us_elapsed; +} + +static int compare_cpu_pct(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(get_cpu_pct(domain1), get_cpu_pct(domain2)); +} + +/* Prints cpu percentage statistic */ +static void print_cpu_pct(xenstat_domain *domain) +{ + print("%6.1f", get_cpu_pct(domain)); +} + +/* Compares current memory of two domains, returning -1,0,1 for <,=,> */ +static int compare_mem(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(xenstat_domain_cur_mem(domain1), + xenstat_domain_cur_mem(domain2)); +} + +/* Prints current memory statistic */ +static void print_mem(xenstat_domain *domain) +{ + print("%10llu", xenstat_domain_cur_mem(domain)/1024); +} + +/* Prints memory percentage statistic, ratio of current domain memory to total + * node memory */ +static void print_mem_pct(xenstat_domain *domain) +{ + print("%6.1f", (double)xenstat_domain_cur_mem(domain) / + (double)xenstat_node_tot_mem(cur_node) * 100); +} + +/* Compares maximum memory of two domains, returning -1,0,1 for <,=,> */ +static int compare_maxmem(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(xenstat_domain_max_mem(domain1), + xenstat_domain_max_mem(domain2)); +} + +/* Prints maximum domain memory statistic in KB */ +static void print_maxmem(xenstat_domain *domain) +{ + unsigned long long max_mem = xenstat_domain_max_mem(domain); + if(max_mem == ((unsigned long long)-1)) + print("%10s", "no limit"); + else + print("%10llu", max_mem/1024); +} + +/* Prints memory percentage statistic, ratio of current domain memory to total + * node memory */ +static void print_max_pct(xenstat_domain *domain) +{ + if (xenstat_domain_max_mem(domain) == (unsigned long long)-1) + print("%9s", "n/a"); + else + print("%9.1f", (double)xenstat_domain_max_mem(domain) / + (double)xenstat_node_tot_mem(cur_node) * 100); +} + +/* Compares number of virtual CPUs of two domains, returning -1,0,1 for + * <,=,> */ +static int compare_vcpus(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(xenstat_domain_num_vcpus(domain1), + xenstat_domain_num_vcpus(domain2)); +} + +/* Prints number of virtual CPUs statistic */ +static void print_vcpus(xenstat_domain *domain) +{ + print("%5u", xenstat_domain_num_vcpus(domain)); +} + +/* Compares number of virtual networks of two domains, returning -1,0,1 for + * <,=,> */ +static int compare_nets(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(xenstat_domain_num_networks(domain1), + xenstat_domain_num_networks(domain2)); +} + +/* Prints number of virtual networks statistic */ +static void print_nets(xenstat_domain *domain) +{ + print("%4u", xenstat_domain_num_networks(domain)); +} + +/* Compares number of total network tx bytes of two domains, returning -1,0,1 for + * <,=,> */ +static int compare_net_tx(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(tot_net_bytes(domain1, FALSE), + tot_net_bytes(domain2, FALSE)); +} + +/* Prints number of total network tx bytes statistic */ +static void print_net_tx(xenstat_domain *domain) +{ + print("%8llu", tot_net_bytes(domain, FALSE)/1024); +} + +/* Compares number of total network rx bytes of two domains, returning -1,0,1 for + * <,=,> */ +static int compare_net_rx(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(tot_net_bytes(domain1, TRUE), + tot_net_bytes(domain2, TRUE)); +} + +/* Prints number of total network rx bytes statistic */ +static void print_net_rx(xenstat_domain *domain) +{ + print("%8llu", tot_net_bytes(domain, TRUE)/1024); +} + +/* Gets number of total network bytes statistic, if rx true, then rx bytes + * otherwise tx bytes + */ +static unsigned long long tot_net_bytes(xenstat_domain *domain, int rx_flag) +{ + int i = 0; + xenstat_network *network; + unsigned num_networks = 0; + unsigned long long total = 0; + + /* How many networks? */ + num_networks = xenstat_domain_num_networks(domain); + + /* Dump information for each network */ + for (i=0; i < num_networks; i++) { + /* Next get the network information */ + network = xenstat_domain_network(domain,i); + if (rx_flag) + total += xenstat_network_rbytes(network); + else + total += xenstat_network_tbytes(network); + } + return (total); +} + +/* Compares security id (ssid) of two domains, returning -1,0,1 for <,=,> */ +static int compare_ssid(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return compare(xenstat_domain_ssid(domain1), + xenstat_domain_ssid(domain2)); +} + +/* Prints ssid statistic */ +static void print_ssid(xenstat_domain *domain) +{ + print("%4u", xenstat_domain_ssid(domain)); +} + +/* Section printing functions */ +/* Prints three line summary header */ +void do_summary(void) +{ +#define TIME_STR_LEN 9 + const char *TIME_STR_FORMAT = "%H:%M:%S"; + char time_str[TIME_STR_LEN]; + unsigned run = 0, block = 0, pause = 0, + crash = 0, dying = 0, shutdown = 0; + unsigned i, num_domains = 0; + unsigned long long used = 0; + xenstat_domain *domain; + + /* Print program name, current time, and number of domains */ + strftime(time_str, TIME_STR_LEN, TIME_STR_FORMAT, + localtime(&curtime.tv_sec)); + num_domains = xenstat_node_num_domains(cur_node); + print("vm-top - %s\n", time_str); + + /* Tabulate what states domains are in for summary */ + for (i=0; i < num_domains; i++) { + domain = xenstat_node_domain_by_index(cur_node,i); + if (xenstat_domain_running(domain)) run++; + else if (xenstat_domain_blocked(domain)) block++; + else if (xenstat_domain_paused(domain)) pause++; + else if (xenstat_domain_shutdown(domain)) shutdown++; + else if (xenstat_domain_crashed(domain)) crash++; + else if (xenstat_domain_dying(domain)) dying++; + } + + print("%u domains: %u running, %u blocked, %u paused, " + "%u crashed, %u dying, %u shutdown \n", + num_domains, run, block, pause, crash, dying, shutdown); + + used = xenstat_node_tot_mem(cur_node)-xenstat_node_free_mem(cur_node); + + /* Dump node memory and cpu information */ + print("Mem: %lluk total, %lluk used, %lluk free " + "CPUs: %u @ %lluMHz\n", + xenstat_node_tot_mem(cur_node)/1024, used/1024, + xenstat_node_free_mem(cur_node)/1024, + xenstat_node_num_cpus(cur_node), + xenstat_node_cpu_hz(cur_node)/1000000); +} + +/* Display top portion of vm-top */ +void do_header(void) +{ + field_id i; + + /* Turn on REVERSE highlight attribute for headings */ + attron(A_REVERSE); + for(i = 0; i < NUM_FIELDS; i++) { + if(i != 0) + print(" "); + /* The BOLD attribute is turned on for the sort column */ + if(i == sort_field) + attron(A_BOLD); + print("%*s", fields[i].default_width, fields[i].header); + if(i == sort_field) + attroff(A_BOLD); + } + attroff(A_REVERSE); + print("\n"); +} + +/* Displays bottom portion of vm-top, interactive options + * N toggles network information display, V toggles CPU information + * display, S toggles sort order of information (ascending/descending), + * R toggles whether header is repeated for each domain + */ +void do_bottom_line(void) +{ + move(lines()-1, 2); + + if (prompt != NULL) { + printw("%s: %s", prompt, prompt_val); + } else { + addch(A_REVERSE | 'D'); addstr("elay "); + + /* network */ + addch(A_REVERSE | 'N'); + attr_addstr(show_networks ? COLOR_PAIR(1) : 0, "etworks"); + addstr(" "); + + /* vcpus */ + addch(A_REVERSE | 'V'); + attr_addstr(show_vcpus ? COLOR_PAIR(1) : 0, "CPUs"); + addstr(" "); + + /* repeat */ + addch(A_REVERSE | 'R'); + attr_addstr(repeat_header ? COLOR_PAIR(1) : 0, "epeat header"); + addstr(" "); + + /* sort order */ + addch(A_REVERSE | 'S'); addstr("ort order "); + + addch(A_REVERSE | 'Q'); addstr("uit "); + } +} + +/* Prints Domain information */ +void do_domain(xenstat_domain *domain) +{ + unsigned int i; + for(i = 0; i < NUM_FIELDS; i++) { + if(i != 0) + print(" "); + if(i == sort_field) + attron(A_BOLD); + fields[i].print(domain); + if(i == sort_field) + attroff(A_BOLD); + } + print("\n"); +} + +/* Output all vcpu information */ +void do_vcpu(xenstat_domain *domain) +{ + int i = 0; + unsigned num_vcpus = 0; + xenstat_vcpu *vcpu; + + print("VCPUs(sec): "); + + num_vcpus = xenstat_domain_num_vcpus(domain); + + /* for all vcpus dump out values */ + for (i=0; i< num_vcpus; i++) { + vcpu = xenstat_domain_vcpu(domain,i); + + if (i != 0 && (i%5)==0) + print("\n "); + print(" %2u: %10llus", i, xenstat_vcpu_ns(vcpu)/1000000000); + } + print("\n"); +} + +/* Output all network information */ +void do_network(xenstat_domain *domain) +{ + int i = 0; + xenstat_network *network; + unsigned num_networks = 0; + + /* How many networks? */ + num_networks = xenstat_domain_num_networks(domain); + + /* Dump information for each network */ + for (i=0; i < num_networks; i++) { + /* Next get the network information */ + network = xenstat_domain_network(domain,i); + + print("Net%d RX: %8llubytes %8llupkts %8lluerr %8lludrop ", + i, + xenstat_network_rbytes(network), + xenstat_network_rpackets(network), + xenstat_network_rerrs(network), + xenstat_network_rdrop(network)); + + print("TX: %8llubytes %8llupkts %8lluerr %8lludrop\n", + xenstat_network_tbytes(network), + xenstat_network_tpackets(network), + xenstat_network_terrs(network), + xenstat_network_tdrop(network)); + } +} + +static void top(void) +{ + xenstat_domain **domains; + unsigned int i, num_domains = 0; + + /* Now get the node information */ + if (prev_node != NULL) + xenstat_free_node(prev_node); + prev_node = cur_node; + cur_node = xenstat_get_node(xhandle, XENSTAT_ALL); + if (cur_node == NULL) + fail("Failed to retrieve statistics from libxenstat\n"); + + /* dump summary top information */ + do_summary(); + + /* Count the number of domains for which to report data */ + num_domains = xenstat_node_num_domains(cur_node); + + domains = malloc(num_domains*sizeof(xenstat_domain *)); + if(domains == NULL) + fail("Failed to allocate memory\n"); + + for (i=0; i < num_domains; i++) + domains[i] = xenstat_node_domain_by_index(cur_node, i); + + /* Sort */ + qsort(domains, num_domains, sizeof(xenstat_domain *), + (int(*)(const void *, const void *))compare_domains); + + if(first_domain_index >= num_domains) + first_domain_index = num_domains-1; + + for (i = first_domain_index; i < num_domains; i++) { + if(current_row() == lines()-1) + break; + if (i == first_domain_index || repeat_header) + do_header(); + do_domain(domains[i]); + if (show_vcpus) + do_vcpu(domains[i]); + if (show_networks) + do_network(domains[i]); + } + + do_bottom_line(); +} + +int main(int argc, char **argv) +{ + int opt, optind = 0; + int ch = ERR; + + struct option lopts[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'V' }, + { "networks", no_argument, NULL, 'n' }, + { "repeat-header", no_argument, NULL, 'r' }, + { "vcpus", no_argument, NULL, 'v' }, + { "delay", required_argument, NULL, 'd' }, + { 0, 0, 0, 0 }, + }; + const char *sopts = "hVbnvd:"; + + if (atexit(cleanup) != 0) + fail("Failed to install cleanup handler.\n"); + + while ((opt = getopt_long(argc, argv, sopts, lopts, &optind)) != -1) { + switch (opt) { + case 'h': + case '?': + default: + usage(argv[0]); + exit(0); + case 'V': + version(); + exit(0); + case 'n': + show_networks = 1; + break; + case 'r': + repeat_header = 1; + break; + case 'v': + show_vcpus = 1; + break; + case 'd': + delay = atoi(optarg); + break; + } + } + + /* Get xenstat handle */ + xhandle = xenstat_init(); + if (xhandle == NULL) + fail("Failed to initialize xenstat library\n"); + + /* Begin curses stuff */ + initscr(); + start_color(); + cbreak(); + noecho(); + nonl(); + keypad(stdscr, TRUE); + halfdelay(5); + use_default_colors(); + init_pair(1, -1, COLOR_YELLOW); + + do { + gettimeofday(&curtime, NULL); + if(ch != ERR || (curtime.tv_sec - oldtime.tv_sec) >= delay) { + clear(); + top(); + oldtime = curtime; + refresh(); + } + ch = getch(); + } while (handle_key(ch)); + + /* Cleanup occurs in cleanup(), so no work to do here. */ + + return 0; +} # HG changeset patch # User josht@xxxxxxxxxx # Node ID e6dba3fbb17e54a7f402acb071c62a329edbcc48 # Parent d39cf132a00a91e65c0ad4640c5bd17f722788b7 Make vm-top and the xenstat perl and python bindings conditional based on configuration variables from Config.mk, rather than disabling them if the needed headers are not found. diff -r d39cf132a00a -r e6dba3fbb17e Config.mk --- a/Config.mk Fri Aug 12 17:00:35 2005 +++ b/Config.mk Fri Aug 12 23:15:51 2005 @@ -35,3 +35,8 @@ # Choose the best mirror to download linux kernel KERNEL_REPO = http://www.kernel.org + +# Optional components +XENSTAT_PERL_BINDINGS ?= n +XENSTAT_PYTHON_BINDINGS ?= y +XENSTAT_VM_TOP ?= y diff -r d39cf132a00a -r e6dba3fbb17e tools/xenstat/libxenstat/Makefile --- a/tools/xenstat/libxenstat/Makefile Fri Aug 12 17:00:35 2005 +++ b/tools/xenstat/libxenstat/Makefile Fri Aug 12 23:15:51 2005 @@ -42,8 +42,6 @@ CFLAGS+=-I$(LINUX_ROOT)/include/asm-xen/linux-public/ LDFLAGS+=-Lsrc -# Note that the bindings are not built by default, because they require a -# number of external dependencies. all: $(LIB) $(LINKS) $(LIB): $(OBJECTS) @@ -81,12 +79,16 @@ BINDINGSRC=$(PYSRC) $(PERLSRC) # The all-bindings target builds all the language bindings -all-bindings: $(BINDINGS) +all-bindings: perl-bindings python-bindings + +# The install-bindings target installs all the language bindings +install-bindings: install-perl-bindings install-python-bindings $(BINDINGS): $(LIB) $(LINKS) src/xenstat.h SWIG_FLAGS=-module xenstat -Isrc +# Python bindings PYTHON_VERSION=2.3 PYTHON_FLAGS=-I/usr/include/python$(PYTHON_VERSION) -lpython$(PYTHON_VERSION) $(PYSRC) $(PYMOD): bindings/swig/xenstat.i @@ -95,6 +97,19 @@ $(PYLIB): $(PYSRC) $(CC) $(CFLAGS) $(LDFLAGS) $(PYTHON_FLAGS) -shared -lxenstat -o $@ $< +python-bindings: $(PYLIB) $(PYMOD) + +pythonlibdir=$(prefix)/lib/python$(PYTHON_VERSION)/site-packages +install-python-bindings: $(PYLIB) $(PYMOD) + $(INSTALL_PROG) $(PYLIB) $(DESTDIR)$(pythonlibdir)/_xenstat.so + $(INSTALL_PROG) $(PYMOD) $(DESTDIR)$(pythonlibdir)/xenstat.py + +ifeq ($(XENSTAT_PYTHON_BINDINGS),y) +all: python-bindings +install: install-python-bindings +endif + +# Perl bindings PERL_FLAGS=`perl -MConfig -e 'print "$$Config{ccflags} -I$$Config{archlib}/CORE";'` $(PERLSRC) $(PERLMOD): bindings/swig/xenstat.i swig -perl $(SWIG_FLAGS) -outdir $(@D) -o $(PERLSRC) $< @@ -102,19 +117,18 @@ $(PERLLIB): $(PERLSRC) $(CC) $(CFLAGS) $(LDFLAGS) $(PERL_FLAGS) -shared -lxenstat -o $@ $< -# The install-bindings target installs all the language bindings -install-bindings: install-perl-bindings install-python-bindings +perl-bindings: $(PERLLIB) $(PERLMOD) -pythonlibdir=$(prefix)/lib/python$(PYTHON_VERSION)/site-packages -install-python-bindings: $(PYLIB) $(PYMOD) - $(INSTALL_PROG) $(PYLIB) $(pythonlibdir)/_xenstat.so - $(INSTALL_PROG) $(PYMOD) $(pythonlibdir)/xenstat.py +perllibdir=$(prefix)/lib/perl5 +perlmoddir=$(prefix)/share/perl5 +install-perl-bindings: $(PERLLIB) $(PERLMOD) + $(INSTALL_PROG) $(PERLLIB) $(DESTDIR)$(perllibdir)/xenstat.so + $(INSTALL_PROG) $(PERLMOD) $(DESTDIR)$(perlmoddir)/xenstat.pm -perllibdir=$(prefix)/lib/site_perl -perlmoddir=$(prefix)/lib/site_perl -install-perl-bindings: $(PERLLIB) $(PERLMOD) - $(INSTALL_PROG) $(PERLLIB) $(perllibdir)/xenstat.so - $(INSTALL_PROG) $(PERLMOD) $(perlmoddir)/xenstat.pm +ifeq ($(XENSTAT_PERL_BINDINGS),y) +all: perl-bindings +install: install-perl-bindings +endif clean: rm -f $(LIB) $(OBJECTS) $(LINKS) $(BINDINGS) $(BINDINGSRC) diff -r d39cf132a00a -r e6dba3fbb17e tools/xenstat/vm-top/Makefile --- a/tools/xenstat/vm-top/Makefile Fri Aug 12 17:00:35 2005 +++ b/tools/xenstat/vm-top/Makefile Fri Aug 12 23:15:51 2005 @@ -10,15 +10,12 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -ifneq (,$(shell [ -e /usr/include/curses.h ] || echo no)) -all vm-top: - @echo "***********************************************************" - @echo "WARNING: Install ncurses to build vm-top." - @echo "***********************************************************" -else - XEN_ROOT=../../.. include $(XEN_ROOT)/tools/Rules.mk + +ifneq ($(XENSTAT_VM_TOP),y) +all install vm-top: +else INSTALL = install INSTALL_PROG = $(INSTALL) -m0755 -D @@ -36,12 +33,11 @@ vm-top: vm-top.o +install: vm-top vm-top.1 + $(INSTALL_PROG) vm-top $(DESTDIR)$(sbindir)/vm-top + $(INSTALL_DATA) vm-top.1 $(DESTDIR)$(man1dir)/vm-top.1 + endif - -install: vm-top vm-top.1 - [ -f vm-top ] && $(INSTALL_PROG) vm-top $(DESTDIR)$(sbindir)/vm-top - [ -f vm-top.1 ] && \ - $(INSTALL_DATA) vm-top.1 $(DESTDIR)$(man1dir)/vm-top.1 clean: rm -f vm-top vm-top.o # HG changeset patch # User josht@xxxxxxxxxx # Node ID a6e9d8a95789c364df73957c688c17d5e74a5ace # Parent 058a50bd0f1ef5bf75338212d19d746d9a9ed422 Add placeholder files to avoid removal of the tools/xenstat/libxenstat/bindings/swig/{perl,python} output directories. diff -r 058a50bd0f1e -r a6e9d8a95789 tools/xenstat/libxenstat/bindings/swig/perl/.empty --- /dev/null Mon Aug 15 17:29:20 2005 +++ b/tools/xenstat/libxenstat/bindings/swig/perl/.empty Mon Aug 15 17:36:05 2005 @@ -0,0 +1,1 @@ +This directory is empty; this file is included to prevent version control systems from removing the directory. diff -r 058a50bd0f1e -r a6e9d8a95789 tools/xenstat/libxenstat/bindings/swig/python/.empty --- /dev/null Mon Aug 15 17:29:20 2005 +++ b/tools/xenstat/libxenstat/bindings/swig/python/.empty Mon Aug 15 17:36:05 2005 @@ -0,0 +1,1 @@ +This directory is empty; this file is included to prevent version control systems from removing the directory.