Exports PROCESSOR structure with sFLOW counters. Refactors vswitchd/system-stats.* functionality to support complex system counters which are enabled on request, and basic stats enabled by default. Adjust unit tests with very basic sanity check for PROCESSOR counters.
Signed-off-by: Michal Weglicki <michalx.wegli...@intel.com> --- lib/sflow.h | 12 ++ lib/sflow_receiver.c | 8 ++ ofproto/ofproto-dpif-sflow.c | 17 ++- tests/ofproto-dpif.at | 28 +++- tests/test-sflow.c | 15 +++ vswitchd/bridge.c | 1 + vswitchd/system-stats.c | 308 ++++++++++++++++++++++++++++++++++++------- vswitchd/system-stats.h | 16 +++ 8 files changed, 352 insertions(+), 53 deletions(-) diff --git a/lib/sflow.h b/lib/sflow.h index 95bedd9..53ba4e0 100644 --- a/lib/sflow.h +++ b/lib/sflow.h @@ -502,6 +502,16 @@ typedef struct _SFLVlan_counters { u_int32_t discards; } SFLVlan_counters; +#define SFL_CTR_PROCESSOR_XDR_SIZE 28 + +typedef struct _SFLProcessor_counters { + int32_t cpu_util_5s; /* 5 second average CPU utilization */ + int32_t cpu_util_1m; /* 1 minute average CPU utilization */ + int32_t cpu_util_5m; /* 5 minute average CPU utilization */ + u_int64_t total_memory; /* total memory (in bytes) */ + u_int64_t free_memory; /* free memory (in bytes) */ +} SFLProcessor_counters; + /* OpenFlow port */ typedef struct { u_int64_t datapath_id; @@ -587,6 +597,7 @@ enum SFLCounters_type_tag { SFLCOUNTERS_VG = 4, SFLCOUNTERS_VLAN = 5, SFLCOUNTERS_LACP = 7, + SFLCOUNTERS_PROCESSOR = 1001, SFLCOUNTERS_OPENFLOWPORT = 1004, SFLCOUNTERS_PORTNAME = 1005, SFLCOUNTERS_APP_RESOURCES = 2203, @@ -604,6 +615,7 @@ typedef union _SFLCounters_type { SFLPortName portName; SFLAPPResources_counters appResources; SFLOVSDP_counters ovsdp; + SFLProcessor_counters processor; } SFLCounters_type; typedef struct _SFLCounters_sample_element { diff --git a/lib/sflow_receiver.c b/lib/sflow_receiver.c index cde1359..23468f1 100644 --- a/lib/sflow_receiver.c +++ b/lib/sflow_receiver.c @@ -655,6 +655,7 @@ static int computeCountersSampleSize(SFLReceiver *receiver, SFL_COUNTERS_SAMPLE_ case SFLCOUNTERS_PORTNAME: elemSiz = stringEncodingLength(&elem->counterBlock.portName.portName); break; case SFLCOUNTERS_APP_RESOURCES: elemSiz = SFL_CTR_APP_RESOURCES_XDR_SIZE; break; case SFLCOUNTERS_OVSDP: elemSiz = SFL_CTR_OVSDP_XDR_SIZE; break; + case SFLCOUNTERS_PROCESSOR: elemSiz = SFL_CTR_PROCESSOR_XDR_SIZE; break; default: sflError(receiver, "unexpected counters_tag"); return -1; @@ -795,6 +796,13 @@ int sfl_receiver_writeCountersSample(SFLReceiver *receiver, SFL_COUNTERS_SAMPLE_ putNet32(receiver, elem->counterBlock.ovsdp.n_flows); putNet32(receiver, elem->counterBlock.ovsdp.n_masks); break; + case SFLCOUNTERS_PROCESSOR: + putNet32(receiver, elem->counterBlock.processor.cpu_util_5s); + putNet32(receiver, elem->counterBlock.processor.cpu_util_1m); + putNet32(receiver, elem->counterBlock.processor.cpu_util_5m); + putNet64(receiver, elem->counterBlock.processor.total_memory); + putNet64(receiver, elem->counterBlock.processor.free_memory); + break; default: sflError(receiver, "unexpected counters_tag"); return -1; diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c index 37992b4..84bbe18 100644 --- a/ofproto/ofproto-dpif-sflow.c +++ b/ofproto/ofproto-dpif-sflow.c @@ -43,6 +43,7 @@ #include "lib/unaligned.h" #include "ofproto-provider.h" #include "lacp.h" +#include "vswitchd/system-stats.h" VLOG_DEFINE_THIS_MODULE(sflow); @@ -297,7 +298,7 @@ sflow_agent_get_counters(void *ds_, SFLPoller *poller, OVS_REQUIRES(mutex) { struct dpif_sflow *ds = ds_; - SFLCounters_sample_element elem, lacp_elem, of_elem, name_elem; + SFLCounters_sample_element elem, lacp_elem, of_elem, name_elem, proc_elem; enum netdev_features current; struct dpif_sflow_port *dsp; SFLIf_counters *counters; @@ -305,6 +306,7 @@ sflow_agent_get_counters(void *ds_, SFLPoller *poller, enum netdev_flags flags; struct lacp_slave_stats lacp_stats; const char *ifName; + struct system_stats_basic *stats_basic; dsp = dpif_sflow_find_port(ds, u32_to_odp(poller->bridgePort)); if (!dsp) { @@ -407,6 +409,19 @@ sflow_agent_get_counters(void *ds_, SFLPoller *poller, (OVS_FORCE uint32_t)dsp->ofport->ofp_port; SFLADD_ELEMENT(cs, &of_elem); + memset(&proc_elem, 0, sizeof proc_elem); + proc_elem.tag = SFLCOUNTERS_PROCESSOR; + stats_basic = system_stats_run_basic(); + if (stats_basic) { + proc_elem.counterBlock.processor.cpu_util_5s = stats_basic->cpu_util_5s; + proc_elem.counterBlock.processor.cpu_util_1m = stats_basic->cpu_util_1m; + proc_elem.counterBlock.processor.cpu_util_5m = stats_basic->cpu_util_5m; + proc_elem.counterBlock.processor.total_memory = stats_basic->total_memory; + proc_elem.counterBlock.processor.free_memory = stats_basic->free_memory; + SFLADD_ELEMENT(cs, &proc_elem); + free(stats_basic); + } + sfl_poller_writeCountersSample(poller, cs); } diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at index ec7bd60..c8ee532 100644 --- a/tests/ofproto-dpif.at +++ b/tests/ofproto-dpif.at @@ -5430,8 +5430,8 @@ HEADER hdr=50-54-00-00-00-05-50-54-00-00-00-07-86-DD-67-00-00-00-00-00-0A-80-FE-80-00-00-00-00-00-00-00-00-00-00-00-00-00-01-FE-80-00-00-00-00-00-00-00-00-00-00-00-00-00-02 ]) - AT_CHECK_UNQUOTED([[sort sflow.log | $EGREP 'IFCOUNTERS|ERROR|PORTNAME|OPENFLOWPORT' | head -18 | sed 's/ /\ - /g']], [0], [dnl + AT_CHECK_UNQUOTED([[sort sflow.log | $EGREP 'PROCESSORCOUNTERS|IFCOUNTERS|ERROR|PORTNAME|OPENFLOWPORT' | head -24 | sed 's/ /\ + /g' | sed '/total_memory/d' | sed '/free_memory/d']], [0], [dnl IFCOUNTERS dgramSeqNo=1 ds=127.0.0.1>0:1002 @@ -5600,6 +5600,30 @@ PORTNAME portName=p2 PORTNAME portName=p2 +PROCESSORCOUNTERS + 5s_cpu=4294967295 + 1m_cpu=4294967295 + 5m_cpu=4294967295 +PROCESSORCOUNTERS + 5s_cpu=4294967295 + 1m_cpu=4294967295 + 5m_cpu=4294967295 +PROCESSORCOUNTERS + 5s_cpu=4294967295 + 1m_cpu=4294967295 + 5m_cpu=4294967295 +PROCESSORCOUNTERS + 5s_cpu=4294967295 + 1m_cpu=4294967295 + 5m_cpu=4294967295 +PROCESSORCOUNTERS + 5s_cpu=4294967295 + 1m_cpu=4294967295 + 5m_cpu=4294967295 +PROCESSORCOUNTERS + 5s_cpu=4294967295 + 1m_cpu=4294967295 + 5m_cpu=4294967295 ])]) AT_SETUP([ofproto-dpif - basic truncate action]) diff --git a/tests/test-sflow.c b/tests/test-sflow.c index 60870df..8d41531 100644 --- a/tests/test-sflow.c +++ b/tests/test-sflow.c @@ -55,6 +55,7 @@ static unixctl_cb_func test_sflow_exit; /* Structure element tag numbers. */ #define SFLOW_TAG_CTR_IFCOUNTERS 1 #define SFLOW_TAG_CTR_LACPCOUNTERS 7 +#define SFLOW_TAG_CTR_PROCESSORCOUNTERS 1001 #define SFLOW_TAG_CTR_OPENFLOWPORT 1004 #define SFLOW_TAG_CTR_PORTNAME 1005 #define SFLOW_TAG_PKT_HEADER 1 @@ -116,6 +117,7 @@ struct sflow_xdr { uint32_t TUNNEL_VNI_IN; uint32_t MPLS; uint32_t IFCOUNTERS; + uint32_t PROCESSORCOUNTERS; uint32_t LACPCOUNTERS; uint32_t OPENFLOWPORT; uint32_t PORTNAME; @@ -297,6 +299,16 @@ process_counter_sample(struct sflow_xdr *x) printf(" portName=%s", portName); printf("\n"); } + if (x->offset.PROCESSORCOUNTERS) { + sflowxdr_setc(x, x->offset.PROCESSORCOUNTERS); + printf("PROCESSORCOUNTERS"); + printf(" 5s_cpu=%"PRIu32, sflowxdr_next(x)); + printf(" 1m_cpu=%"PRIu32, sflowxdr_next(x)); + printf(" 5m_cpu=%"PRIu32, sflowxdr_next(x)); + printf(" total_memory=%"PRIu64, sflowxdr_next_int64(x)); + printf(" free_memory=%"PRIu64, sflowxdr_next_int64(x)); + printf("\n"); + } } static char @@ -513,6 +525,9 @@ process_datagram(struct sflow_xdr *x) case SFLOW_TAG_CTR_IFCOUNTERS: sflowxdr_mark_unique(x, &x->offset.IFCOUNTERS); break; + case SFLOW_TAG_CTR_PROCESSORCOUNTERS: + sflowxdr_mark_unique(x, &x->offset.PROCESSORCOUNTERS); + break; case SFLOW_TAG_CTR_LACPCOUNTERS: sflowxdr_mark_unique(x, &x->offset.LACPCOUNTERS); break; diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index d78c48e..50934e6 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -645,6 +645,7 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) shash_destroy(&br->wanted_ports); } + system_stats_init(); reconfigure_system_stats(ovs_cfg); /* Complete the configuration. */ diff --git a/vswitchd/system-stats.c b/vswitchd/system-stats.c index 49e5419..e779b0c 100644 --- a/vswitchd/system-stats.c +++ b/vswitchd/system-stats.c @@ -23,7 +23,6 @@ #if HAVE_MNTENT_H #include <mntent.h> #endif -#include <stdint.h> #include <stdio.h> #include <stdlib.h> #if HAVE_SYS_STATVFS_H @@ -58,6 +57,116 @@ VLOG_DEFINE_THIS_MODULE(system_stats); #define LINUX 0 #endif +struct system_stats_cpu_snapshot { + long double proc_stats[4]; + int64_t time_stamp_ms; + uint64_t period_ms; +}; + +#define SYSTEM_STATS_INTERVAL (5 * 1000) /* In milliseconds. */ +#define CPU_SNAPSHOTS 3 +#define CPU_COUNTERS 4 +#define SYSTEM_STATS_CPU_5S_ID 0 +#define SYSTEM_STATS_CPU_1M_ID 1 +#define SYSTEM_STATS_CPU_5M_ID 2 + +static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER; +static struct ovs_mutex mutex_basic = OVS_MUTEX_INITIALIZER; +static struct latch latch OVS_GUARDED_BY(mutex); +static bool enabled_complex; +bool stats_init = false; +static bool started OVS_GUARDED_BY(mutex); +static struct smap *system_stats OVS_GUARDED_BY(mutex); +struct system_stats_basic stats_basic OVS_GUARDED_BY(mutex_basic); +static struct system_stats_cpu_snapshot cpu_snapshots[CPU_SNAPSHOTS]; + +OVS_NO_RETURN static void *system_stats_thread_func(void *); +static void discard_stats(void); + +/* Function gets current statistics snapshot from memory. It assumes + * that four element array will be passed as argument. */ +static void +get_cpu_snapshot_from_system(long double *cpu_array, uint8_t array_size, + int64_t *time_stamp) +{ + if (LINUX) { + FILE *fp; + struct timeval now; + + xgettimeofday(&now); + + *time_stamp = timeval_to_msec(&now); + + /* Sanity array check */ + if (array_size != CPU_COUNTERS) { + for (uint8_t i = 0 ; i < array_size; i++) { + cpu_array[i] = -1; + } + }else{ + fp = fopen("/proc/stat","r"); + fscanf(fp,"%*s %Lf %Lf %Lf %Lf",&cpu_array[0],&cpu_array[1], + &cpu_array[2],&cpu_array[3]); + fclose(fp); + } + } +} +/* Function initializes statistics snapshot with default values */ +static void +cpu_snapshots_init(void) +{ + + long double cpu_values[CPU_COUNTERS] = {0, 0, 0, 0}; + int64_t time_stamp_ms = 0; + + get_cpu_snapshot_from_system(cpu_values, CPU_COUNTERS, + &time_stamp_ms); + + /* 5 seconds snapshot */ + cpu_snapshots[0].period_ms = 5000; + /* 1 minute snapshot */ + cpu_snapshots[1].period_ms = 60000; + /* 5 minutes snapshot */ + cpu_snapshots[2].period_ms = 5 * 60000; + + for (uint8_t snap_id = 0 ; snap_id < CPU_SNAPSHOTS ; snap_id++) { + for (uint8_t c_id = 0 ; c_id < CPU_COUNTERS ; c_id++) { + cpu_snapshots[snap_id].proc_stats[c_id] = cpu_values[c_id]; + } + cpu_snapshots[snap_id].time_stamp_ms = time_stamp_ms; + } +} + +/* Simple initialize function */ +static void +system_stats_basic_init(struct system_stats_basic* stats) +{ + stats->cpu_util_5s = -1; + stats->cpu_util_1m = -1; + stats->cpu_util_5m = -1; + + stats->free_memory = 0; + stats->total_memory = 0; +} + +/* Conditional copy function */ +static void +system_stats_basic_copy(struct system_stats_basic* stats_in, + struct system_stats_basic* stats_out) +{ + if (stats_in->cpu_util_5s != -1) { + stats_out->cpu_util_5s = stats_in->cpu_util_5s; + } + if (stats_in->cpu_util_1m != -1) { + stats_out->cpu_util_1m = stats_in->cpu_util_1m; + } + if (stats_in->cpu_util_5m != -1) { + stats_out->cpu_util_5m = stats_in->cpu_util_5m; + } + stats_out->total_memory = stats_in->total_memory; + stats_out->free_memory = stats_in->free_memory; +} + + static void get_cpu_cores(struct smap *stats) { @@ -67,6 +176,54 @@ get_cpu_cores(struct smap *stats) } } +/* Function gets current basic system statistics if available */ +static void +update_cpu_utilization(struct system_stats_basic *stats) +{ + if (LINUX) { + long double cpu_val[CPU_COUNTERS] = {0, 0, 0, 0}; + long double util_value; + long double work_current, total_current, work_previous, + total_previous; + int64_t time_stamp_ms = 0; + + get_cpu_snapshot_from_system(cpu_val, CPU_COUNTERS, + &time_stamp_ms); + + for (uint8_t snap_id = 0 ; snap_id < CPU_SNAPSHOTS; snap_id++) { + uint64_t period = time_stamp_ms - + cpu_snapshots[snap_id].time_stamp_ms; + if (period >= cpu_snapshots[snap_id].period_ms) { + /* Data from requested period is gathered. */ + work_current = cpu_val[0] + cpu_val[1] + + cpu_val[2]; + total_current = cpu_val[0] + cpu_val[1] + + cpu_val[2] + cpu_val[3]; + work_previous = cpu_snapshots[snap_id].proc_stats[0] + + cpu_snapshots[snap_id].proc_stats[1] + + cpu_snapshots[snap_id].proc_stats[2]; + total_previous = cpu_snapshots[snap_id].proc_stats[0] + + cpu_snapshots[snap_id].proc_stats[1] + + cpu_snapshots[snap_id].proc_stats[2] + + cpu_snapshots[snap_id].proc_stats[3]; + util_value = ((work_current - work_previous) / + (total_current - total_previous)) * 10000; + if (SYSTEM_STATS_CPU_5S_ID == snap_id) { + stats->cpu_util_5s = util_value; + } else if (SYSTEM_STATS_CPU_1M_ID == snap_id){ + stats->cpu_util_1m = util_value; + } else { + stats->cpu_util_5m = util_value; + } + cpu_snapshots[snap_id].time_stamp_ms = time_stamp_ms; + for (uint8_t c_id = 0 ; c_id < CPU_COUNTERS ; c_id++) { + cpu_snapshots[snap_id].proc_stats[c_id] = cpu_val[c_id]; + } + } + } + } +} + static void get_load_average(struct smap *stats OVS_UNUSED) { @@ -103,7 +260,8 @@ get_page_size(void) } static void -get_memory_stats(struct smap *stats) +get_memory_stats(struct smap *stats, + struct system_stats_basic * stats_basic_out) { if (!LINUX) { unsigned int pagesize = get_page_size(); @@ -133,7 +291,11 @@ get_memory_stats(struct smap *stats) mem_total = memory_status.dwTotalPhys; mem_used = memory_status.dwTotalPhys - memory_status.dwAvailPhys; #endif - smap_add_format(stats, "memory", "%d,%d", mem_total, mem_used); + if (NULL != stats) { + smap_add_format(stats, "memory", "%d,%d", mem_total, mem_used); + } + stats_basic_out->total_memory = mem_total; + stats_basic_out->free_memory = mem_total - mem_used; } else { static const char file_name[] = "/proc/meminfo"; int mem_used, mem_cache, swap_used; @@ -178,8 +340,13 @@ get_memory_stats(struct smap *stats) mem_used = mem_total - mem_free; mem_cache = buffers + cached; swap_used = swap_total - swap_free; - smap_add_format(stats, "memory", "%d,%d,%d,%d,%d", - mem_total, mem_used, mem_cache, swap_total, swap_used); + if (NULL != stats) { + smap_add_format(stats, "memory", "%d,%d,%d,%d,%d", + mem_total, mem_used, mem_cache, + swap_total, swap_used); + } + stats_basic_out->total_memory = mem_total; + stats_basic_out->free_memory = mem_free; } } @@ -522,36 +689,45 @@ get_filesys_stats(struct smap *stats OVS_UNUSED) ds_destroy(&s); #endif /* HAVE_GETMNTENT_R && HAVE_STATVFS */ } - -#define SYSTEM_STATS_INTERVAL (5 * 1000) /* In milliseconds. */ -static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER; -static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; -static struct latch latch OVS_GUARDED_BY(mutex); -static bool enabled; -static bool started OVS_GUARDED_BY(mutex); -static struct smap *system_stats OVS_GUARDED_BY(mutex); +/* Initializes system statistics with basic functionality. */ +void +system_stats_init(void) +{ -OVS_NO_RETURN static void *system_stats_thread_func(void *); -static void discard_stats(void); + /* Make sure that stats are initialized just once. */ + if (!stats_init) { + stats_init = true; + cpu_snapshots_init(); -/* Enables or disables system stats collection, according to 'enable'. */ + ovs_mutex_lock(&mutex_basic); + system_stats_basic_init(&stats_basic); + ovs_mutex_unlock(&mutex_basic); + + ovs_mutex_lock(&mutex); + if (!started) { + ovs_thread_create("system_stats", + system_stats_thread_func, NULL); + latch_init(&latch); + started = true; + } + discard_stats(); + enabled_complex = false; + ovs_mutex_unlock(&mutex); + } +} + +/* Enables or disables system complex stats collection, + * according to 'enable'. */ void system_stats_enable(bool enable) { - if (enabled != enable) { + if (enabled_complex != enable) { ovs_mutex_lock(&mutex); if (enable) { - if (!started) { - ovs_thread_create("system_stats", - system_stats_thread_func, NULL); - latch_init(&latch); - started = true; - } discard_stats(); - xpthread_cond_signal(&cond); } - enabled = enable; + enabled_complex = enable; ovs_mutex_unlock(&mutex); } } @@ -573,7 +749,7 @@ system_stats_run(void) if (system_stats) { latch_poll(&latch); - if (enabled) { + if (enabled_complex) { stats = system_stats; system_stats = NULL; } else { @@ -585,12 +761,32 @@ system_stats_run(void) return stats; } +/* Gets new snapshot of system basic stats. + * + * Function returns current state of basic statistics. Returned data is + * owned by the caller. The caller must use free() to completely + * free the returned data. + * + * If basic statistics are disabled, NULL is returned. */ +struct system_stats_basic* +system_stats_run_basic(void) +{ + struct system_stats_basic *stats_basic_ret = NULL; + + stats_basic_ret = xmalloc(sizeof *stats_basic_ret); + ovs_mutex_lock(&mutex_basic); + *stats_basic_ret = stats_basic; + ovs_mutex_unlock(&mutex_basic); + + return stats_basic_ret; +} + /* Causes poll_block() to wake up when system_stats_run() needs to be * called. */ void system_stats_wait(void) { - if (enabled) { + if (enabled_complex) { latch_wait(&latch); } } @@ -612,32 +808,44 @@ system_stats_thread_func(void *arg OVS_UNUSED) for (;;) { long long int next_refresh; - struct smap *stats; - - ovs_mutex_lock(&mutex); - while (!enabled) { - /* The thread is sleeping, potentially for a long time, and it's - * not holding RCU protected references, so it makes sense to - * quiesce */ - ovsrcu_quiesce_start(); - ovs_mutex_cond_wait(&cond, &mutex); - ovsrcu_quiesce_end(); + bool do_complex = false; + struct smap *stats = NULL; + struct system_stats_basic stats_current; + + system_stats_basic_init(&stats_current); + + /* Check status flags at the beginning to prevent some + * synchronization problems during execution. + * + * Basic statistics are enabled by default */ + if (enabled_complex) { + do_complex = true; + stats = xmalloc(sizeof *stats); + smap_init(stats); } - ovs_mutex_unlock(&mutex); - stats = xmalloc(sizeof *stats); - smap_init(stats); - get_cpu_cores(stats); - get_load_average(stats); - get_memory_stats(stats); - get_process_stats(stats); - get_filesys_stats(stats); + /* Get memory stats always */ + get_memory_stats(stats, &stats_current); - ovs_mutex_lock(&mutex); - discard_stats(); - system_stats = stats; - latch_set(&latch); - ovs_mutex_unlock(&mutex); + /* Get basic statistics */ + update_cpu_utilization(&stats_current); + + ovs_mutex_lock(&mutex_basic); + system_stats_basic_copy(&stats_current, &stats_basic); + ovs_mutex_unlock(&mutex_basic); + + if (do_complex) { + get_cpu_cores(stats); + get_load_average(stats); + get_process_stats(stats); + get_filesys_stats(stats); + + ovs_mutex_lock(&mutex); + discard_stats(); + system_stats = stats; + latch_set(&latch); + ovs_mutex_unlock(&mutex); + } next_refresh = time_msec() + SYSTEM_STATS_INTERVAL; do { diff --git a/vswitchd/system-stats.h b/vswitchd/system-stats.h index 83b4bcb..e0b3078 100644 --- a/vswitchd/system-stats.h +++ b/vswitchd/system-stats.h @@ -17,9 +17,25 @@ #define VSWITCHD_SYSTEM_STATS 1 #include <stdbool.h> +#include <stdint.h> +struct system_stats_basic { + + /* Percentage expressed in hundredths of a percent + (e.g. 100 = 1%). If a percentage value is unknown then + -1 value is used. */ + int32_t cpu_util_5s; + int32_t cpu_util_1m; + int32_t cpu_util_5m; + + uint64_t total_memory; + uint64_t free_memory; +}; + +void system_stats_init(void); void system_stats_enable(bool enable); struct smap *system_stats_run(void); +struct system_stats_basic* system_stats_run_basic(void); void system_stats_wait(void); #endif /* vswitchd/system-stats.h */ -- 1.8.3.1 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev