APP = guest_vm_power_mgr
# all source are stored in SRCS-y
-SRCS-y := main.c vm_power_cli_guest.c
+SRCS-y := main.c vm_power_cli_guest.c parse.c
CFLAGS += -O3 -I$(RTE_SDK)/lib/librte_power/
CFLAGS += $(WERROR_FLAGS)
* Copyright(c) 2010-2014 Intel Corporation
*/
-/*
#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-#include <sys/epoll.h>
-#include <fcntl.h>
-#include <unistd.h>
#include <stdlib.h>
-#include <errno.h>
-*/
#include <signal.h>
+#include <getopt.h>
+#include <string.h>
#include <rte_lcore.h>
#include <rte_power.h>
#include <rte_debug.h>
+#include <rte_eal.h>
+#include <rte_log.h>
#include "vm_power_cli_guest.h"
+#include "parse.h"
static void
sig_handler(int signo)
}
+#define MAX_HOURS 24
+
+/* Parse the argument given in the command line of the application */
+static int
+parse_args(int argc, char **argv)
+{
+ int opt, ret;
+ char **argvopt;
+ int option_index;
+ char *prgname = argv[0];
+ const struct option lgopts[] = {
+ { "vm-name", required_argument, 0, 'n'},
+ { "busy-hours", required_argument, 0, 'b'},
+ { "quiet-hours", required_argument, 0, 'q'},
+ { "port-list", required_argument, 0, 'p'},
+ { "vcpu-list", required_argument, 0, 'l'},
+ { "policy", required_argument, 0, 'o'},
+ {NULL, 0, 0, 0}
+ };
+ struct channel_packet *policy;
+ unsigned short int hours[MAX_HOURS];
+ unsigned short int cores[MAX_VCPU_PER_VM];
+ unsigned short int ports[MAX_VCPU_PER_VM];
+ int i, cnt, idx;
+
+ policy = get_policy();
+ set_policy_defaults(policy);
+
+ argvopt = argv;
+
+ while ((opt = getopt_long(argc, argvopt, "n:b:q:p:",
+ lgopts, &option_index)) != EOF) {
+
+ switch (opt) {
+ /* portmask */
+ case 'n':
+ strcpy(policy->vm_name, optarg);
+ printf("Setting VM Name to [%s]\n", policy->vm_name);
+ break;
+ case 'b':
+ case 'q':
+ //printf("***Processing set using [%s]\n", optarg);
+ cnt = parse_set(optarg, hours, MAX_HOURS);
+ if (cnt < 0) {
+ printf("Invalid value passed to quiet/busy hours - [%s]\n",
+ optarg);
+ break;
+ }
+ idx = 0;
+ for (i = 0; i < MAX_HOURS; i++) {
+ if (hours[i]) {
+ if (opt == 'b') {
+ printf("***Busy Hour %d\n", i);
+ policy->timer_policy.busy_hours
+ [idx++] = i;
+ } else {
+ printf("***Quiet Hour %d\n", i);
+ policy->timer_policy.quiet_hours
+ [idx++] = i;
+ }
+ }
+ }
+ break;
+ case 'l':
+ cnt = parse_set(optarg, cores, MAX_VCPU_PER_VM);
+ if (cnt < 0) {
+ printf("Invalid value passed to vcpu-list - [%s]\n",
+ optarg);
+ break;
+ }
+ idx = 0;
+ for (i = 0; i < MAX_VCPU_PER_VM; i++) {
+ if (cores[i]) {
+ printf("***Using core %d\n", i);
+ policy->vcpu_to_control[idx++] = i;
+ }
+ }
+ policy->num_vcpu = idx;
+ printf("Total cores: %d\n", idx);
+ break;
+ case 'p':
+ cnt = parse_set(optarg, ports, MAX_VCPU_PER_VM);
+ if (cnt < 0) {
+ printf("Invalid value passed to port-list - [%s]\n",
+ optarg);
+ break;
+ }
+ idx = 0;
+ for (i = 0; i < MAX_VCPU_PER_VM; i++) {
+ if (ports[i]) {
+ printf("***Using port %d\n", i);
+ set_policy_mac(i, idx++);
+ }
+ }
+ policy->nb_mac_to_monitor = idx;
+ printf("Total Ports: %d\n", idx);
+ break;
+ case 'o':
+ if (!strcmp(optarg, "TRAFFIC"))
+ policy->policy_to_use = TRAFFIC;
+ else if (!strcmp(optarg, "TIME"))
+ policy->policy_to_use = TIME;
+ else if (!strcmp(optarg, "WORKLOAD"))
+ policy->policy_to_use = WORKLOAD;
+ else if (!strcmp(optarg, "BRANCH_RATIO"))
+ policy->policy_to_use = BRANCH_RATIO;
+ else {
+ printf("Invalid policy specified: %s\n",
+ optarg);
+ return -1;
+ }
+ break;
+ /* long options */
+
+ case 0:
+ break;
+
+ default:
+ return -1;
+ }
+ }
+
+ if (optind >= 0)
+ argv[optind-1] = prgname;
+
+ ret = optind-1;
+ optind = 0; /* reset getopt lib */
+ return ret;
+}
+
int
main(int argc, char **argv)
{
signal(SIGINT, sig_handler);
signal(SIGTERM, sig_handler);
+ argc -= ret;
+ argv += ret;
+
+ /* parse application arguments (after the EAL ones) */
+ ret = parse_args(argc, argv);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Invalid arguments\n");
+
rte_power_set_env(PM_ENV_KVM_VM);
RTE_LCORE_FOREACH(lcore_id) {
rte_power_init(lcore_id);
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation.
+ * Copyright(c) 2014 6WIND S.A.
+ */
+
+#include <stdlib.h>
+#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;
+}
--- /dev/null
+/* 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_ */
cmdline_fixed_string_t quit;
};
+union PFID {
+ struct ether_addr addr;
+ uint64_t pfid;
+};
+
+static struct channel_packet policy;
+
+struct channel_packet *
+get_policy(void)
+{
+ return &policy;
+}
+
+int
+set_policy_mac(int port, int idx)
+{
+ struct channel_packet *policy;
+ union PFID pfid;
+
+ /* Use port MAC address as the vfid */
+ rte_eth_macaddr_get(port, &pfid.addr);
+
+ printf("Port %u MAC: %02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 ":"
+ "%02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 "\n",
+ port,
+ pfid.addr.addr_bytes[0], pfid.addr.addr_bytes[1],
+ pfid.addr.addr_bytes[2], pfid.addr.addr_bytes[3],
+ pfid.addr.addr_bytes[4], pfid.addr.addr_bytes[5]);
+ policy = get_policy();
+ policy->vfid[idx] = pfid.pfid;
+ return 0;
+}
+
+void
+set_policy_defaults(struct channel_packet *pkt)
+{
+ set_policy_mac(0, 0);
+ pkt->nb_mac_to_monitor = 1;
+
+ pkt->t_boost_status.tbEnabled = false;
+
+ pkt->vcpu_to_control[0] = 0;
+ pkt->vcpu_to_control[1] = 1;
+ pkt->num_vcpu = 2;
+ /* Dummy Population. */
+ pkt->traffic_policy.min_packet_thresh = 96000;
+ pkt->traffic_policy.avg_max_packet_thresh = 1800000;
+ pkt->traffic_policy.max_max_packet_thresh = 2000000;
+
+ pkt->timer_policy.busy_hours[0] = 3;
+ pkt->timer_policy.busy_hours[1] = 4;
+ pkt->timer_policy.busy_hours[2] = 5;
+ pkt->timer_policy.quiet_hours[0] = 11;
+ pkt->timer_policy.quiet_hours[1] = 12;
+ pkt->timer_policy.quiet_hours[2] = 13;
+
+ pkt->timer_policy.hours_to_use_traffic_profile[0] = 8;
+ pkt->timer_policy.hours_to_use_traffic_profile[1] = 10;
+
+ pkt->workload = LOW;
+ pkt->policy_to_use = TIME;
+ pkt->command = PKT_POLICY;
+ strcpy(pkt->vm_name, "ubuntu2");
+}
+
static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result,
__attribute__((unused)) struct cmdline *cl,
__attribute__((unused)) void *data)
cmdline_fixed_string_t cmd;
};
-union PFID {
- struct ether_addr addr;
- uint64_t pfid;
-};
-
static inline int
-send_policy(void)
+send_policy(struct channel_packet *pkt)
{
- struct channel_packet pkt;
int ret;
- union PFID pfid;
- /* Use port MAC address as the vfid */
- rte_eth_macaddr_get(0, &pfid.addr);
- printf("Port %u MAC: %02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 ":"
- "%02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 "\n",
- 1,
- pfid.addr.addr_bytes[0], pfid.addr.addr_bytes[1],
- pfid.addr.addr_bytes[2], pfid.addr.addr_bytes[3],
- pfid.addr.addr_bytes[4], pfid.addr.addr_bytes[5]);
- pkt.vfid[0] = pfid.pfid;
-
- pkt.nb_mac_to_monitor = 1;
- pkt.t_boost_status.tbEnabled = false;
-
- pkt.vcpu_to_control[0] = 0;
- pkt.vcpu_to_control[1] = 1;
- pkt.num_vcpu = 2;
- /* Dummy Population. */
- pkt.traffic_policy.min_packet_thresh = 96000;
- pkt.traffic_policy.avg_max_packet_thresh = 1800000;
- pkt.traffic_policy.max_max_packet_thresh = 2000000;
-
- pkt.timer_policy.busy_hours[0] = 3;
- pkt.timer_policy.busy_hours[1] = 4;
- pkt.timer_policy.busy_hours[2] = 5;
- pkt.timer_policy.quiet_hours[0] = 11;
- pkt.timer_policy.quiet_hours[1] = 12;
- pkt.timer_policy.quiet_hours[2] = 13;
-
- pkt.timer_policy.hours_to_use_traffic_profile[0] = 8;
- pkt.timer_policy.hours_to_use_traffic_profile[1] = 10;
-
- pkt.workload = LOW;
- pkt.policy_to_use = TIME;
- pkt.command = PKT_POLICY;
- strcpy(pkt.vm_name, "ubuntu2");
- ret = rte_power_guest_channel_send_msg(&pkt, 1);
+ ret = rte_power_guest_channel_send_msg(pkt, 1);
if (ret == 0)
return 1;
RTE_LOG(DEBUG, POWER, "Error sending message: %s\n",
if (!strcmp(res->cmd, "now")) {
printf("Sending Policy down now!\n");
- ret = send_policy();
+ ret = send_policy(&policy);
}
if (ret != 1)
cmdline_printf(cl, "Error sending message: %s\n",
#include "channel_commands.h"
+struct channel_packet *get_policy(void);
+
+int set_policy_mac(int port, int idx);
+
+void set_policy_defaults(struct channel_packet *pkt);
+
void run_cli(__attribute__((unused)) void *arg);
#ifdef __cplusplus