~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to tools/xenstat/libxenstat/src/xenstat.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* libxenstat: statistics-collection library for Xen
 
2
 * Copyright (C) International Business Machines Corp., 2005
 
3
 * Authors: Josh Triplett <josh@kernel.org>
 
4
 *          Judy Fischbach <jfisch@cs.pdx.edu>
 
5
 *          David Hendricks <cro_marmot@comcast.net>
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Lesser General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2.1 of the License, or (at your option) any later version.
 
11
 *
 
12
 * This library is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Lesser General Public License for more details.
 
16
 */
 
17
 
 
18
/*
 
19
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 
20
 * Use is subject to license terms.
 
21
 */
 
22
 
 
23
#include <stdlib.h>
 
24
#include <string.h>
 
25
#include <stdio.h>
 
26
#include <unistd.h>
 
27
 
 
28
#include "xenstat_priv.h"
 
29
 
 
30
/*
 
31
 * Data-collection types
 
32
 */
 
33
/* Called to collect the information for the node and all the domains on
 
34
 * it. When called, the domain information has already been collected. 
 
35
 * Return status is 0 if fatal error occurs, 1 for success. Collectors
 
36
 * may prune a domain from the list if it has been deleted between the
 
37
 * time the list was setup and the time the colector is called */
 
38
typedef int (*xenstat_collect_func)(xenstat_node * node);
 
39
/* Called to free the information collected by the collect function.  The free
 
40
 * function will only be called on a xenstat_node if that node includes
 
41
 * information collected by the corresponding collector. */
 
42
typedef void (*xenstat_free_func)(xenstat_node * node);
 
43
/* Called to free any information stored in the handle.  Note the lack of a
 
44
 * matching init function; the collect functions should initialize on first
 
45
 * use.  Also, the uninit function must handle the case that the collector has
 
46
 * never been initialized. */
 
47
typedef void (*xenstat_uninit_func)(xenstat_handle * handle);
 
48
typedef struct xenstat_collector {
 
49
        unsigned int flag;
 
50
        xenstat_collect_func collect;
 
51
        xenstat_free_func free;
 
52
        xenstat_uninit_func uninit;
 
53
} xenstat_collector;
 
54
 
 
55
static int  xenstat_collect_vcpus(xenstat_node * node);
 
56
static int  xenstat_collect_xen_version(xenstat_node * node);
 
57
static void xenstat_free_vcpus(xenstat_node * node);
 
58
static void xenstat_free_networks(xenstat_node * node);
 
59
static void xenstat_free_xen_version(xenstat_node * node);
 
60
static void xenstat_free_vbds(xenstat_node * node);
 
61
static void xenstat_uninit_vcpus(xenstat_handle * handle);
 
62
static void xenstat_uninit_xen_version(xenstat_handle * handle);
 
63
static char *xenstat_get_domain_name(xenstat_handle * handle, unsigned int domain_id);
 
64
static void xenstat_prune_domain(xenstat_node *node, unsigned int entry);
 
65
 
 
66
static xenstat_collector collectors[] = {
 
67
        { XENSTAT_VCPU, xenstat_collect_vcpus,
 
68
          xenstat_free_vcpus, xenstat_uninit_vcpus },
 
69
        { XENSTAT_NETWORK, xenstat_collect_networks,
 
70
          xenstat_free_networks, xenstat_uninit_networks },
 
71
        { XENSTAT_XEN_VERSION, xenstat_collect_xen_version,
 
72
          xenstat_free_xen_version, xenstat_uninit_xen_version },
 
73
        { XENSTAT_VBD, xenstat_collect_vbds,
 
74
          xenstat_free_vbds, xenstat_uninit_vbds }
 
75
};
 
76
 
 
77
#define NUM_COLLECTORS (sizeof(collectors)/sizeof(xenstat_collector))
 
78
 
 
79
/*
 
80
 * libxenstat API
 
81
 */
 
82
xenstat_handle *xenstat_init(void)
 
