bdedadf689
- fix fd leak (always close socket) - send first message (login) after renegotiation vmm_stats: - remove unneeded functionality (keeping old statistics around) - translate internal tap names to bridge names - gather statistics from vmmapi as well vmm_prometheus_stats: - new exporter of statistics to prometheus *: - fix typo in README - style
188 lines
5.1 KiB
C
188 lines
5.1 KiB
C
#include <caml/mlvalues.h>
|
|
#include <caml/alloc.h>
|
|
#include <caml/memory.h>
|
|
#include <caml/fail.h>
|
|
#include <caml/unixsupport.h>
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/types.h>
|
|
#include <sys/time.h>
|
|
#include <sys/resource.h>
|
|
#include <sys/user.h>
|
|
#include <sys/sysctl.h>
|
|
#include <net/if.h>
|
|
|
|
#define Val32 caml_copy_int32
|
|
#define Val64 caml_copy_int64
|
|
|
|
#ifdef __FreeBSD__
|
|
#include <net/if_mib.h>
|
|
#include <vmmapi.h>
|
|
|
|
CAMLprim value vmmanage_sysctl_rusage (value pid_r) {
|
|
CAMLparam1(pid_r);
|
|
CAMLlocal3(res, utime, stime);
|
|
int name[4];
|
|
int error;
|
|
size_t len;
|
|
struct kinfo_proc p;
|
|
struct rusage ru;
|
|
|
|
len = sizeof(p);
|
|
name[0] = CTL_KERN;
|
|
name[1] = KERN_PROC;
|
|
name[2] = KERN_PROC_PID;
|
|
name[3] = Int_val(pid_r);
|
|
|
|
error = sysctl(name, nitems(name), &p, &len, NULL, 0);
|
|
if (error < 0)
|
|
uerror("sysctl", Nothing);
|
|
|
|
if (ru.ru_utime.tv_usec < 0 || ru.ru_utime.tv_usec > 999999999 ||
|
|
ru.ru_stime.tv_usec < 0 || ru.ru_stime.tv_usec > 999999999)
|
|
uerror("sysctl", Nothing);
|
|
|
|
ru = p.ki_rusage;
|
|
utime = caml_alloc(2, 0);
|
|
Store_field (utime, 0, Val64(ru.ru_utime.tv_sec));
|
|
Store_field (utime, 1, Val_int(ru.ru_utime.tv_usec));
|
|
stime = caml_alloc(2, 0);
|
|
Store_field (stime, 0, Val64(ru.ru_stime.tv_sec));
|
|
Store_field (stime, 1, Val_int(ru.ru_stime.tv_usec));
|
|
res = caml_alloc(16, 0);
|
|
Store_field (res, 0, utime);
|
|
Store_field (res, 1, stime);
|
|
Store_field (res, 2, Val64(ru.ru_maxrss));
|
|
Store_field (res, 3, Val64(ru.ru_ixrss));
|
|
Store_field (res, 4, Val64(ru.ru_idrss));
|
|
Store_field (res, 5, Val64(ru.ru_isrss));
|
|
Store_field (res, 6, Val64(ru.ru_minflt));
|
|
Store_field (res, 7, Val64(ru.ru_majflt));
|
|
Store_field (res, 8, Val64(ru.ru_nswap));
|
|
Store_field (res, 9, Val64(ru.ru_inblock));
|
|
Store_field (res, 10, Val64(ru.ru_oublock));
|
|
Store_field (res, 11, Val64(ru.ru_msgsnd));
|
|
Store_field (res, 12, Val64(ru.ru_msgrcv));
|
|
Store_field (res, 13, Val64(ru.ru_nsignals));
|
|
Store_field (res, 14, Val64(ru.ru_nvcsw));
|
|
Store_field (res, 15, Val64(ru.ru_nivcsw));
|
|
|
|
CAMLreturn(res);
|
|
}
|
|
|
|
CAMLprim value vmmanage_vmmapi_stats (value name) {
|
|
CAMLparam1(name);
|
|
CAMLlocal3(res, tmp, t);
|
|
int i, num_stats;
|
|
uint64_t *stats;
|
|
const char *desc;
|
|
struct vmctx *ctx;
|
|
const char *devname;
|
|
|
|
if (! caml_string_is_c_safe(name)) caml_raise_not_found();
|
|
|
|
devname = String_val(name);
|
|
ctx = vm_open(devname);
|
|
if (ctx == NULL) uerror("vm_open", Nothing);
|
|
|
|
stats = vm_get_stats(ctx, 0, NULL, &num_stats);
|
|
if (stats != NULL) {
|
|
for (i = 0; i < num_stats; i++) {
|
|
tmp = caml_alloc(2, 0);
|
|
desc = vm_get_stat_desc(ctx, i);
|
|
Store_field (tmp, 0, caml_copy_string(desc));
|
|
Store_field (tmp, 1, Val64(stats[i]));
|
|
t = caml_alloc(2, 0);
|
|
Store_field (t, 0, tmp);
|
|
Store_field (t, 1, res);
|
|
res = t;
|
|
}
|
|
}
|
|
CAMLreturn(res);
|
|
}
|
|
|
|
|
|
CAMLprim value vmmanage_sysctl_ifcount (value unit) {
|
|
CAMLparam1(unit);
|
|
int data = 0;
|
|
size_t dlen = 0;
|
|
int name[5];
|
|
|
|
name[0] = CTL_NET;
|
|
name[1] = PF_LINK;
|
|
name[2] = NETLINK_GENERIC;
|
|
name[3] = IFMIB_SYSTEM;
|
|
name[4] = IFMIB_IFCOUNT;
|
|
dlen = sizeof(data);
|
|
|
|
if (sysctl(name, nitems(name), &data, &dlen, NULL, 0) != 0)
|
|
uerror("sysctl", Nothing);
|
|
|
|
CAMLreturn(Val_long(data));
|
|
}
|
|
|
|
CAMLprim value vmmanage_sysctl_ifdata (value num) {
|
|
CAMLparam1(num);
|
|
CAMLlocal1(res);
|
|
size_t datalen;
|
|
int name[6];
|
|
struct ifmibdata data;
|
|
|
|
name[0] = CTL_NET;
|
|
name[1] = PF_LINK;
|
|
name[2] = NETLINK_GENERIC;
|
|
name[3] = IFMIB_IFDATA;
|
|
name[4] = Int_val(num);
|
|
name[5] = IFDATA_GENERAL;
|
|
datalen = sizeof(data);
|
|
|
|
if (sysctl(name, nitems(name), &data, &datalen, NULL, 0) != 0)
|
|
uerror("sysctl", Nothing);
|
|
|
|
res = caml_alloc(18, 0);
|
|
Store_field(res, 0, caml_copy_string(data.ifmd_name));
|
|
Store_field(res, 1, Val32(data.ifmd_flags));
|
|
Store_field(res, 2, Val32(data.ifmd_snd_len));
|
|
Store_field(res, 3, Val32(data.ifmd_snd_maxlen));
|
|
Store_field(res, 4, Val32(data.ifmd_snd_drops));
|
|
Store_field(res, 5, Val32(data.ifmd_data.ifi_mtu));
|
|
Store_field(res, 6, Val64(data.ifmd_data.ifi_baudrate));
|
|
Store_field(res, 7, Val64(data.ifmd_data.ifi_ipackets));
|
|
Store_field(res, 8, Val64(data.ifmd_data.ifi_ierrors));
|
|
Store_field(res, 9, Val64(data.ifmd_data.ifi_opackets));
|
|
Store_field(res, 10, Val64(data.ifmd_data.ifi_oerrors));
|
|
Store_field(res, 11, Val64(data.ifmd_data.ifi_collisions));
|
|
Store_field(res, 12, Val64(data.ifmd_data.ifi_ibytes));
|
|
Store_field(res, 13, Val64(data.ifmd_data.ifi_obytes));
|
|
Store_field(res, 14, Val64(data.ifmd_data.ifi_imcasts));
|
|
Store_field(res, 15, Val64(data.ifmd_data.ifi_omcasts));
|
|
Store_field(res, 16, Val64(data.ifmd_data.ifi_iqdrops));
|
|
Store_field(res, 17, Val64(data.ifmd_data.ifi_oqdrops));
|
|
|
|
CAMLreturn(res);
|
|
}
|
|
#else /* FreeBSD */
|
|
|
|
/* stub symbols for OS currently not supported */
|
|
|
|
CAMLprim value vmmanage_sysctl_rusage (value pid_r) {
|
|
CAMLparam1(pid_r);
|
|
uerror("sysctl_rusage", Nothing);
|
|
}
|
|
|
|
CAMLprim value vmmanage_sysctl_ifcount (value unit) {
|
|
CAMLparam1(unit);
|
|
uerror("sysctl_ifcount", Nothing);
|
|
}
|
|
|
|
CAMLprim value vmmanage_sysctl_ifdata (value num) {
|
|
CAMLparam1(num);
|
|
uerror("sysctl_ifdata", Nothing);
|
|
}
|
|
|
|
CAMLprim value vmmanage_vmmapi_stats (value name) {
|
|
CAMLparam1(name);
|
|
uerror("vm_stat", Nothing);
|
|
}
|
|
#endif
|