examples/vm_power: add core list parameter
authorDavid Hunt <david.hunt@intel.com>
Fri, 13 Jul 2018 14:22:55 +0000 (15:22 +0100)
committerThomas Monjalon <thomas@monjalon.net>
Fri, 20 Jul 2018 20:53:17 +0000 (22:53 +0200)
Add in the '-l' command line parameter (also --core-list)
So the user can now pass --corelist=4,6,8-10 and it will
expand out to 4,6,8,9,10 using the parse function provided
in parse.c (parse_set).

This list of cores is then used to enable out-of-band monitoring
to scale up and down these cores based on the ratio of branch
hits versus branch misses. The ratio will be low when a poll
loop is spinning with no packets being received, so the frequency
will be scaled down.

Also , as part of this change, we introduce a core_info struct
which keeps information on each core in the system, and whether
we're doing out of band monitoring on them.

Signed-off-by: David Hunt <david.hunt@intel.com>
Acked-by: Radu Nicolau <radu.nicolau@intel.com>
examples/vm_power_manager/Makefile
examples/vm_power_manager/main.c
examples/vm_power_manager/parse.c [new file with mode: 0644]
examples/vm_power_manager/parse.h [new file with mode: 0644]
examples/vm_power_manager/power_manager.c
examples/vm_power_manager/power_manager.h

index ef2a9f9..0c92596 100644 (file)
@@ -19,7 +19,7 @@ APP = vm_power_mgr
 
 # all source are stored in SRCS-y
 SRCS-y := main.c vm_power_cli.c power_manager.c channel_manager.c
-SRCS-y += channel_monitor.c
+SRCS-y += channel_monitor.c parse.c
 
 CFLAGS += -O3 -I$(RTE_SDK)/lib/librte_power/
 CFLAGS += $(WERROR_FLAGS)
index 0d38469..613a40a 100644 (file)
@@ -29,6 +29,7 @@
 #include "channel_monitor.h"
 #include "power_manager.h"
 #include "vm_power_cli.h"
+#include "parse.h"
 #include <rte_pmd_ixgbe.h>
 #include <rte_pmd_i40e.h>
 #include <rte_pmd_bnxt.h>