83
{
 
84
        xenstat_handle *handle;
 
85
 
 
86
        handle = (xenstat_handle *) calloc(1, sizeof(xenstat_handle));
 
87
        if (handle == NULL)
 
88
                return NULL;
 
89
 
 
90
#if defined(PAGESIZE)
 
91
        handle->page_size = PAGESIZE;
 
92
#elif defined(PAGE_SIZE)
 
93
        handle->page_size = PAGE_SIZE;
 
94
#else
 
95
        handle->page_size = sysconf(_SC_PAGE_SIZE);
 
96
        if (handle->page_size < 0) {
 
97
                perror("Failed to retrieve page size.");
 
98
                free(handle);
 
99
                return NULL;
 
100
        }
 
101
#endif
 
102
 
 
103
        handle->xc_handle = xc_interface_open();
 
104
        if (handle->xc_handle == -1) {
 
105
                perror("xc_interface_open");
 
106
                free(handle);
 
107
                return NULL;
 
108
        }
 
109
 
 
110
        handle->xshandle = xs_daemon_open_readonly(); /* open handle to xenstore*/
 
111
        if (handle->xshandle == NULL) {
 
112
                perror("unable to open xenstore");
 
113
                xc_interface_close(handle->xc_handle);
 
114
                free(handle);
 
115
                return NULL;
 
116
        }
 
117
 
 
118
        return handle;
 
119
}
 
120
 
 
121
void xenstat_uninit(xenstat_handle * handle)
 
122
{
 
123
        unsigned int i;
 
124
        if (handle) {
 
125
                for (i = 0; i < NUM_COLLECTORS; i++)
 
126
                        collectors[i].uninit(handle);
 
127
                xc_interface_close(handle->xc_handle);
 
128
                xs_daemon_close(handle->xshandle);
 
129
                free(handle->priv);
 
130
                free(handle);
 
131
        }
 
132
}
 
133
 
 
134
static inline unsigned long long parse(char *s, char *match)
 
135
{
 
136
        char *s1 = strstr(s,match);
 
137
        unsigned long long ret;
 
138
 
 
139
        if ( s1 == NULL )
 
140
                return 0LL;
 
141
        s1 += 2;
 
142
        if ( *s1++ != ':' )
 
143
                return 0LL;
 
144
        sscanf(s1,"%llu",&ret);
 
145
        return ret;
 
146
}
 
147
 
 
148
void domain_get_tmem_stats(xenstat_handle * handle, xenstat_domain * domain)
 
149
{
 
150
        char buffer[4096];
 
151
 
 
152
        if (xc_tmem_control(handle->xc_handle,-1,TMEMC_LIST,domain->id,
 
153
                        sizeof(buffer),-1,-1,buffer) < 0)
 
154
                return;
 
155
        domain->tmem_stats.curr_eph_pages = parse(buffer,"Ec");
 
156
        domain->tmem_stats.succ_eph_gets = parse(buffer,"Ge");
 
157
        domain->tmem_stats.succ_pers_puts = parse(buffer,"Pp");
 
158
        domain->tmem_stats.succ_pers_gets = parse(buffer,"Gp");
 
159
}
 
160
 
 
161
xenstat_node *xenstat_get_node(xenstat_handle * handle, unsigned int flags)
 
