summaryrefslogtreecommitdiff
path: root/src/pmdas/aix
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmdas/aix')
-rw-r--r--src/pmdas/aix/GNUmakefile69
-rw-r--r--src/pmdas/aix/aix.c127
-rw-r--r--src/pmdas/aix/common.h104
-rw-r--r--src/pmdas/aix/cpu.c186
-rw-r--r--src/pmdas/aix/cpu_total.c133
-rw-r--r--src/pmdas/aix/data.c435
-rw-r--r--src/pmdas/aix/disk.c189
-rw-r--r--src/pmdas/aix/disk_total.c127
-rw-r--r--src/pmdas/aix/help61
-rw-r--r--src/pmdas/aix/netif.c190
-rw-r--r--src/pmdas/aix/pmns.disk22
-rw-r--r--src/pmdas/aix/pmns.hinv6
-rw-r--r--src/pmdas/aix/pmns.kernel77
-rw-r--r--src/pmdas/aix/pmns.mem2
-rw-r--r--src/pmdas/aix/pmns.network26
-rw-r--r--src/pmdas/aix/root20
16 files changed, 1774 insertions, 0 deletions
diff --git a/src/pmdas/aix/GNUmakefile b/src/pmdas/aix/GNUmakefile
new file mode 100644
index 0000000..9282d76
--- /dev/null
+++ b/src/pmdas/aix/GNUmakefile
@@ -0,0 +1,69 @@
+#
+# Copyright (c) 2000,2003,2004 Silicon Graphics, Inc. All Rights Reserved.
+#
+# 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; either version 2 of the License, or (at your
+# option) any later version.
+#
+# 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.
+#
+
+TOPDIR = ../../..
+include $(TOPDIR)/src/include/builddefs
+
+IAM = aix
+DOMAIN = AIX
+CMDTARGET = pmdaaix
+LIBTARGET = pmda_aix.so
+PMDADIR = $(PCP_PMDAS_DIR)/$(IAM)
+CONF_LINE = "aix 80 dso aix_init $(PMDADIR)/$(LIBTARGET)"
+
+CFILES = aix.c data.c disk_total.c disk.c cpu_total.c cpu.c netif.c
+
+LLDLIBS = $(PCP_PMDALIB) -lperfstat
+PMNS = pmns.disk pmns.kernel pmns.mem pmns.network pmns.hinv
+LSRCFILES = $(PMNS) help root common.h
+
+LDIRT = *.log *.dir *.pag root_aix domain.h
+
+default: build-me
+
+ifeq "$(TARGET_OS)" "aix"
+build-me: common.h root_aix domain.h $(CMDTARGET) $(LIBTARGET) help.dir help.pag
+ @if [ `grep -c $(CONF_LINE) ../pmcd.conf` -eq 0 ]; then \
+ echo $(CONF_LINE) >> ../pmcd.conf ; \
+ fi
+
+install: build-me
+ $(INSTALL) -m 755 -d $(PMDADIR)
+ $(INSTALL) -m 644 domain.h help.dir help.pag $(PMDADIR)
+ $(INSTALL) -m 755 $(LIBTARGET) $(CMDTARGET) $(PMDADIR)
+ $(INSTALL) -m 644 root_aix $(PCP_VAR_DIR)/pmns/root_aix
+else
+build-me:
+install:
+endif
+
+$(OBJECTS): common.h
+
+include $(BUILDRULES)
+
+default_pcp : default
+
+install_pcp : install
+
+help.dir help.pag: help root_aix
+ $(RUN_IN_BUILD_ENV) $(TOPDIR)/src/newhelp/newhelp -n root_aix -v 2 -o help < help
+
+root_aix: ../../pmns/stdpmid
+ rm -f root_aix
+ sed -e 's;<stdpmid>;"../../pmns/stdpmid";' <root \
+ | $(RUN_IN_BUILD_ENV) $(TOPDIR)/src/pmcpp/pmcpp \
+ | sed -e '/^#/d' -e '/^$$/d' >root_aix
+
+domain.h: ../../pmns/stdpmid
+ $(DOMAIN_MAKERULE)
diff --git a/src/pmdas/aix/aix.c b/src/pmdas/aix/aix.c
new file mode 100644
index 0000000..335aacd
--- /dev/null
+++ b/src/pmdas/aix/aix.c
@@ -0,0 +1,127 @@
+/*
+ * AIX PMDA
+ *
+ * Collect performance data from the AIX kernel using libperfstat for
+ * the most part.
+ *
+ * Copyright (c) 2012,2014 Red Hat.
+ * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * 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; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * 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.
+ */
+
+#include <time.h>
+#include "common.h"
+
+static int _isDSO = 1;
+static char mypath[MAXPATHLEN];
+static char *username;
+
+/*
+ * wrapper for pmdaFetch which primes the methods ready for
+ * the next fetch
+ * ... real callback is fetch_callback()
+ */
+static int
+aix_fetch(int numpmid, pmID pmidlist[], pmResult **resp, pmdaExt *pmda)
+{
+ int i;
+
+ // TODO: this should only fetch metrics from "pmidlist"
+ for (i = 0; i < methodtab_sz; i++) {
+ methodtab[i].m_prefetch();
+ }
+
+ return pmdaFetch(numpmid, pmidlist, resp, pmda);
+}
+
+/*
+ * callback provided to pmdaFetch
+ */
+static int
+aix_fetch_callback(pmdaMetric *mdesc, unsigned int inst, pmAtomValue *atom)
+{
+ metricdesc_t *mdp;
+
+ mdp = (metricdesc_t *)mdesc->m_user;
+ return methodtab[mdp->md_method].m_fetch(mdesc, inst, atom);
+}
+
+/*
+ * Initialise the agent (both daemon and DSO).
+ */
+void
+aix_init(pmdaInterface *dp)
+{
+ if (_isDSO) {
+ int sep = __pmPathSeparator();
+ snprintf(mypath, sizeof(mypath), "%s%c" "aix" "%c" "help",
+ pmGetConfig("PCP_PMDAS_DIR"), sep, sep);
+ pmdaDSO(dp, PMDA_INTERFACE_3, "AIX DSO", mypath);
+ } else {
+ __pmSetProcessIdentity(username);
+ }
+
+ if (dp->status != 0)
+ return;
+
+ dp->version.two.fetch = aix_fetch;
+ pmdaSetFetchCallBack(dp, aix_fetch_callback);
+ init_data(dp->domain);
+ pmdaInit(dp, indomtab, indomtab_sz, metrictab, metrictab_sz);
+}
+
+pmLongOptions longopts[] = {
+ PMDA_OPTIONS_HEADER("Options"),
+ PMOPT_DEBUG,
+ PMDAOPT_DOMAIN,
+ PMDAOPT_LOGFILE,
+ PMDAOPT_USERNAME,
+ PMOPT_HELP,
+ PMDA_OPTIONS_END
+};
+
+pmdaOptions opts = {
+ .short_options = "D:d:l:U:?",
+ .long_options = longopts,
+};
+
+/*
+ * Set up the agent if running as a daemon.
+ */
+int
+main(int argc, char **argv)
+{
+ int sep = __pmPathSeparator();
+ pmdaInterface desc;
+
+ _isDSO = 0;
+ __pmSetProgname(argv[0]);
+ __pmGetUsername(&username);
+
+ snprintf(mypath, sizeof(mypath), "%s%c" "aix" "%c" "help",
+ pmGetConfig("PCP_PMDAS_DIR"), sep, sep);
+ pmdaDaemon(&desc, PMDA_INTERFACE_3, pmProgname, AIX, "aix.log", mypath);
+
+ pmdaGetOptions(argc, argv, &opts, &desc);
+ if (opts.errors) {
+ pmdaUsageMessage(&opts);
+ exit(1);
+ }
+ if (opts.username)
+ username = opts.username;
+
+ pmdaOpenLog(&desc);
+ aix_init(&desc);
+ pmdaConnect(&desc);
+ pmdaMain(&desc);
+ exit(0);
+}
diff --git a/src/pmdas/aix/common.h b/src/pmdas/aix/common.h
new file mode 100644
index 0000000..604ff73
--- /dev/null
+++ b/src/pmdas/aix/common.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * 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; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "pmapi.h"
+#include "impl.h"
+#include "pmda.h"
+#include "./domain.h"
+
+typedef long long longlong_t; // TODO nuke for AIX
+typedef unsigned long long u_longlong_t; // TODO nuke for AIX build
+typedef unsigned char uchar; // TODO nuke for AIX build
+
+#include <libperfstat.h>
+
+/*
+ * libperfstat method controls
+ *
+ * md_method choices (see below) ... must be contiguous integers so
+ * we can index directly into method[]
+ */
+#define M_CPU_TOTAL 0
+#define M_CPU 1
+#define M_DISK_TOTAL 2
+#define M_DISK 3
+#define M_NETIF 4
+#define M_NETBUF 5 // TODO
+#define M_PROTO 6 // TODO
+#define M_MEM_TOTAL 7 // TODO
+
+/*
+ * special values for offset
+ */
+#define OFF_NOVALUES -2
+#define OFF_DERIVED -1
+
+typedef struct {
+ void (*m_init)(int);
+ void (*m_prefetch)(void);
+ int (*m_fetch)(pmdaMetric *, int, pmAtomValue *);
+} method_t;
+
+extern method_t methodtab[];
+extern int methodtab_sz;
+
+extern void init_data(int);
+
+extern void cpu_total_init(int);
+extern void cpu_total_prefetch(void);
+extern int cpu_total_fetch(pmdaMetric *, int, pmAtomValue *);
+
+extern void cpu_init(int);
+extern void cpu_prefetch(void);
+extern int cpu_fetch(pmdaMetric *, int, pmAtomValue *);
+
+extern void disk_total_init(int);
+extern void disk_total_prefetch(void);
+extern int disk_total_fetch(pmdaMetric *, int, pmAtomValue *);
+
+extern void disk_init(int);
+extern void disk_prefetch(void);
+extern int disk_fetch(pmdaMetric *, int, pmAtomValue *);
+
+extern void netif_init(int);
+extern void netif_prefetch(void);
+extern int netif_fetch(pmdaMetric *, int, pmAtomValue *);
+
+/*
+ * metric descriptions
+ */
+typedef struct {
+ pmDesc md_desc; // PMDA's idea of the semantics
+ int md_method; // specific stats method
+ int md_offset; // offset into stats structure
+} metricdesc_t;
+
+extern metricdesc_t metricdesc[];
+extern pmdaMetric *metrictab;
+extern int metrictab_sz;
+
+#define DISK_INDOM 0
+#define CPU_INDOM 1
+#define NETIF_INDOM 2
+
+extern pmdaIndom indomtab[];
+extern int indomtab_sz;
diff --git a/src/pmdas/aix/cpu.c b/src/pmdas/aix/cpu.c
new file mode 100644
index 0000000..98d3348
--- /dev/null
+++ b/src/pmdas/aix/cpu.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * 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; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * 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.
+ */
+
+#include "common.h"
+
+static int ncpu;
+static int ncpu_alloc;
+static int *fetched;
+static perfstat_cpu_t *cpustat;
+
+void
+cpu_init(int first)
+{
+ perfstat_id_t id;
+ int i;
+
+ if (!first)
+ /* TODO ... not sure if/when we'll use this re-init hook */
+ return;
+
+ ncpu = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0);
+ if ((fetched = (int *)malloc(ncpu * sizeof(int))) == NULL) {
+ fprintf(stderr, "cpu_init: fetched malloc[%d] failed: %s\n",
+ ncpu * sizeof(int), osstrerror());
+ exit(1);
+ }
+ if ((cpustat = (perfstat_cpu_t *)malloc(ncpu * sizeof(perfstat_cpu_t))) == NULL) {
+ fprintf(stderr, "cpu_init: cpustat malloc[%d] failed: %s\n",
+ ncpu * sizeof(perfstat_cpu_t), osstrerror());
+ exit(1);
+ }
+ ncpu_alloc = ncpu;
+
+ /*
+ * set up instance domain
+ */
+ strcpy(id.name, "");
+ ncpu = perfstat_cpu(&id, cpustat, sizeof(perfstat_cpu_t), ncpu_alloc);
+
+ indomtab[CPU_INDOM].it_numinst = ncpu;
+ indomtab[CPU_INDOM].it_set = (pmdaInstid *)malloc(ncpu * sizeof(pmdaInstid));
+ if (indomtab[CPU_INDOM].it_set == NULL) {
+ fprintf(stderr, "cpu_init: indomtab malloc[%d] failed: %s\n",
+ ncpu * sizeof(pmdaInstid), osstrerror());
+ exit(1);
+ }
+ for (i = 0; i < ncpu; i++) {
+ indomtab[CPU_INDOM].it_set[i].i_inst = i;
+ indomtab[CPU_INDOM].it_set[i].i_name = strdup(cpustat[i].name);
+ }
+
+#ifdef PCP_DEBUG
+ if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) {
+ /* desperate */
+ fprintf(stderr, "cpu_init: ncpu=%d\n", ncpu);
+ }
+#endif
+}
+
+void
+cpu_prefetch(void)
+{
+ int i;
+
+ for (i = 0; i < ncpu_alloc; i++)
+ fetched[i] = 0;
+}
+
+static __uint64_t
+cpu_derived(pmdaMetric *mdesc, int inst)
+{
+ pmID pmid;
+ __pmID_int *ip = (__pmID_int *)&pmid;
+ __uint64_t val;
+
+ pmid = mdesc->m_desc.pmid;
+ ip->domain = 0;
+
+ switch (pmid) {
+
+ default:
+ fprintf(stderr, "cpu_derived: Botch: no method for pmid %s\n",
+ pmIDStr(mdesc->m_desc.pmid));
+ val = 0;
+ break;
+ }
+
+#ifdef PCP_DEBUG
+ if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) {
+ /* desperate */
+ fprintf(stderr, "cpu_derived: pmid %s inst %d val %llu\n",
+ pmIDStr(mdesc->m_desc.pmid), inst, val);
+ }
+#endif
+
+ return val;
+}
+
+int
+cpu_fetch(pmdaMetric *mdesc, int inst, pmAtomValue *atom)
+{
+ int offset;
+
+ if (fetched[inst] == 0) {
+ int sts;
+ int i;
+ perfstat_id_t id;
+
+ strcpy(id.name, "");
+ sts = perfstat_cpu(&id, cpustat, sizeof(perfstat_cpu_t), ncpu_alloc);
+
+ /* TODO ...
+ * - if sts != ncpu, the number of CPUs has changed, need to set
+ * fetched[i] to -1 for the missing ones
+ * - is sts > ncpu possible? worse, if the number of cpus is >
+ * ncpu_alloc what should we do?
+ * - possibly reshape the instance domain?
+ * - error handling?
+ */
+
+ for (i = 0; i < ncpu; i++) {
+ fetched[i] = 1;
+ }
+ }
+
+ if (fetched[inst] != 1)
+ return 0;
+
+ offset = ((metricdesc_t *)mdesc->m_user)->md_offset;
+ if (offset == OFF_NOVALUES)
+ return 0;
+
+ if (mdesc->m_desc.type == PM_TYPE_U64) {
+ if (offset == OFF_DERIVED)
+ atom->ull = cpu_derived(mdesc, inst);
+ else {
+ __uint64_t *ullp;
+ ullp = (__uint64_t *)&((char *)&cpustat[inst])[offset];
+ atom->ull = *ullp;
+ }
+ if (mdesc->m_desc.units.scaleTime == PM_TIME_MSEC) {
+ /* assumed to be CPU time */
+ atom->ull *= 1000 / HZ;
+ }
+#ifdef PCP_DEBUG
+ if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) {
+ /* desperate */
+ fprintf(stderr, "cpu_fetch: pmid %s inst %d val %llu\n",
+ pmIDStr(mdesc->m_desc.pmid), inst, atom->ull);
+ }
+#endif
+ }
+ else {
+ if (offset == OFF_DERIVED)
+ atom->ul = (__uint32_t)cpu_derived(mdesc, inst);
+ else {
+ __uint32_t *ulp;
+ ulp = (__uint32_t *)&((char *)&cpustat[inst])[offset];
+ atom->ul = *ulp;
+ }
+ if (mdesc->m_desc.units.scaleTime == PM_TIME_MSEC) {
+ /* assumed to be CPU time */
+ atom->ul *= 1000 / HZ;
+ }
+#ifdef PCP_DEBUG
+ if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) {
+ /* desperate */
+ fprintf(stderr, "cpu_fetch: pmid %s inst %d val %lu\n",
+ pmIDStr(mdesc->m_desc.pmid), inst, atom->ul);
+ }
+#endif
+ }
+
+ return 1;
+}
diff --git a/src/pmdas/aix/cpu_total.c b/src/pmdas/aix/cpu_total.c
new file mode 100644
index 0000000..bf3d118
--- /dev/null
+++ b/src/pmdas/aix/cpu_total.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * 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; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * 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.
+ */
+
+#include "common.h"
+#include <sys/m_param.h>
+
+static perfstat_cpu_total_t cpustat;
+static int fetched;
+
+void
+cpu_total_init(int first)
+{
+ if (!first)
+ /* TODO ... not sure if/when we'll use this re-init hook */
+ return;
+}
+
+void
+cpu_total_prefetch(void)
+{
+ int i;
+
+ fetched = 0;
+}
+
+static __uint64_t
+cpu_total_derived(pmdaMetric *mdesc, int inst)
+{
+ pmID pmid;
+ __pmID_int *ip = (__pmID_int *)&pmid;
+ __uint64_t val;
+
+ pmid = mdesc->m_desc.pmid;
+ ip->domain = 0;
+
+ switch (pmid) {
+
+ default:
+ fprintf(stderr, "cpu_total_derived: Botch: no method for pmid %s\n",
+ pmIDStr(mdesc->m_desc.pmid));
+ val = 0;
+ break;
+ }
+
+#ifdef PCP_DEBUG
+ if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) {
+ /* desperate */
+ fprintf(stderr, "cpu_total_derived: pmid %s inst %d val %llu\n",
+ pmIDStr(mdesc->m_desc.pmid), inst, val);
+ }
+#endif
+
+ return val;
+}
+
+int
+cpu_total_fetch(pmdaMetric *mdesc, int inst, pmAtomValue *atom)
+{
+ int offset;
+
+ if (fetched == 0) {
+ int sts;
+ sts = perfstat_cpu_total(NULL, &cpustat, sizeof(perfstat_cpu_total_t), 1);
+ if (sts != 1) {
+ /* TODO - how to find/decode errors? */
+ fprintf(stderr, "perfstat_cpu_total: failed %s\n", osstrerror());
+ fetched = -1;
+ }
+ else
+ fetched = 1;
+ }
+
+ if (fetched != 1)
+ return 0;
+
+ offset = ((metricdesc_t *)mdesc->m_user)->md_offset;
+ if (offset == OFF_NOVALUES)
+ return 0;
+
+ if (mdesc->m_desc.type == PM_TYPE_U64) {
+ if (offset == OFF_DERIVED)
+ atom->ull = cpu_total_derived(mdesc, inst);
+ else {
+ __uint64_t *ullp;
+ ullp = (__uint64_t *)&((char *)&cpustat)[offset];
+ atom->ull = *ullp;
+ }
+ if (mdesc->m_desc.units.scaleTime == PM_TIME_MSEC) {
+ /* assumed to be CPU time */
+ atom->ull *= 1000 / HZ;
+ }
+#ifdef PCP_DEBUG
+ if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) {
+ /* desperate */
+ fprintf(stderr, "cpu_total_fetch: pmid %s inst %d val %llu\n",
+ pmIDStr(mdesc->m_desc.pmid), inst, atom->ull);
+ }
+#endif
+ }
+ else {
+ if (offset == OFF_DERIVED)
+ atom->ul = (__uint32_t)cpu_total_derived(mdesc, inst);
+ else {
+ __uint32_t *ulp;
+ ulp = (__uint32_t *)&((char *)&cpustat)[offset];
+ atom->ul = *ulp;
+ }
+ if (mdesc->m_desc.units.scaleTime == PM_TIME_MSEC) {
+ /* assumed to be CPU time */
+ atom->ul *= 1000 / HZ;
+ }
+#ifdef PCP_DEBUG
+ if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) {
+ /* desperate */
+ fprintf(stderr, "cpu_total_fetch: pmid %s inst %d val %lu\n",
+ pmIDStr(mdesc->m_desc.pmid), inst, atom->ul);
+ }
+#endif
+ }
+
+ return 1;
+}
diff --git a/src/pmdas/aix/data.c b/src/pmdas/aix/data.c
new file mode 100644
index 0000000..6198e78
--- /dev/null
+++ b/src/pmdas/aix/data.c
@@ -0,0 +1,435 @@
+/*
+ * Data structures that define metrics and control the AIX PMDA
+ *
+ * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * 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; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * 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.
+ */
+
+#include "common.h"
+#include <ctype.h>
+
+/*
+ * List of instance domains ... we expect the *_INDOM macros
+ * to index into this table.
+ */
+pmdaIndom indomtab[] = {
+ { DISK_INDOM, 0, NULL },
+ { CPU_INDOM, 0, NULL },
+ { NETIF_INDOM, 0, NULL }
+};
+int indomtab_sz = sizeof(indomtab) / sizeof(indomtab[0]);
+
+pmdaMetric *metrictab;
+
+method_t methodtab[] = {
+ { cpu_total_init, cpu_total_prefetch, cpu_total_fetch }, // M_CPU_TOTAL
+ { cpu_init, cpu_prefetch, cpu_fetch }, // M_CPU
+ { disk_total_init, disk_total_prefetch, disk_total_fetch }, // M_DISK_TOTAL
+ { disk_init, disk_prefetch, disk_fetch }, // M_DISK
+ { netif_init, netif_prefetch, netif_fetch } // M_NETIF
+ // M_NETBUF - TODO
+ // M_PROTO - TODO
+ // M_MEM_TOTAL - TODO
+};
+int methodtab_sz = sizeof(methodtab) / sizeof(methodtab[0]);
+
+#define CPU_OFF(field) ((int)&((perfstat_cpu_t *)0)->field)
+#define CPU_TOTAL_OFF(field) ((int)&((perfstat_cpu_total_t *)0)->field)
+#define DISK_OFF(field) ((int)&((perfstat_disk_t *)0)->field)
+#define DISK_TOTAL_OFF(field) ((int)&((perfstat_disk_total_t *)0)->field)
+#define NETIF_OFF(field) ((int)&((perfstat_netinterface_t *)0)->field)
+
+/*
+ * all metrics supported in this PMDA - one table entry for each metric
+ */
+metricdesc_t metricdesc[] = {
+
+/* kernel.all.cpu.idle */
+ { { PMDA_PMID(0,0), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(idle) },
+
+/* kernel.all.cpu.user */
+ { { PMDA_PMID(0,1), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(user) },
+
+/* kernel.all.cpu.sys */
+ { { PMDA_PMID(0,2), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(sys) },
+
+/* kernel.all.cpu.wait.total */
+ { { PMDA_PMID(0,3), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(wait) },
+
+/* kernel.percpu.cpu.idle */
+ { { PMDA_PMID(0,4), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0)
+ }, M_CPU, CPU_OFF(idle) },
+
+/* kernel.percpu.cpu.user */
+ { { PMDA_PMID(0,5), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0)
+ }, M_CPU, CPU_OFF(user) },
+
+/* kernel.percpu.cpu.sys */
+ { { PMDA_PMID(0,6), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0)
+ }, M_CPU, CPU_OFF(sys) },
+
+/* kernel.percpu.cpu.wait.total */
+ { { PMDA_PMID(0,7), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0)
+ }, M_CPU, CPU_OFF(wait) },
+
+/* kernel.all.readch */
+ { { PMDA_PMID(0,8), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(readch) },
+
+/* kernel.all.writech */
+ { { PMDA_PMID(0,9), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(readch) },
+
+/* kernel.all.io.softintrs */
+ { { PMDA_PMID(0,10), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(softintrs) },
+
+/* kernel.percpu.readch */
+ { { PMDA_PMID(0,11), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0)
+ }, M_CPU, CPU_OFF(readch) },
+
+/* kernel.percpu.writech */
+ { { PMDA_PMID(0,12), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0)
+ }, M_CPU, CPU_OFF(writech) },
+
+/* kernel.percpu.cpu.intr */
+ { { PMDA_PMID(0,13), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0)
+ }, M_CPU, OFF_NOVALUES },
+
+/* kernel.all.io.bread */
+ { { PMDA_PMID(0,14), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(bread) },
+
+/* kernel.all.io.bwrite */
+ { { PMDA_PMID(0,15), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(bwrite) },
+
+/* kernel.all.io.lread */
+ { { PMDA_PMID(0,16), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(lread) },
+
+/* kernel.all.io.lwrite */
+ { { PMDA_PMID(0,17), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(lwrite) },
+
+/* kernel.percpu.io.bread */
+ { { PMDA_PMID(0,18), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU, CPU_OFF(bread) },
+
+/* kernel.percpu.io.bwrite */
+ { { PMDA_PMID(0,19), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU, CPU_OFF(bwrite) },
+
+/* kernel.percpu.io.lread */
+ { { PMDA_PMID(0,20), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU, CPU_OFF(lread) },
+
+/* kernel.percpu.io.lwrite */
+ { { PMDA_PMID(0,21), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU, CPU_OFF(lwrite) },
+
+/* kernel.all.syscall */
+ { { PMDA_PMID(0,22), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(syscall) },
+
+/* kernel.all.pswitch */
+ { { PMDA_PMID(0,23), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(pswitch) },
+
+/* kernel.percpu.syscall */
+ { { PMDA_PMID(0,24), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU, CPU_OFF(syscall) },
+
+/* kernel.percpu.pswitch */
+ { { PMDA_PMID(0,25), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU, CPU_OFF(pswitch) },
+
+/* kernel.all.io.phread */
+ { { PMDA_PMID(0,26), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(phread) },
+
+/* kernel.all.io.phwrite */
+ { { PMDA_PMID(0,27), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(phwrite) },
+
+/* kernel.all.io.devintrs */
+ { { PMDA_PMID(0,28), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(devintrs) },
+
+/* kernel.percpu.io.phread */
+ { { PMDA_PMID(0,29), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU, CPU_OFF(phread) },
+
+/* kernel.percpu.io.phwrite */
+ { { PMDA_PMID(0,30), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU, CPU_OFF(phwrite) },
+
+/* kernel.all.cpu.intr */
+ { { PMDA_PMID(0,31), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0)
+ }, M_CPU_TOTAL, OFF_NOVALUES },
+
+/* kernel.all.trap */
+ { { PMDA_PMID(0,32), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(traps) },
+
+/* kernel.all.sysexec */
+ { { PMDA_PMID(0,33), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(sysexec) },
+
+/* kernel.all.sysfork */
+ { { PMDA_PMID(0,34), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(sysfork) },
+
+/* kernel.all.io.namei */
+ { { PMDA_PMID(0,35), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(namei) },
+
+/* kernel.all.sysread */
+ { { PMDA_PMID(0,36), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(sysread) },
+
+/* kernel.all.syswrite */
+ { { PMDA_PMID(0,37), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(syswrite) },
+
+/* hinv.ncpu_cfg */
+ { { PMDA_PMID(0,38), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(ncpus_cfg) },
+
+/* kernel.percpu.sysexec */
+ { { PMDA_PMID(0,39), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU, CPU_OFF(sysexec) },
+
+/* kernel.percpu.sysfork */
+ { { PMDA_PMID(0,40), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU, CPU_OFF(sysfork) },
+
+/* kernel.percpu.io.namei */
+ { { PMDA_PMID(0,41), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU, CPU_OFF(namei) },
+
+/* kernel.percpu.sysread */
+ { { PMDA_PMID(0,42), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU, CPU_OFF(sysread) },
+
+/* kernel.percpu.syswrite */
+ { { PMDA_PMID(0,43), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU, CPU_OFF(syswrite) },
+
+/* disk.all.read -- not available */
+ { { PMDA_PMID(0,44), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_DISK_TOTAL, OFF_NOVALUES },
+
+/* disk.all.write -- not available */
+ { { PMDA_PMID(0,45), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_DISK_TOTAL, OFF_NOVALUES },
+
+/* disk.all.total */
+ { { PMDA_PMID(0,46), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_DISK_TOTAL, DISK_TOTAL_OFF(xfers) },
+
+/* disk.all.read_bytes */
+ { { PMDA_PMID(0,47), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(1, 0, 0, PM_SPACE_MBYTE, 0, 0)
+ }, M_DISK_TOTAL, DISK_TOTAL_OFF(rblks) },
+
+/* disk.all.write_bytes */
+ { { PMDA_PMID(0,48), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(1, 0, 0, PM_SPACE_MBYTE, 0, 0)
+ }, M_DISK_TOTAL, DISK_TOTAL_OFF(wblks) },
+
+/* disk.all.total_bytes */
+ { { PMDA_PMID(0,49), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
+ PMDA_PMUNITS(1, 0, 0, PM_SPACE_MBYTE, 0, 0)
+ }, M_DISK_TOTAL, OFF_DERIVED },
+
+/* disk.dev.read -- not available */
+ { { PMDA_PMID(0,50), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_DISK, OFF_NOVALUES },
+
+/* disk.dev.write -- not available */
+ { { PMDA_PMID(0,51), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_DISK, OFF_NOVALUES },
+
+/* disk.dev.total */
+ { { PMDA_PMID(0,52), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_DISK, DISK_OFF(xfers) },
+
+/* disk.dev.read_bytes */
+ { { PMDA_PMID(0,53), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(1, 0, 0, PM_SPACE_MBYTE, 0, 0)
+ }, M_DISK, DISK_OFF(rblks) },
+
+/* disk.dev.write_bytes */
+ { { PMDA_PMID(0,54), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(1, 0, 0, PM_SPACE_MBYTE, 0, 0)
+ }, M_DISK, DISK_OFF(wblks) },
+
+/* disk.dev.total_bytes */
+ { { PMDA_PMID(0,55), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(1, 0, 0, PM_SPACE_MBYTE, 0, 0)
+ }, M_DISK, OFF_DERIVED },
+
+/* hinv.ncpu */
+ { { PMDA_PMID(0,56), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_CPU_TOTAL, CPU_TOTAL_OFF(ncpus) },
+
+/* hinv.ndisk */
+ { { PMDA_PMID(0,57), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_DISK_TOTAL, DISK_TOTAL_OFF(number) },
+
+/* hinv.nnetif */
+ { { PMDA_PMID(0,58), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_NETIF, OFF_DERIVED },
+
+/* network.interface.in.packets */
+ { { PMDA_PMID(0,59), PM_TYPE_U64, NETIF_INDOM, PM_SEM_DISCRETE,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_NETIF, NETIF_OFF(ipackets) },
+
+/* network.interface.in.bytes */
+ { { PMDA_PMID(0,60), PM_TYPE_U64, NETIF_INDOM, PM_SEM_DISCRETE,
+ PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0)
+ }, M_NETIF, NETIF_OFF(ibytes) },
+
+/* network.interface.in.errors */
+ { { PMDA_PMID(0,61), PM_TYPE_U64, NETIF_INDOM, PM_SEM_DISCRETE,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_NETIF, NETIF_OFF(ierrors) },
+
+/* network.interface.out.packets */
+ { { PMDA_PMID(0,62), PM_TYPE_U64, NETIF_INDOM, PM_SEM_DISCRETE,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_NETIF, NETIF_OFF(opackets) },
+
+/* network.interface.out.bytes */
+ { { PMDA_PMID(0,63), PM_TYPE_U64, NETIF_INDOM, PM_SEM_DISCRETE,
+ PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0)
+ }, M_NETIF, NETIF_OFF(obytes) },
+
+/* network.interface.out.errors */
+ { { PMDA_PMID(0,64), PM_TYPE_U64, NETIF_INDOM, PM_SEM_DISCRETE,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_NETIF, NETIF_OFF(oerrors) },
+
+/* network.interface.total.packets */
+ { { PMDA_PMID(0,65), PM_TYPE_U64, NETIF_INDOM, PM_SEM_DISCRETE,
+ PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE)
+ }, M_NETIF, OFF_DERIVED },
+
+/* network.interface.total.bytes */
+ { { PMDA_PMID(0,66), PM_TYPE_U64, NETIF_INDOM, PM_SEM_DISCRETE,
+ PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0)
+ }, M_NETIF, OFF_DERIVED }
+
+/* remember to add trailing comma before adding more entries ... */
+};
+int metrictab_sz = sizeof(metricdesc) / sizeof(metricdesc[0]);
+
+void
+init_data(int domain)
+{
+ int i;
+ int serial;
+ __pmID_int *ip;
+ __pmInDom_int *iip;
+
+ /*
+ * Create the PMDA's metrictab[] version of the per-metric table.
+ *
+ * Also do domain initialization for each pmid and indom element of
+ * the metricdesc[] table ... the PMDA table is fixed up in
+ * libpcp_pmda
+ */
+ if ((metrictab = (pmdaMetric *)malloc(metrictab_sz * sizeof(pmdaMetric))) == NULL) {
+ fprintf(stderr, "init_data: Error: malloc metrictab [%d] failed: %s\n",
+ metrictab_sz * sizeof(pmdaMetric), osstrerror());
+ exit(1);
+ }
+ for (i = 0; i < metrictab_sz; i++) {
+ metrictab[i].m_user = &metricdesc[i];
+ metrictab[i].m_desc = metricdesc[i].md_desc;
+ ip = (__pmID_int *)&metricdesc[i].md_desc.pmid;
+ ip->domain = domain;
+ if (metricdesc[i].md_desc.indom != PM_INDOM_NULL) {
+ serial = metricdesc[i].md_desc.indom;
+ iip = (__pmInDom_int *)&metricdesc[i].md_desc.indom;
+ iip->serial = serial;
+ iip->pad = 0;
+ iip->domain = domain;
+ }
+ }
+
+ /*
+ * initialize each of the methods
+ */
+ for (i = 0; i < methodtab_sz; i++) {
+ methodtab[i].m_init(1);
+ }
+}
diff --git a/src/pmdas/aix/disk.c b/src/pmdas/aix/disk.c
new file mode 100644
index 0000000..5ab52d6
--- /dev/null
+++ b/src/pmdas/aix/disk.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * 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; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * 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.
+ */
+
+#include "common.h"
+
+static int ndisk;
+static int ndisk_alloc;
+static int *fetched;
+static perfstat_disk_t *diskstat;
+
+void
+disk_init(int first)
+{
+ perfstat_id_t id;
+ int i;
+
+ if (!first)
+ /* TODO ... not sure if/when we'll use this re-init hook */
+ return;
+
+ ndisk = perfstat_disk(NULL, NULL, sizeof(perfstat_disk_t), 0);
+ if ((fetched = (int *)malloc(ndisk * sizeof(int))) == NULL) {
+ fprintf(stderr, "disk_init: fetched malloc[%d] failed: %s\n",
+ ndisk * sizeof(int), osstrerror());
+ exit(1);
+ }
+ if ((diskstat = (perfstat_disk_t *)malloc(ndisk * sizeof(perfstat_disk_t))) == NULL) {
+ fprintf(stderr, "disk_init: diskstat malloc[%d] failed: %s\n",
+ ndisk * sizeof(perfstat_disk_t), osstrerror());
+ exit(1);
+ }
+ ndisk_alloc = ndisk;
+
+ /*
+ * set up instance domain
+ */
+ strcpy(id.name, "");
+ ndisk = perfstat_disk(&id, diskstat, sizeof(perfstat_disk_t), ndisk_alloc);
+
+ indomtab[DISK_INDOM].it_numinst = ndisk;
+ indomtab[DISK_INDOM].it_set = (pmdaInstid *)malloc(ndisk * sizeof(pmdaInstid));
+ if (indomtab[DISK_INDOM].it_set == NULL) {
+ fprintf(stderr, "disk_init: indomtab malloc[%d] failed: %s\n",
+ ndisk * sizeof(pmdaInstid), osstrerror());
+ exit(1);
+ }
+ for (i = 0; i < ndisk; i++) {
+ indomtab[DISK_INDOM].it_set[i].i_inst = i;
+ indomtab[DISK_INDOM].it_set[i].i_name = strdup(diskstat[i].name);
+ }
+
+#ifdef PCP_DEBUG
+ if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) {
+ /* desperate */
+ fprintf(stderr, "disk_init: ndisk=%d\n", ndisk);
+ }
+#endif
+}
+
+void
+disk_prefetch(void)
+{
+ int i;
+
+ for (i = 0; i < ndisk_alloc; i++)
+ fetched[i] = 0;
+}
+
+static __uint64_t
+disk_derived(pmdaMetric *mdesc, int inst)
+{
+ pmID pmid;
+ __pmID_int *ip = (__pmID_int *)&pmid;
+ __uint64_t val;
+
+ pmid = mdesc->m_desc.pmid;
+ ip->domain = 0;
+
+ switch (pmid) {
+ case PMDA_PMID(0,55): /* disk.dev.total_bytes */
+ val = diskstat[inst].rblks + diskstat[inst].wblks;
+ break;
+
+ default:
+ fprintf(stderr, "disk_derived: Botch: no method for pmid %s\n",
+ pmIDStr(mdesc->m_desc.pmid));
+ val = 0;
+ break;
+ }
+
+#ifdef PCP_DEBUG
+ if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) {
+ /* desperate */
+ fprintf(stderr, "disk_derived: pmid %s inst %d val %llu\n",
+ pmIDStr(mdesc->m_desc.pmid), inst, val);
+ }
+#endif
+
+ return val;
+}
+
+int
+disk_fetch(pmdaMetric *mdesc, int inst, pmAtomValue *atom)
+{
+ int offset;
+
+ if (fetched[inst] == 0) {
+ int sts;
+ int i;
+ perfstat_id_t id;
+
+ strcpy(id.name, "");
+ sts = perfstat_disk(&id, diskstat, sizeof(perfstat_disk_t), ndisk_alloc);
+
+ /* TODO ...
+ * - if sts != ndisk, the number of disks has changed, need to set
+ * fetched[i] to -1 for the missing ones
+ * - is sts > ndisk possible? worse, if the number of disks is >
+ * ndisk_alloc what should we do?
+ * - possibly reshape the instance domain?
+ * - error handling?
+ */
+
+ for (i = 0; i < ndisk; i++) {
+ fetched[i] = 1;
+ }
+ }
+
+ if (fetched[inst] != 1)
+ return 0;
+
+ offset = ((metricdesc_t *)mdesc->m_user)->md_offset;
+ if (offset == OFF_NOVALUES)
+ return 0;
+
+ if (mdesc->m_desc.type == PM_TYPE_U64) {
+ if (offset == OFF_DERIVED)
+ atom->ull = disk_derived(mdesc, inst);
+ else {
+ __uint64_t *ullp;
+ ullp = (__uint64_t *)&((char *)&diskstat[inst])[offset];
+ atom->ull = *ullp;
+ }
+ if (mdesc->m_desc.units.scaleTime == PM_TIME_MSEC) {
+ /* assumed to be CPU time */
+ atom->ull *= 1000 / HZ;
+ }
+#ifdef PCP_DEBUG
+ if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) {
+ /* desperate */
+ fprintf(stderr, "disk_fetch: pmid %s inst %d val %llu\n",
+ pmIDStr(mdesc->m_desc.pmid), inst, atom->ull);
+ }
+#endif
+ }
+ else {
+ if (offset == OFF_DERIVED)
+ atom->ul = (__uint32_t)disk_derived(mdesc, inst);
+ else {
+ __uint32_t *ulp;
+ ulp = (__uint32_t *)&((char *)&diskstat[inst])[offset];
+ atom->ul = *ulp;
+ }
+ if (mdesc->m_desc.units.scaleTime == PM_TIME_MSEC) {
+ /* assumed to be CPU time */
+ atom->ul *= 1000 / HZ;
+ }
+#ifdef PCP_DEBUG
+ if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) {
+ /* desperate */
+ fprintf(stderr, "disk_fetch: pmid %s inst %d val %lu\n",
+ pmIDStr(mdesc->m_desc.pmid), inst, atom->ul);
+ }
+#endif
+ }
+
+ return 1;
+}
diff --git a/src/pmdas/aix/disk_total.c b/src/pmdas/aix/disk_total.c
new file mode 100644
index 0000000..1087d74
--- /dev/null
+++ b/src/pmdas/aix/disk_total.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * 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; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * 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.
+ */
+
+#include "common.h"
+
+static perfstat_disk_total_t diskstat;
+static int fetched;
+
+void
+disk_total_init(int first)
+{
+ if (!first)
+ /* TODO ... not sure if/when we'll use this re-init hook */
+ return;
+}
+
+void
+disk_total_prefetch(void)
+{
+ int i;
+
+ fetched = 0;
+}
+
+static __uint64_t
+disk_total_derived(pmdaMetric *mdesc, int inst)
+{
+ pmID pmid;
+ __pmID_int *ip = (__pmID_int *)&pmid;
+ __uint64_t val;
+
+ pmid = mdesc->m_desc.pmid;
+ ip->domain = 0;
+
+ switch (pmid) {
+ case PMDA_PMID(0,49): /* disk.all.total_bytes */
+ val = diskstat.rblks + diskstat.wblks;
+ break;
+
+ default:
+ fprintf(stderr, "disk_total_derived: Botch: no method for pmid %s\n",
+ pmIDStr(mdesc->m_desc.pmid));
+ val = 0;
+ break;
+ }
+
+#ifdef PCP_DEBUG
+ if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) {
+ /* desperate */
+ fprintf(stderr, "disk_total_derived: pmid %s inst %d val %llu\n",
+ pmIDStr(mdesc->m_desc.pmid), inst, val);
+ }
+#endif
+
+ return val;
+}
+
+int
+disk_total_fetch(pmdaMetric *mdesc, int inst, pmAtomValue *atom)
+{
+ int offset;
+
+ if (fetched == 0) {
+ int sts;
+ sts = perfstat_disk_total(NULL, &diskstat, sizeof(perfstat_disk_total_t), 1);
+ if (sts != 1) {
+ /* TODO - how to find/decode errors? */
+ fprintf(stderr, "perfstat_disk_total: failed %s\n", osstrerror());
+ fetched = -1;
+ }
+ else
+ fetched = 1;
+ }
+
+ if (fetched != 1)
+ return 0;
+
+ offset = ((metricdesc_t *)mdesc->m_user)->md_offset;
+ if (offset == OFF_NOVALUES)
+ return 0;
+
+ if (mdesc->m_desc.type == PM_TYPE_U64) {
+ if (offset == OFF_DERIVED)
+ atom->ull = disk_total_derived(mdesc, inst);
+ else {
+ __uint64_t *ullp;
+ ullp = (__uint64_t *)&((char *)&diskstat)[offset];
+ atom->ull = *ullp;
+ }
+#ifdef PCP_DEBUG
+ if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) {
+ /* desperate */
+ fprintf(stderr, "disk_total_fetch: pmid %s inst %d val %llu\n",
+ pmIDStr(mdesc->m_desc.pmid), inst, atom->ull);
+ }
+#endif
+ }
+ else {
+ if (offset == OFF_DERIVED)
+ atom->ul = (__uint32_t)disk_total_derived(mdesc, inst);
+ else {
+ __uint32_t *ulp;
+ ulp = (__uint32_t *)&((char *)&diskstat)[offset];
+ atom->ul = *ulp;
+ }
+#ifdef PCP_DEBUG
+ if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) {
+ /* desperate */
+ fprintf(stderr, "disk_total_fetch: pmid %s inst %d val %lu\n",
+ pmIDStr(mdesc->m_desc.pmid), inst, atom->ul);
+ }
+#endif
+ }
+
+ return 1;
+}
diff --git a/src/pmdas/aix/help b/src/pmdas/aix/help
new file mode 100644
index 0000000..afce5d8
--- /dev/null
+++ b/src/pmdas/aix/help
@@ -0,0 +1,61 @@
+#
+# Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved.
+#
+# 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; either version 2 of the License, or (at your
+# option) any later version.
+#
+# 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.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# AIX PMDA help file in the ASCII format
+#
+# lines beginning with a # are ignored
+# lines beginning @ introduce a new entry of the form
+# @ metric_name oneline-text
+# help test goes
+# here over multiple lines
+# ...
+#
+# the metric_name is decoded against the default PMNS -- as a special case,
+# a name of the form NNN.MM (for numeric NNN and MM) is interpreted as an
+# instance domain identification, and the text describes the instance domain
+#
+# blank lines before the @ line are ignored
+#
+
+@ kernel.all.cpu.idle TODO
+@ kernel.all.cpu.user TODO
+@ kernel.all.cpu.sys TODO
+@ kernel.all.cpu.wait.total TODO
+@ kernel.percpu.cpu.user TODO
+@ kernel.percpu.cpu.idle TODO
+@ kernel.percpu.cpu.sys TODO
+@ kernel.percpu.cpu.wait.total TODO
+@ disk.all.read TODO
+@ disk.all.write TODO
+@ disk.all.total TODO
+@ disk.all.read_bytes TODO
+@ disk.all.write_bytes TODO
+@ disk.all.total_bytes TODO
+@ disk.dev.read TODO
+@ disk.dev.write TODO
+@ disk.dev.total TODO
+@ disk.dev.read_bytes TODO
+@ disk.dev.write_bytes TODO
+@ disk.dev.total_bytes TODO
+@ network.interface.in.packets TODO
+@ network.interface.in.bytes TODO
+@ network.interface.in.errors TODO
+@ network.interface.out.packets TODO
+@ network.interface.out.bytes TODO
+@ network.interface.out.errors TODO
+@ network.interface.total.packets TODO
+@ network.interface.total.bytes TODO
diff --git a/src/pmdas/aix/netif.c b/src/pmdas/aix/netif.c
new file mode 100644
index 0000000..01e0ac6
--- /dev/null
+++ b/src/pmdas/aix/netif.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * 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; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * 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.
+ */
+
+#include "common.h"
+
+static int nnetif;
+static int nnetif_alloc;
+static int *fetched;
+static perfstat_netinterface_t *netifstat;
+
+void
+netif_init(int first)
+{
+ perfstat_id_t id;
+ int i;
+
+ if (!first)
+ /* TODO ... not sure if/when we'll use this re-init hook */
+ return;
+
+ nnetif = perfstat_netinterface(NULL, NULL, sizeof(perfstat_netinterface_t), 0);
+ if ((fetched = (int *)malloc(nnetif * sizeof(int))) == NULL) {
+ fprintf(stderr, "netif_init: fetched malloc[%d] failed: %s\n",
+ nnetif * sizeof(int), osstrerror());
+ exit(1);
+ }
+ if ((netifstat = (perfstat_netinterface_t *)malloc(nnetif * sizeof(perfstat_netinterface_t))) == NULL) {
+ fprintf(stderr, "netif_init: netifstat malloc[%d] failed: %s\n",
+ nnetif * sizeof(perfstat_netinterface_t), osstrerror());
+ exit(1);
+ }
+ nnetif_alloc = nnetif;
+
+ /*
+ * set up instance domain
+ */
+ strcpy(id.name, "");
+ nnetif = perfstat_netinterface(&id, netifstat, sizeof(perfstat_netinterface_t), nnetif_alloc);
+
+ indomtab[NETIF_INDOM].it_numinst = nnetif;
+ indomtab[NETIF_INDOM].it_set = (pmdaInstid *)malloc(nnetif * sizeof(pmdaInstid));
+ if (indomtab[NETIF_INDOM].it_set == NULL) {
+ fprintf(stderr, "netif_init: indomtab malloc[%d] failed: %s\n",
+ nnetif * sizeof(pmdaInstid), osstrerror());
+ exit(1);
+ }
+ for (i = 0; i < nnetif; i++) {
+ indomtab[NETIF_INDOM].it_set[i].i_inst = i;
+ indomtab[NETIF_INDOM].it_set[i].i_name = strdup(netifstat[i].name);
+ }
+
+#ifdef PCP_DEBUG
+ if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) {
+ /* desperate */
+ fprintf(stderr, "netif_init: nnetif=%d\n", nnetif);
+ }
+#endif
+}
+
+void
+netif_prefetch(void)
+{
+ int i;
+
+ for (i = 0; i < nnetif_alloc; i++)
+ fetched[i] = 0;
+}
+
+static __uint64_t
+netif_derived(pmdaMetric *mdesc, int inst)
+{
+ pmID pmid;
+ __pmID_int *ip = (__pmID_int *)&pmid;
+ __uint64_t val;
+
+ pmid = mdesc->m_desc.pmid;
+ ip->domain = 0;
+
+ switch (pmid) {
+ case PMDA_PMID(0,58): /* hinv.nnetif */
+ val = nnetif;
+ break;
+
+ case PMDA_PMID(0,65): /* network.interface.total.packets */
+ val = netifstat[inst].ipackets + netifstat[inst].opackets;
+ break;
+
+ case PMDA_PMID(0,66): /* network.interface.total.bytes */
+ val = netifstat[inst].ibytes + netifstat[inst].obytes;
+ break;
+
+ default:
+ fprintf(stderr, "netif_derived: Botch: no method for pmid %s\n",
+ pmIDStr(mdesc->m_desc.pmid));
+ val = 0;
+ break;
+ }
+
+#ifdef PCP_DEBUG
+ if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) {
+ /* desperate */
+ fprintf(stderr, "netif_derived: pmid %s inst %d val %llu\n",
+ pmIDStr(mdesc->m_desc.pmid), inst, val);
+ }
+#endif
+
+ return val;
+}
+
+int
+netif_fetch(pmdaMetric *mdesc, int inst, pmAtomValue *atom)
+{
+ int offset;
+
+ if (fetched[inst] == 0) {
+ int sts;
+ int i;
+ perfstat_id_t id;
+
+ strcpy(id.name, "");
+ sts = perfstat_netinterface(&id, netifstat, sizeof(perfstat_netinterface_t), nnetif_alloc);
+
+ /* TODO ...
+ * - if sts != nnetif, the number of network interfaces has changed,
+ * need to set fetched[i] to -1 for the missing ones
+ * - is sts > nnetif possible? worse, if the number of network
+ * interfaces is > nnetif_alloc what should we do?
+ * - possibly reshape the instance domain?
+ * - error handling?
+ */
+
+ for (i = 0; i < nnetif; i++) {
+ fetched[i] = 1;
+ }
+ }
+
+ /* hinv.nnetif is a singular metric ... so no "instance" for this one */
+ if (inst != PM_IN_NULL && fetched[inst] != 1)
+ return 0;
+
+ offset = ((metricdesc_t *)mdesc->m_user)->md_offset;
+ if (offset == OFF_NOVALUES)
+ return 0;
+
+ if (mdesc->m_desc.type == PM_TYPE_U64) {
+ if (offset == OFF_DERIVED)
+ atom->ull = netif_derived(mdesc, inst);
+ else {
+ __uint64_t *ullp;
+ ullp = (__uint64_t *)&((char *)&netifstat[inst])[offset];
+ atom->ull = *ullp;
+ }
+#ifdef PCP_DEBUG
+ if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) {
+ /* desperate */
+ fprintf(stderr, "netif_fetch: pmid %s inst %d val %llu\n",
+ pmIDStr(mdesc->m_desc.pmid), inst, atom->ull);
+ }
+#endif
+ }
+ else {
+ if (offset == OFF_DERIVED)
+ atom->ul = (__uint32_t)netif_derived(mdesc, inst);
+ else {
+ __uint32_t *ulp;
+ ulp = (__uint32_t *)&((char *)&netifstat[inst])[offset];
+ atom->ul = *ulp;
+ }
+#ifdef PCP_DEBUG
+ if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) {
+ /* desperate */
+ fprintf(stderr, "netif_fetch: pmid %s inst %d val %lu\n",
+ pmIDStr(mdesc->m_desc.pmid), inst, atom->ul);
+ }
+#endif
+ }
+
+ return 1;
+}
diff --git a/src/pmdas/aix/pmns.disk b/src/pmdas/aix/pmns.disk
new file mode 100644
index 0000000..d9ed093
--- /dev/null
+++ b/src/pmdas/aix/pmns.disk
@@ -0,0 +1,22 @@
+disk {
+ all
+ dev
+}
+
+disk.all {
+ read AIX:0:44
+ write AIX:0:45
+ total AIX:0:46
+ read_bytes AIX:0:47
+ write_bytes AIX:0:48
+ total_bytes AIX:0:49
+}
+
+disk.dev {
+ read AIX:0:50
+ write AIX:0:51
+ total AIX:0:52
+ read_bytes AIX:0:53
+ write_bytes AIX:0:54
+ total_bytes AIX:0:55
+}
diff --git a/src/pmdas/aix/pmns.hinv b/src/pmdas/aix/pmns.hinv
new file mode 100644
index 0000000..ba148e2
--- /dev/null
+++ b/src/pmdas/aix/pmns.hinv
@@ -0,0 +1,6 @@
+hinv {
+ ncpu AIX:0:56
+ ncpu_cfg AIX:0:38
+ ndisk AIX:0:57
+ nnetif AIX:0:58
+}
diff --git a/src/pmdas/aix/pmns.kernel b/src/pmdas/aix/pmns.kernel
new file mode 100644
index 0000000..fcafd54
--- /dev/null
+++ b/src/pmdas/aix/pmns.kernel
@@ -0,0 +1,77 @@
+kernel {
+ all
+ percpu
+}
+
+kernel.all {
+ cpu
+ io
+ trap AIX:0:32
+ pswitch AIX:0:23
+ syscall AIX:0:22
+ sysexec AIX:0:33
+ sysfork AIX:0:34
+ sysread AIX:0:36
+ syswrite AIX:0:37
+ readch AIX:0:8
+ writech AIX:0:9
+}
+
+kernel.all.cpu {
+ idle AIX:0:0
+ user AIX:0:1
+ sys AIX:0:2
+ intr AIX:0:31
+ wait
+}
+
+kernel.all.cpu.wait {
+ total AIX:0:3
+}
+
+kernel.all.io {
+ bread AIX:0:14
+ bwrite AIX:0:15
+ lread AIX:0:16
+ lwrite AIX:0:17
+ phread AIX:0:26
+ phwrite AIX:0:27
+ devintrs AIX:0:28
+ softintrs AIX:0:10
+ namei AIX:0:35
+}
+
+kernel.percpu {
+ cpu
+ io
+ pswitch AIX:0:25
+ syscall AIX:0:24
+ sysexec AIX:0:39
+ sysfork AIX:0:40
+ sysread AIX:0:42
+ syswrite AIX:0:43
+ readch AIX:0:11
+ writech AIX:0:12
+}
+
+kernel.percpu.cpu {
+ idle AIX:0:4
+ user AIX:0:5
+ sys AIX:0:6
+ intr AIX:0:13
+ wait
+}
+
+kernel.percpu.cpu.wait {
+ total AIX:0:7
+}
+
+kernel.percpu.io {
+ bread AIX:0:18
+ bwrite AIX:0:19
+ lread AIX:0:20
+ lwrite AIX:0:21
+ phread AIX:0:29
+ phwrite AIX:0:30
+ namei AIX:0:41
+}
diff --git a/src/pmdas/aix/pmns.mem b/src/pmdas/aix/pmns.mem
new file mode 100644
index 0000000..bfe42d2
--- /dev/null
+++ b/src/pmdas/aix/pmns.mem
@@ -0,0 +1,2 @@
+mem {
+}
diff --git a/src/pmdas/aix/pmns.network b/src/pmdas/aix/pmns.network
new file mode 100644
index 0000000..a469296
--- /dev/null
+++ b/src/pmdas/aix/pmns.network
@@ -0,0 +1,26 @@
+network {
+ interface
+}
+
+network.interface {
+ in
+ out
+ total
+}
+
+network.interface.in {
+ packets AIX:0:59
+ bytes AIX:0:60
+ errors AIX:0:61
+}
+
+network.interface.out {
+ packets AIX:0:62
+ bytes AIX:0:63
+ errors AIX:0:64
+}
+
+network.interface.total {
+ packets AIX:0:65
+ bytes AIX:0:66
+}
diff --git a/src/pmdas/aix/root b/src/pmdas/aix/root
new file mode 100644
index 0000000..ec99587
--- /dev/null
+++ b/src/pmdas/aix/root
@@ -0,0 +1,20 @@
+/*
+ * fake "root" for validating the local PMNS subtree
+ */
+
+#include <stdpmid>
+
+root {
+ kernel
+ disk
+ mem
+ network
+ hinv
+}
+
+#include "pmns.kernel"
+#include "pmns.disk"
+#include "pmns.mem"
+#include "pmns.network"
+#include "pmns.hinv"
+