@@ -133,18 +134,22 @@ parse_portmask(const char *portmask)
 static int
 parse_args(int argc, char **argv)
 {
-       int opt, ret;
+       int opt, ret, cnt, i;
        char **argvopt;
+       uint16_t *oob_enable;
        int option_index;
        char *prgname = argv[0];
+       struct core_info *ci;
        static struct option lgopts[] = {
                { "mac-updating", no_argument, 0, 1},
                { "no-mac-updating", no_argument, 0, 0},
+               { "core-list", optional_argument, 0, 'l'},
                {NULL, 0, 0, 0}
        };
        argvopt = argv;
+       ci = get_core_info();
 
-       while ((opt = getopt_long(argc, argvopt, "p:q:T:",
+       while ((opt = getopt_long(argc, argvopt, "l:p:q:T:",
                                  lgopts, &option_index)) != EOF) {
 
                switch (opt) {
@@ -156,6 +161,27 @@ parse_args(int argc, char **argv)
                                return -1;
                        }
                        break;
+               case 'l':
+                       oob_enable = malloc(ci->core_count * sizeof(uint16_t));
+                       if (oob_enable == NULL) {
+                               printf("Error - Unable to allocate memory\n");
+                               return -1;
+                       }
+                       cnt = parse_set(optarg, oob_enable, ci->core_count);
+                       if (cnt < 0) {
+                               printf("Invalid core-list - [%s]\n",
+                                               optarg);
+                               break;
+                       }
+                       for (i = 0; i < ci->core_count; i++) {
+                               if (oob_enable[i]) {
+                                       printf("***Using core %d\n", i);
+                                       ci->cd[i].oob_enabled = 1;
+                                       ci->cd[i].global_enabled_cpus = 1;
+                               }
+                       }
+                       free(oob_enable);
+                       break;
                /* long options */
                case 0:
                        break;
@@ -261,6 +287,10 @@ main(int argc, char **argv)
        uint16_t portid;
 
 
+       ret = core_info_init();
+       if (ret < 0)
+               rte_panic("Cannot allocate core info\n");
+
        ret = rte_eal_init(argc, argv);
        if (ret < 0)
                rte_panic("Cannot init EAL\n");
diff --git a/examples/vm_power_manager/parse.c b/examples/vm_power_manager/parse.c
new file mode 100644 (file)
index 0000000..8231533
--- /dev/null
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation.
+ * Copyright(c) 2014 6WIND S.A.
+ */
+
+#include <string.h>
+#include <rte_log.h>
+#include "parse.h"
+
+/*
+ * Parse elem, the elem could be single number/range or group
+ * 1) A single number elem, it's just a simple digit. e.g. 9
+ * 2) A single range elem, two digits with a '-' between. e.g. 2-6
+ * 3) A group elem, combines multiple 1) or 2) e.g 0,2-4,6
+ *    Within group, '-' used for a range separator;
+ *                       ',' used for a single number.
+ */
+int
+parse_set(const char *input, uint16_t set[], unsigned int num)
+{
+       unsigned int idx;
+       const char *str = input;
+       char *end = NULL;
+       unsigned int min, max;
+
+       memset(set, 0, num * sizeof(uint16_t));
+
+       while (isblank(*str))
+               str++;
+
+       /* only digit or left bracket is qualify for start point */
+       if (!isdigit(*str) || *str == '\0')
+               return -1;
+
+       while (isblank(*str))
+               str++;
+       if (*str == '\0')
+               return -1;
+
+       min = num;
+       do {
+
+               /* go ahead to the first digit */
+               while (isblank(*str))
+                       str++;
+               if (!isdigit(*str))
+                       return -1;
+
+               /* get the digit value */
+               errno = 0;
+               idx = strtoul(str, &end, 10);
+               if (errno || end == NULL || idx >= num)
+                       return -1;
+
+               /* go ahead to separator '-' and ',' */
+               while (isblank(*end))
+                       end++;
+               if (*end == '-') {
+                       if (min == num)
+                               min = idx;
+                       else /* avoid continuous '-' */
+                               return -1;
+               } else if ((*end == ',') || (*end == '\0')) {
+                       max = idx;
+
+                       if (min == num)
+                               min = idx;
+
+                       for (idx = RTE_MIN(min, max);
+                                       idx <= RTE_MAX(min, max); idx++) {
+                               set[idx] = 1;
+                       }
+                       min = num;
+               } else
+                       return -1;
+
+               str = end + 1;
+       } while (*end != '\0');
+
+       return str - input;
+}
diff --git a/examples/vm_power_manager/parse.h b/examples/vm_power_manager/parse.h
new file mode 100644 (file)
index 0000000..a5971e9
--- /dev/null
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef PARSE_H_
+#define PARSE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int
+parse_set(const char *, uint16_t [], unsigned int);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* PARSE_H_ */
index 35db255..a7849e4 100644 (file)
@@ -12,6 +12,7 @@
 #include <dirent.h>
 #include <errno.h>
 
+#include <sys/sysinfo.h>
 #include <sys/types.h>
 
 #include <rte_log.h>
@@ -54,6 +55,7 @@ struct freq_info {
 
 static struct freq_info global_core_freq_info[POWER_MGR_MAX_CPUS];
 
+struct core_info ci;
 static uint64_t global_enabled_cpus;
 
 #define SYSFS_CPU_PATH "/sys/devices/system/cpu/cpu%u/topology/core_id"
@@ -76,6 +78,35 @@ set_host_cpus_mask(void)
        return num_cpus;
 }
 
+struct core_info *
+get_core_info(void)
+{
+       return &ci;
+}
+
+int
+core_info_init(void)
+{
+       struct core_info *ci;
+       int i;
+
+       ci = get_core_info();
+
+       ci->core_count = get_nprocs_conf();
+       ci->cd = malloc(ci->core_count * sizeof(struct core_details));
+       if (!ci->cd) {
+               RTE_LOG(ERR, POWER_MANAGER, "Failed to allocate memory for core info.");
+               return -1;
+       }
+       for (i = 0; i < ci->core_count; i++) {
+               ci->cd[i].global_enabled_cpus = 1;
+               ci->cd[i].oob_enabled = 0;
+               ci->cd[i].msr_fd = 0;
+       }
+       printf("%d cores in system\n", ci->core_count);
+       return 0;
+}
+
 int
 power_manager_init(void)
 {
index 8a8a84a..45385de 100644 (file)
@@ -8,6 +8,26 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
+struct core_details {
+       uint64_t last_branches;
+       uint64_t last_branch_misses;
+       uint16_t global_enabled_cpus;
+       uint16_t oob_enabled;
+       int msr_fd;
+};
+
+struct core_info {
+       uint16_t core_count;
+       struct core_details *cd;
+};
+
+struct core_info *
+get_core_info(void);
+
+int
+core_info_init(void);
+
+#define RTE_LOGTYPE_POWER_MANAGER RTE_LOGTYPE_USER1
 
 /* Maximum number of CPUS to manage */
 #define POWER_MGR_MAX_CPUS 64