162
{
 
163
#define DOMAIN_CHUNK_SIZE 256
 
164
        xenstat_node *node;
 
165
        xc_physinfo_t physinfo = { 0 };
 
166
        xc_domaininfo_t domaininfo[DOMAIN_CHUNK_SIZE];
 
167
        unsigned int new_domains;
 
168
        unsigned int i;
 
169
 
 
170
        /* Create the node */
 
171
        node = (xenstat_node *) calloc(1, sizeof(xenstat_node));
 
172
        if (node == NULL)
 
173
                return NULL;
 
174
 
 
175
        /* Store the handle in the node for later access */
 
176
        node->handle = handle;
 
177
 
 
178
        /* Get information about the physical system */
 
179
        if (xc_physinfo(handle->xc_handle, &physinfo) < 0) {
 
180
                free(node);
 
181
                return NULL;
 
182
        }
 
183
 
 
184
 
 
185
        node->cpu_hz = ((unsigned long long)physinfo.cpu_khz) * 1000ULL;
 
186
        node->num_cpus = physinfo.nr_cpus;
 
187
        node->tot_mem = ((unsigned long long)physinfo.total_pages)
 
188
            * handle->page_size;
 
189
        node->free_mem = ((unsigned long long)physinfo.free_pages)
 
190
            * handle->page_size;
 
191
 
 
192
        node->freeable_mb = (long)xc_tmem_control(handle->xc_handle, -1,
 
193
                                TMEMC_QUERY_FREEABLE_MB, -1, 0, 0, 0, NULL);
 
194
 
 
195
        /* malloc(0) is not portable, so allocate a single domain.  This will
 
196
         * be resized below. */
 
197
        node->domains = malloc(sizeof(xenstat_domain));
 
198
        if (node->domains == NULL) {
 
199
                free(node);
 
200
                return NULL;
 
201
        }
 
202
 
 
203
        node->num_domains = 0;
 
204
        do {
 
205
                xenstat_domain *domain, *tmp;
 
206
 
 
207
                new_domains = xc_domain_getinfolist(handle->xc_handle,
 
208
                                                    node->num_domains, 
 
209
                                                    DOMAIN_CHUNK_SIZE, 
 
210
                                                    domaininfo);
 
211
 
 
212
                tmp = realloc(node->domains,
 
213
                              (node->num_domains + new_domains)
 
214
                              * sizeof(xenstat_domain));
 
215
                if (tmp == NULL) {
 
216
                        free(node->domains);
 
217
                        free(node);
 
218
                        return NULL;
 
219
                }
 
220
                node->domains = tmp;
 
221
 
 
222
                domain = node->domains + node->num_domains;
 
223
 
 
224
                /* zero out newly allocated memory in case error occurs below */
 
225
                memset(domain, 0, new_domains * sizeof(xenstat_domain));
 
226
 
 
227
                for (i = 0; i < new_domains; i++) {
 
228
                        /* Fill in domain using domaininfo[i] */
 
229
                        domain->id = domaininfo[i].domain;
 
230
                        domain->name = xenstat_get_domain_name(handle, 
 
231
                                                               domain->id);
 
232
                        if (domain->name == NULL) {
 
233
                                if (errno == ENOMEM) {
 
234
                                        /* fatal error */
 
235
                                        xenstat_free_node(node);
 
236
                                        return NULL;
 
237
                                }
 
238
                                else {
 
239
                                        /* failed to get name -- this means the
 
240
                                           domain is being destroyed so simply
 
241
                                           ignore this entry */
 
242
                                        continue;
 
243
                                }
 
244
                        }
 
245
                        domain->state = domaininfo[i].flags;
 
246
                        domain->cpu_ns = domaininfo[i].cpu_time;
 
247
                        domain->num_vcpus = (domaininfo[i].max_vcpu_id+1);
 
248
                        domain->vcpus = NULL;
 
249
                        domain->cur_mem =
 
250
                            ((unsigned long long)domaininfo[i].tot_pages)
 
251
                            * handle->page_size;
 
252
                        domain->max_mem =
 
253
                            domaininfo[i].max_pages == UINT_MAX
 
254
                            ? (unsigned long long)-1
 
255
                            : (unsigned long long)(domaininfo[i].max_pages
 
256
                                                   * handle->page_size);
 
257
                        domain->ssid = domaininfo[i].ssidref;
 
258
                        domain->num_networks = 0;
 
259
                        domain->networks = NULL;
 
260
                        domain->num_vbds = 0;
 
261
                        domain->vbds = NULL;
 
262
                        domain_get_tmem_stats(handle,domain);
 
263
 
 
264
                        domain++;
 
265
                        node->num_domains++;
 
266
                }
 
267
        } while (new_domains == DOMAIN_CHUNK_SIZE);
 
268
 
 
269
 
 
270
        /* Run all the extra data collectors requested */
 
271
        node->flags = 0;
 
272
        for (i = 0; i < NUM_COLLECTORS; i++) {
 
273
                if ((flags & collectors[i].flag) == collectors[i].flag) {
 
274
                        node->flags |= collectors[i].flag;
 
275
                        if(collectors[i].collect(node) == 0) {
 
276
                                xenstat_free_node(node);
 
277
                                return NULL;
 
278
                        }
 
279
                }
 
280
        }
 
281
 
 
282
        return node;
 
283
}
 
284
 
 
285
void xenstat_free_node(xenstat_node * node)
 
286
{
 
287
        int i;
 
288
 
 
289
        if (node) {
 
290
                if (node->domains) {
 
291
                        for (i = 0; i < node->num_domains; i++)
 
292
                                free(node->domains[i].name);
 
293
 
 
294
                        for (i = 0; i < NUM_COLLECTORS; i++)
 
295
                                if((node->flags & collectors[i].flag)
 
296
                                   == collectors[i].flag)
 
297
                                        collectors[i].free(node);
 
298
                        free(node->domains);
 
299
                }
 
300
                free(node);
 
301
        }
 
302
}
 
303
 
 
304
xenstat_domain *xenstat_node_domain(xenstat_node * node, unsigned int domid)
 
305
{
 
306
        unsigned int i;
 
307
 
 
308
        /* FIXME: binary search */
 
309
        /* Find the appropriate domain entry in the node struct. */
 
310
        for (i = 0; i < node->num_domains; i++) {
 
311
                if (node->domains[i].id == domid)
 
312
                        return &(node->domains[i]);
 
313
        }
 
314
        return NULL;
 
315
}
 
316
 
 
317
xenstat_domain *xenstat_node_domain_by_index(xenstat_node * node,
 
318
                                             unsigned int index)
 
319
{
 
320
        if (0 <= index && index < node->num_domains)
 
321
                return &(node->domains[index]);
 
322
        return NULL;
 
323
}
 
324
 
 
325
const char *xenstat_node_xen_version(xenstat_node * node)
 
326
{
 
327
        return node->handle->xen_version;
 
328
}
 
329
 
 
330
unsigned long long xenstat_node_tot_mem(xenstat_node * node)
 
331
{
 
332
        return node->tot_mem;
 
333
}
 
334
 
 
335
unsigned long long xenstat_node_free_mem(xenstat_node * node)
 
336
{
 
337
        return node->free_mem;
 
338
}
 
339
 
 
340
long xenstat_node_freeable_mb(xenstat_node * node)
 
341
{
 
342
        return node->freeable_mb;
 
343
}
 
344
 
 
345
unsigned int xenstat_node_num_domains(xenstat_node * node)
 
346
{
 
347
        return node->num_domains;
 
348
}
 
349
 
 
350
unsigned int xenstat_node_num_cpus(xenstat_node * node)
 
351
{
 
352
        return node->num_cpus;
 
353
}
 
354
 
 
355
/* Get information about the CPU speed */
 
356
unsigned long long xenstat_node_cpu_hz(xenstat_node * node)
 
357
{
 
358
        return node->cpu_hz;
 
359
}
 
360
 
 
361
/* Get the domain ID for this domain */
 
362
unsigned xenstat_domain_id(xenstat_domain * domain)
 
363
{
 
364
        return domain->id;
 
365
}
 
366
 
 
367
/* Get the domain name for the domain */
 
368
char *xenstat_domain_name(xenstat_domain * domain)
 
369
{
 
370
        return domain->name;
 
371
}
 
372
 
 
373
/* Get information about how much CPU time has been used */
 
374
unsigned long long xenstat_domain_cpu_ns(xenstat_domain * domain)
 
375
{
 
376
        return domain->cpu_ns;
 
377
}
 
378
 
 
379
/* Find the number of VCPUs for a domain */
 
380
unsigned int xenstat_domain_num_vcpus(xenstat_domain * domain)
 
381
{
 
382
        return domain->num_vcpus;
 
383
}
 
384
 
 
385
xenstat_vcpu *xenstat_domain_vcpu(xenstat_domain * domain, unsigned int vcpu)
 
386
{
 
387
        if (0 <= vcpu && vcpu < domain->num_vcpus)
 
388
                return &(domain->vcpus[vcpu]);
 
389
        return NULL;
 
390
}
 
391
 
 
392
/* Find the current memory reservation for this domain */
 
393
unsigned long long xenstat_domain_cur_mem(xenstat_domain * domain)
 
394
{
 
395
        return domain->cur_mem;
 
396
}
 
397
 
 
398
/* Find the maximum memory reservation for this domain */
 
399
unsigned long long xenstat_domain_max_mem(xenstat_domain * domain)
 
400
{
 
401
        return domain->max_mem;
 
402
}
 
403
 
 
404
/* Find the domain's SSID */
 
405
unsigned int xenstat_domain_ssid(xenstat_domain * domain)
 
406
{
 
407
        return domain->ssid;
 
408
}
 
409
 
 
410
/* Get domain states */
 
411
unsigned int xenstat_domain_dying(xenstat_domain * domain)
 
412
{
 
413
        return (domain->state & XEN_DOMINF_dying) == XEN_DOMINF_dying;
 
414
}
 
415
 
 
416
unsigned int xenstat_domain_crashed(xenstat_domain * domain)
 
417
{
 
418
        return ((domain->state & XEN_DOMINF_shutdown) == XEN_DOMINF_shutdown)
 
419
            && (((domain->state >> XEN_DOMINF_shutdownshift)
 
420
                 & XEN_DOMINF_shutdownmask) == SHUTDOWN_crash);
 
421
}
 
422
 
 
423
unsigned int xenstat_domain_shutdown(xenstat_domain * domain)
 
424
{
 
425
        return ((domain->state & XEN_DOMINF_shutdown) == XEN_DOMINF_shutdown)
 
426
            && (((domain->state >> XEN_DOMINF_shutdownshift)
 
427
                 & XEN_DOMINF_shutdownmask) != SHUTDOWN_crash);
 
428
}
 
429
 
 
430
unsigned int xenstat_domain_paused(xenstat_domain * domain)
 
431
{
 
432
        return (domain->state & XEN_DOMINF_paused) == XEN_DOMINF_paused;
 
433
}
 
434
 
 
435
unsigned int xenstat_domain_blocked(xenstat_domain * domain)
 
436
{
 
437
        return (domain->state & XEN_DOMINF_blocked) == XEN_DOMINF_blocked;
 
438
}
 
439
 
 
440
unsigned int xenstat_domain_running(xenstat_domain * domain)
 
441
{
 
442
        return (domain->state & XEN_DOMINF_running) == XEN_DOMINF_running;
 
443
}
 
444
 
 
445
/* Get the number of networks for a given domain */
 
446
unsigned int xenstat_domain_num_networks(xenstat_domain * domain)
 
447
{
 
448
        return domain->num_networks;
 
449
}
 
450
 
 
451
/* Get the network handle to obtain network stats */
 
452
xenstat_network *xenstat_domain_network(xenstat_domain * domain,
 
453
                                        unsigned int network)
 
454
{
 
455
        if (domain->networks && 0 <= network && network < domain->num_networks)
 
456
                return &(domain->networks[network]);
 
457
        return NULL;
 
458
}
 
459
 
 
460
/* Get the number of VBDs for a given domain */
 
461
unsigned int xenstat_domain_num_vbds(xenstat_domain * domain)
 
462
{
 
463
        return domain->num_vbds;
 
464
}
 
465
 
 
466
/* Get the VBD handle to obtain VBD stats */
 
467
xenstat_vbd *xenstat_domain_vbd(xenstat_domain * domain,
 
468
                                unsigned int vbd)
 
469
{
 
470
        if (domain->vbds && 0 <= vbd && vbd < domain->num_vbds)
 
471
                return &(domain->vbds[vbd]);
 
472
        return NULL;
 
473
}
 
474
 
 
475
/*
 
476
 * VCPU functions
 
477
 */
 
478
/* Collect information about VCPUs */
 
479
static int xenstat_collect_vcpus(xenstat_node * node)
 
480
{
 
481
        unsigned int i, vcpu, inc_index;
 
482
 
 
483
        /* Fill in VCPU information */
 
484
        for (i = 0; i < node->num_domains; i+=inc_index) {
 
485
                inc_index = 1; /* default is to increment to next domain */
 
486
 
 
487
                node->domains[i].vcpus = malloc(node->domains[i].num_vcpus
 
488
                                                * sizeof(xenstat_vcpu));
 
489
                if (node->domains[i].vcpus == NULL)
 
490
                        return 0;
 
491
        
 
492
                for (vcpu = 0; vcpu < node->domains[i].num_vcpus; vcpu++) {
 
493
                        /* FIXME: need to be using a more efficient mechanism*/
 
494
                        xc_vcpuinfo_t info;
 
495
 
 
496
                        if (xc_vcpu_getinfo(node->handle->xc_handle,
 
497
                                            node->domains[i].id, vcpu, &info) != 0) {
 
498
                                if (errno == ENOMEM) {
 
499
                                        /* fatal error */ 
 
500
                                        return 0;
 
501
                                }
 
502
                                else {
 
503
                                        /* domain is in transition - remove
 
504
                                           from list */
 
505
                                        xenstat_prune_domain(node, i);
 
506
 
 
507
                                        /* remember not to increment index! */
 
508
                                        inc_index = 0;
 
509
                                        break;
 
510
                                }
 
511
                        }
 
512
                        else {
 
513
                                node->domains[i].vcpus[vcpu].online = info.online;
 
514
                                node->domains[i].vcpus[vcpu].ns = info.cpu_time;
 
515
                        }
 
516
                }
 
517
        }
 
518
        return 1;
 
519
}
 
520
 
 
521
/* Free VCPU information */
 
522
static void xenstat_free_vcpus(xenstat_node * node)
 
523
{
 
524
        unsigned int i;
 
525
        for (i = 0; i < node->num_domains; i++)
 
526
                free(node->domains[i].vcpus);
 
527
}
 
528
 
 
529
/* Free VCPU information in handle - nothing to do */
 
530
static void xenstat_uninit_vcpus(xenstat_handle * handle)
 
531
{
 
532
}
 
533
 
 
534
/* Get VCPU online status */
 
535
unsigned int xenstat_vcpu_online(xenstat_vcpu * vcpu)
 
536
{
 
537
        return vcpu->online;
 
538
}
 
539
 
 
540
/* Get VCPU usage */
 
541
unsigned long long xenstat_vcpu_ns(xenstat_vcpu * vcpu)
 
542
{
 
543
        return vcpu->ns;
 
544
}
 
545
 
 
546
/*
 
547
 * Network functions
 
548
 */
 
549
 
 
550
/* Free network information */
 
551
static void xenstat_free_networks(xenstat_node * node)
 
552
{
 
553
        unsigned int i;
 
554
        for (i = 0; i < node->num_domains; i++)
 
555
                free(node->domains[i].networks);
 
556
}
 
557
 
 
558
/* Get the network ID */
 
559
unsigned int xenstat_network_id(xenstat_network * network)
 
560
{
 
561
        return network->id;
 
562
}
 
563
 
 
564
/* Get the number of receive bytes */
 
565
unsigned long long xenstat_network_rbytes(xenstat_network * network)
 
566
{
 
567
        return network->rbytes;
 
568
}
 
569
 
 
570
/* Get the number of receive packets */
 
571
unsigned long long xenstat_network_rpackets(xenstat_network * network)
 
572
{
 
573
        return network->rpackets;
 
574
}
 
575
 
 
576
/* Get the number of receive errors */
 
577
unsigned long long xenstat_network_rerrs(xenstat_network * network)
 
578
{
 
579
        return network->rerrs;
 
580
}
 
581
 
 
582
/* Get the number of receive drops */
 
583
unsigned long long xenstat_network_rdrop(xenstat_network * network)
 
584
{
 
585
        return network->rdrop;
 
586
}
 
587
 
 
588
/* Get the number of transmit bytes */
 
589
unsigned long long xenstat_network_tbytes(xenstat_network * network)
 
590
{
 
591
        return network->tbytes;
 
592
}
 
593
 
 
594
/* Get the number of transmit packets */
 
595
unsigned long long xenstat_network_tpackets(xenstat_network * network)
 
596
{
 
597
        return network->tpackets;
 
598
}
 
599
 
 
600
/* Get the number of transmit errors */
 
601
unsigned long long xenstat_network_terrs(xenstat_network * network)
 
602
{
 
603
        return network->terrs;
 
604
}
 
605
 
 
606
/* Get the number of transmit dropped packets */
 
607
unsigned long long xenstat_network_tdrop(xenstat_network * network)
 
608
{
 
609
        return network->tdrop;
 
610
}
 
611
 
 
612
/*
 
613
 * Xen version functions
 
614
 */
 
615
 
 
616
/* Collect Xen version information */
 
617
static int xenstat_collect_xen_version(xenstat_node * node)
 
618
{
 
619
        long vnum = 0;
 
620
        xen_extraversion_t version;
 
621
 
 
622
        /* Collect Xen version information if not already collected */
 
623
        if (node->handle->xen_version[0] == '\0') {
 
624
                /* Get the Xen version number and extraversion string */
 
625
                vnum = xc_version(node->handle->xc_handle,
 
626
                        XENVER_version, NULL);
 
627
 
 
628
                if (vnum < 0)
 
629
                        return 0;
 
630
 
 
631
                if (xc_version(node->handle->xc_handle, XENVER_extraversion,
 
632
                        &version) < 0)
 
633
                        return 0;
 
634
                /* Format the version information as a string and store it */
 
635
                snprintf(node->handle->xen_version, VERSION_SIZE, "%ld.%ld%s",
 
636
                         ((vnum >> 16) & 0xFFFF), vnum & 0xFFFF, version);
 
637
        }
 
638
 
 
639
        return 1;
 
640
}
 
641
 
 
642
/* Free Xen version information in node - nothing to do */
 
643
static void xenstat_free_xen_version(xenstat_node * node)
 
644
{
 
645
}
 
646
 
 
647
/* Free Xen version information in handle - nothing to do */
 
648
static void xenstat_uninit_xen_version(xenstat_handle * handle)
 
649
{
 
650
}
 
651
 
 
652
/*
 
653
 * VBD functions
 
654
 */
 
655
 
 
656
/* Free VBD information */
 
657
static void xenstat_free_vbds(xenstat_node * node)
 
658
{
 
659
        unsigned int i;
 
660
        for (i = 0; i < node->num_domains; i++)
 
661
                free(node->domains[i].vbds);
 
662
}
 
663
 
 
664
/* Get the back driver type  for Virtual Block Device */
 
665
unsigned int xenstat_vbd_type(xenstat_vbd * vbd)
 
666
{
 
667
        return vbd->back_type;
 
668
}
 
669
 
 
670
/* Get the major number of VBD device */
 
671
unsigned int xenstat_vbd_dev(xenstat_vbd * vbd)
 
672
{
 
673
        return vbd->dev;
 
674
}
 
675
 
 
676
/* Get the number of OO(Out of) requests */
 
677
unsigned long long xenstat_vbd_oo_reqs(xenstat_vbd * vbd)
 
678
{
 
679
        return vbd->oo_reqs;
 
680
}
 
681
 
 
682
/* Get the number of READ requests */
 
683
unsigned long long xenstat_vbd_rd_reqs(xenstat_vbd * vbd)
 
684
{
 
685
        return vbd->rd_reqs;
 
686
}
 
687
 
 
688
/* Get the number of WRITE requests */
 
689
unsigned long long xenstat_vbd_wr_reqs(xenstat_vbd * vbd)
 
690
{
 
691
        return vbd->wr_reqs;
 
692
}
 
693
 
 
694
/* Get the number of READ sectors */
 
695
unsigned long long xenstat_vbd_rd_sects(xenstat_vbd * vbd)
 
696
{
 
697
        return vbd->rd_sects;
 
698
}
 
699
 
 
700
/* Get the number of WRITE sectors */
 
701
unsigned long long xenstat_vbd_wr_sects(xenstat_vbd * vbd)
 
702
{
 
703
        return vbd->wr_sects;
 
704
}
 
705
 
 
706
/*
 
707
 * Tmem functions
 
708
 */
 
709
 
 
710
xenstat_tmem *xenstat_domain_tmem(xenstat_domain * domain)
 
711
{
 
712
        return &domain->tmem_stats;
 
713
}
 
714
 
 
715
/* Get the current number of ephemeral pages */
 
716
unsigned long long xenstat_tmem_curr_eph_pages(xenstat_tmem *tmem)
 
717
{
 
718
        return tmem->curr_eph_pages;
 
719
}
 
720
 
 
721
/* Get the number of successful ephemeral gets */
 
722
unsigned long long xenstat_tmem_succ_eph_gets(xenstat_tmem *tmem)
 
723
{
 
724
        return tmem->succ_eph_gets;
 
725
}
 
726
 
 
727
/* Get the number of successful persistent puts */
 
728
unsigned long long xenstat_tmem_succ_pers_puts(xenstat_tmem *tmem)
 
729
{
 
730
        return tmem->succ_pers_puts;
 
731
}
 
732
 
 
733
/* Get the number of successful persistent gets */
 
734
unsigned long long xenstat_tmem_succ_pers_gets(xenstat_tmem *tmem)
 
735
{
 
736
        return tmem->succ_pers_gets;
 
737
}
 
738
 
 
739
 
 
740
static char *xenstat_get_domain_name(xenstat_handle *handle, unsigned int domain_id)
 
741
{
 
742
        char path[80], *vmpath;
 
743
 
 
744
        snprintf(path, sizeof(path),"/local/domain/%i/vm", domain_id);
 
745
 
 
746
        vmpath = xs_read(handle->xshandle, XBT_NULL, path, NULL);
 
747
 
 
748
        if (vmpath == NULL)
 
749
                return NULL;
 
750
 
 
751
        snprintf(path, sizeof(path),"%s/name", vmpath);
 
752
        free(vmpath);
 
753
 
 
754
        return xs_read(handle->xshandle, XBT_NULL, path, NULL);
 
755
}
 
756
 
 
757
/* Remove specified entry from list of domains */
 
758
static void xenstat_prune_domain(xenstat_node *node, unsigned int entry)
 
759
{
 
760
        /* nothing to do if array is empty or entry is beyond end */
 
761
        if (node->num_domains == 0 || entry >= node->num_domains)
 
762
                return;
 
763
 
 
764
        /* decrement count of domains */
 
765
        node->num_domains--;
 
766
 
 
767
        /* shift entries following specified entry up by one */
 
768
        if (entry < node->num_domains) {
 
769
                xenstat_domain *domain = &node->domains[entry];
 
770
                memmove(domain,domain+1,(node->num_domains - entry) * sizeof(xenstat_domain) );
 
771
        }
 
772
 
 
773
        /* zero out original last entry from node -- not
 
774
           strictly necessary but safer! */
 
775
        memset(&node->domains[node->num_domains], 0, sizeof(xenstat_domain)); 
 
776
}