From patchwork Thu Aug 30 10:54:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Hunt, David" X-Patchwork-Id: 44010 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id D25904C9F; Thu, 30 Aug 2018 12:55:00 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id 46E742BA3 for ; Thu, 30 Aug 2018 12:54:58 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 30 Aug 2018 03:54:57 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.53,306,1531810800"; d="scan'208";a="84641468" Received: from silpixa00399952.ir.intel.com (HELO silpixa00399952.ger.corp.intel.com) ([10.237.223.64]) by fmsmga004.fm.intel.com with ESMTP; 30 Aug 2018 03:54:56 -0700 From: David Hunt To: dev@dpdk.org Cc: john.mcnamara@intel.com, david.hunt@intel.com Date: Thu, 30 Aug 2018 11:54:16 +0100 Message-Id: <20180830105422.1198-2-david.hunt@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180830105422.1198-1-david.hunt@intel.com> References: <20180830105422.1198-1-david.hunt@intel.com> Subject: [dpdk-dev] [PATCH v1 1/7] examples/power: add checks around hypervisor X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Allow vm_power_manager to run without requiring qemy to be present on the machine. This will be required for instances where the JSON interface is used for commands and polices, without any VMs present. A use case for this is a container enviromnent. Signed-off-by: David Hunt --- examples/vm_power_manager/channel_manager.c | 71 +++++++++++++-------- examples/vm_power_manager/channel_monitor.c | 2 +- 2 files changed, 44 insertions(+), 29 deletions(-) diff --git a/examples/vm_power_manager/channel_manager.c b/examples/vm_power_manager/channel_manager.c index 927fc35ab..2bb8641d3 100644 --- a/examples/vm_power_manager/channel_manager.c +++ b/examples/vm_power_manager/channel_manager.c @@ -43,7 +43,8 @@ static unsigned char *global_cpumaps; static virVcpuInfo *global_vircpuinfo; static size_t global_maplen; -static unsigned global_n_host_cpus; +static unsigned int global_n_host_cpus; +static unsigned int global_hypervisor_available; /* * Represents a single Virtual Machine @@ -198,7 +199,11 @@ get_pcpus_mask(struct channel_info *chan_info, unsigned vcpu) { struct virtual_machine_info *vm_info = (struct virtual_machine_info *)chan_info->priv_info; - return rte_atomic64_read(&vm_info->pcpu_mask[vcpu]); + + if ((global_hypervisor_available) && (vm_info != NULL)) + return rte_atomic64_read(&vm_info->pcpu_mask[vcpu]); + else + return 0; } static inline int @@ -559,6 +564,8 @@ get_all_vm(int *num_vm, int *num_vcpu) VIR_CONNECT_LIST_DOMAINS_PERSISTENT; unsigned int domain_flag = VIR_DOMAIN_VCPU_CONFIG; + if (!global_hypervisor_available) + return; memset(global_cpumaps, 0, CHANNEL_CMDS_MAX_CPUS*global_maplen); if (virNodeGetInfo(global_vir_conn_ptr, &node_info)) { @@ -768,38 +775,42 @@ connect_hypervisor(const char *path) } return 0; } - int -channel_manager_init(const char *path) +channel_manager_init(const char *path __rte_unused) { virNodeInfo info; LIST_INIT(&vm_list_head); if (connect_hypervisor(path) < 0) { - RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to initialize channel manager\n"); - return -1; - } - - global_maplen = VIR_CPU_MAPLEN(CHANNEL_CMDS_MAX_CPUS); + global_n_host_cpus = 64; + global_hypervisor_available = 0; + RTE_LOG(INFO, CHANNEL_MANAGER, "Unable to initialize channel manager\n"); + } else { + global_hypervisor_available = 1; + + global_maplen = VIR_CPU_MAPLEN(CHANNEL_CMDS_MAX_CPUS); + + global_vircpuinfo = rte_zmalloc(NULL, + sizeof(*global_vircpuinfo) * + CHANNEL_CMDS_MAX_CPUS, RTE_CACHE_LINE_SIZE); + if (global_vircpuinfo == NULL) { + RTE_LOG(ERR, CHANNEL_MANAGER, "Error allocating memory for CPU Info\n"); + goto error; + } + global_cpumaps = rte_zmalloc(NULL, + CHANNEL_CMDS_MAX_CPUS * global_maplen, + RTE_CACHE_LINE_SIZE); + if (global_cpumaps == NULL) + goto error; - global_vircpuinfo = rte_zmalloc(NULL, sizeof(*global_vircpuinfo) * - CHANNEL_CMDS_MAX_CPUS, RTE_CACHE_LINE_SIZE); - if (global_vircpuinfo == NULL) { - RTE_LOG(ERR, CHANNEL_MANAGER, "Error allocating memory for CPU Info\n"); - goto error; - } - global_cpumaps = rte_zmalloc(NULL, CHANNEL_CMDS_MAX_CPUS * global_maplen, - RTE_CACHE_LINE_SIZE); - if (global_cpumaps == NULL) { - goto error; + if (virNodeGetInfo(global_vir_conn_ptr, &info)) { + RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to retrieve node Info\n"); + goto error; + } + global_n_host_cpus = (unsigned int)info.cpus; } - if (virNodeGetInfo(global_vir_conn_ptr, &info)) { - RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to retrieve node Info\n"); - goto error; - } - global_n_host_cpus = (unsigned)info.cpus; if (global_n_host_cpus > CHANNEL_CMDS_MAX_CPUS) { RTE_LOG(WARNING, CHANNEL_MANAGER, "The number of host CPUs(%u) exceeds the " @@ -811,7 +822,8 @@ channel_manager_init(const char *path) return 0; error: - disconnect_hypervisor(); + if (global_hypervisor_available) + disconnect_hypervisor(); return -1; } @@ -838,7 +850,10 @@ channel_manager_exit(void) rte_free(vm_info); } - rte_free(global_cpumaps); - rte_free(global_vircpuinfo); - disconnect_hypervisor(); + if (global_hypervisor_available) { + /* Only needed if hypervisor available */ + rte_free(global_cpumaps); + rte_free(global_vircpuinfo); + disconnect_hypervisor(); + } } diff --git a/examples/vm_power_manager/channel_monitor.c b/examples/vm_power_manager/channel_monitor.c index 7fa47ba97..f180d74e6 100644 --- a/examples/vm_power_manager/channel_monitor.c +++ b/examples/vm_power_manager/channel_monitor.c @@ -66,7 +66,7 @@ static void core_share_status(int pNo) { - int noVms, noVcpus, z, x, t; + int noVms = 0, noVcpus = 0, z, x, t; get_all_vm(&noVms, &noVcpus); From patchwork Thu Aug 30 10:54:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Hunt, David" X-Patchwork-Id: 44011 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 89BCA4CB3; Thu, 30 Aug 2018 12:55:03 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id 1232C4C8D for ; Thu, 30 Aug 2018 12:54:58 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 30 Aug 2018 03:54:58 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.53,306,1531810800"; d="scan'208";a="84641474" Received: from silpixa00399952.ir.intel.com (HELO silpixa00399952.ger.corp.intel.com) ([10.237.223.64]) by fmsmga004.fm.intel.com with ESMTP; 30 Aug 2018 03:54:57 -0700 From: David Hunt To: dev@dpdk.org Cc: john.mcnamara@intel.com, david.hunt@intel.com Date: Thu, 30 Aug 2018 11:54:17 +0100 Message-Id: <20180830105422.1198-3-david.hunt@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180830105422.1198-1-david.hunt@intel.com> References: <20180830105422.1198-1-david.hunt@intel.com> Subject: [dpdk-dev] [PATCH v1 2/7] lib/power: add changes for host commands/policies X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Signed-off-by: David Hunt --- lib/librte_power/channel_commands.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/librte_power/channel_commands.h b/lib/librte_power/channel_commands.h index ee638eefa..a82724911 100644 --- a/lib/librte_power/channel_commands.h +++ b/lib/librte_power/channel_commands.h @@ -19,6 +19,7 @@ extern "C" { #define CPU_POWER 1 #define CPU_POWER_CONNECT 2 #define PKT_POLICY 3 +#define PKT_POLICY_REMOVE 4 /* CPU Power Command Scaling */ #define CPU_POWER_SCALE_UP 1 @@ -58,6 +59,8 @@ struct traffic { uint32_t max_max_packet_thresh; }; +enum core_type { VIRTUAL = 0, PHYSICAL }; + struct channel_packet { uint64_t resource_id; /**< core_num, device */ uint32_t unit; /**< scale down/up/min/max */ @@ -70,6 +73,7 @@ struct channel_packet { uint8_t vcpu_to_control[MAX_VCPU_PER_VM]; uint8_t num_vcpu; struct timer_profile timer_policy; + enum core_type core_type; enum workload workload; enum policy_to_use policy_to_use; struct t_boost_status t_boost_status; From patchwork Thu Aug 30 10:54:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Hunt, David" X-Patchwork-Id: 44012 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 393184CBD; Thu, 30 Aug 2018 12:55:05 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id E1E054C99 for ; Thu, 30 Aug 2018 12:54:59 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 30 Aug 2018 03:54:59 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.53,306,1531810800"; d="scan'208";a="84641481" Received: from silpixa00399952.ir.intel.com (HELO silpixa00399952.ger.corp.intel.com) ([10.237.223.64]) by fmsmga004.fm.intel.com with ESMTP; 30 Aug 2018 03:54:58 -0700 From: David Hunt To: dev@dpdk.org Cc: john.mcnamara@intel.com, david.hunt@intel.com Date: Thu, 30 Aug 2018 11:54:18 +0100 Message-Id: <20180830105422.1198-4-david.hunt@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180830105422.1198-1-david.hunt@intel.com> References: <20180830105422.1198-1-david.hunt@intel.com> Subject: [dpdk-dev] [PATCH v1 3/7] examples/power: add necessary changes to guest app X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" The changes here are minimal, as the guest app functionality is not changing at all, but there is a new element in the channel_packet struct that needs to have a default set (channel_packet->core_type). Signed-off-by: David Hunt --- examples/vm_power_manager/guest_cli/vm_power_cli_guest.c | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c b/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c index 0db1b804f..88b825c3b 100644 --- a/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c +++ b/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c @@ -92,6 +92,7 @@ set_policy_defaults(struct channel_packet *pkt) pkt->timer_policy.hours_to_use_traffic_profile[0] = 8; pkt->timer_policy.hours_to_use_traffic_profile[1] = 10; + pkt->core_type = VIRTUAL; pkt->workload = LOW; pkt->policy_to_use = TIME; pkt->command = PKT_POLICY; From patchwork Thu Aug 30 10:54:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Hunt, David" X-Patchwork-Id: 44013 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 179874D27; Thu, 30 Aug 2018 12:55:07 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id 511C54CA2 for ; Thu, 30 Aug 2018 12:55:01 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 30 Aug 2018 03:55:00 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.53,306,1531810800"; d="scan'208";a="84641493" Received: from silpixa00399952.ir.intel.com (HELO silpixa00399952.ger.corp.intel.com) ([10.237.223.64]) by fmsmga004.fm.intel.com with ESMTP; 30 Aug 2018 03:54:59 -0700 From: David Hunt To: dev@dpdk.org Cc: john.mcnamara@intel.com, david.hunt@intel.com Date: Thu, 30 Aug 2018 11:54:19 +0100 Message-Id: <20180830105422.1198-5-david.hunt@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180830105422.1198-1-david.hunt@intel.com> References: <20180830105422.1198-1-david.hunt@intel.com> Subject: [dpdk-dev] [PATCH v1 4/7] examples/power: add host channel to power manager X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This patch adds a fifo channel to the vm_power_manager app through which we can send commands and polices. Intended for sending JSON strings. The fifo is at /tmp/powermonitor/fifo.0 Signed-off-by: David Hunt --- examples/vm_power_manager/channel_manager.c | 108 +++++++++++++++ examples/vm_power_manager/channel_manager.h | 17 ++- examples/vm_power_manager/channel_monitor.c | 146 +++++++++++++++----- examples/vm_power_manager/main.c | 2 + 4 files changed, 238 insertions(+), 35 deletions(-) diff --git a/examples/vm_power_manager/channel_manager.c b/examples/vm_power_manager/channel_manager.c index 2bb8641d3..bcd106be1 100644 --- a/examples/vm_power_manager/channel_manager.c +++ b/examples/vm_power_manager/channel_manager.c @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -284,6 +285,38 @@ open_non_blocking_channel(struct channel_info *info) return 0; } +static int +open_host_channel(struct channel_info *info) +{ + int flags; + + info->fd = open(info->channel_path, O_RDWR | O_RSYNC); + if (info->fd == -1) { + RTE_LOG(ERR, CHANNEL_MANAGER, "Error(%s) opening fifo for '%s'\n", + strerror(errno), + info->channel_path); + return -1; + } + + /* Get current flags */ + flags = fcntl(info->fd, F_GETFL, 0); + if (flags < 0) { + RTE_LOG(WARNING, CHANNEL_MANAGER, "Error(%s) fcntl get flags socket for" + "'%s'\n", strerror(errno), info->channel_path); + return 1; + } + /* Set to Non Blocking */ + flags |= O_NONBLOCK; + if (fcntl(info->fd, F_SETFL, flags) < 0) { + RTE_LOG(WARNING, CHANNEL_MANAGER, + "Error(%s) setting non-blocking " + "socket for '%s'\n", + strerror(errno), info->channel_path); + return -1; + } + return 0; +} + static int setup_channel_info(struct virtual_machine_info **vm_info_dptr, struct channel_info **chan_info_dptr, unsigned channel_num) @@ -294,6 +327,7 @@ setup_channel_info(struct virtual_machine_info **vm_info_dptr, chan_info->channel_num = channel_num; chan_info->priv_info = (void *)vm_info; chan_info->status = CHANNEL_MGR_CHANNEL_DISCONNECTED; + chan_info->type = CHANNEL_TYPE_BINARY; if (open_non_blocking_channel(chan_info) < 0) { RTE_LOG(ERR, CHANNEL_MANAGER, "Could not open channel: " "'%s' for VM '%s'\n", @@ -316,6 +350,35 @@ setup_channel_info(struct virtual_machine_info **vm_info_dptr, return 0; } +static int +setup_host_channel_info(struct channel_info **chan_info_dptr, + unsigned int channel_num) +{ + struct channel_info *chan_info = *chan_info_dptr; + + chan_info->channel_num = channel_num; + chan_info->priv_info = (void *)0; + chan_info->status = CHANNEL_MGR_CHANNEL_DISCONNECTED; + chan_info->type = CHANNEL_TYPE_JSON; + sprintf(chan_info->channel_path, "%sfifo.0", CHANNEL_MGR_SOCKET_PATH); + + if (open_host_channel(chan_info) < 0) { + RTE_LOG(ERR, CHANNEL_MANAGER, "Could not open host channel: " + "'%s'\n", + chan_info->channel_path); + return -1; + } + if (add_channel_to_monitor(&chan_info) < 0) { + RTE_LOG(ERR, CHANNEL_MANAGER, "Could add channel: " + "'%s' to epoll ctl\n", + chan_info->channel_path); + return -1; + + } + chan_info->status = CHANNEL_MGR_CHANNEL_CONNECTED; + return 0; +} + int add_all_channels(const char *vm_name) { @@ -470,6 +533,51 @@ add_channels(const char *vm_name, unsigned *channel_list, return num_channels_enabled; } +int +add_host_channel(void) +{ + struct channel_info *chan_info; + char socket_path[PATH_MAX]; + int num_channels_enabled = 0; + int ret; + + snprintf(socket_path, sizeof(socket_path), "%sfifo.%u", + CHANNEL_MGR_SOCKET_PATH, 0); + + errno = 0; + ret = mkfifo(socket_path, 0666); + if ((errno != EEXIST) && (ret < 0)) { + printf(" %d %d, %d\n", ret, EEXIST, errno); + RTE_LOG(ERR, CHANNEL_MANAGER, "Cannot create fifo '%s' error: " + "%s\n", socket_path, strerror(errno)); + return 0; + } + + errno = 0; + if (access(socket_path, F_OK) < 0) { + RTE_LOG(ERR, CHANNEL_MANAGER, "Channel path '%s' error: " + "%s\n", socket_path, strerror(errno)); + return 0; + } + chan_info = rte_malloc(NULL, sizeof(*chan_info), + RTE_CACHE_LINE_SIZE); + if (chan_info == NULL) { + RTE_LOG(ERR, CHANNEL_MANAGER, "Error allocating memory for " + "channel '%s'\n", socket_path); + return 0; + } + snprintf(chan_info->channel_path, + sizeof(chan_info->channel_path), "%sfifo.%u", + CHANNEL_MGR_SOCKET_PATH, 0); + if (setup_host_channel_info(&chan_info, 0) < 0) { + rte_free(chan_info); + return 0; + } + num_channels_enabled++; + + return num_channels_enabled; +} + int remove_channel(struct channel_info **chan_info_dptr) { diff --git a/examples/vm_power_manager/channel_manager.h b/examples/vm_power_manager/channel_manager.h index 872ec6140..c157cc22b 100644 --- a/examples/vm_power_manager/channel_manager.h +++ b/examples/vm_power_manager/channel_manager.h @@ -37,7 +37,7 @@ struct sockaddr_un _sockaddr_un; #define UNIX_PATH_MAX sizeof(_sockaddr_un.sun_path) #endif -#define MAX_VMS 4 +#define MAX_VMS 64 #define MAX_VCPUS 20 @@ -54,6 +54,11 @@ enum channel_status { CHANNEL_MGR_CHANNEL_DISCONNECTED = 0, CHANNEL_MGR_CHANNEL_DISABLED, CHANNEL_MGR_CHANNEL_PROCESSING}; +/* Communication Channel Type */ +enum channel_type { CHANNEL_TYPE_BINARY = 0, + CHANNEL_TYPE_INI, + CHANNEL_TYPE_JSON}; + /* VM libvirt(qemu/KVM) connection status */ enum vm_status { CHANNEL_MGR_VM_INACTIVE = 0, CHANNEL_MGR_VM_ACTIVE}; @@ -66,6 +71,7 @@ struct channel_info { volatile uint32_t status; /**< Connection status(enum channel_status) */ int fd; /**< AF_UNIX socket fd */ unsigned channel_num; /**< CHANNEL_MGR_SOCKET_PATH/.channel_num */ + enum channel_type type; /**< Binary, ini, json, etc. */ void *priv_info; /**< Pointer to private info, do not modify */ }; @@ -226,6 +232,15 @@ int add_all_channels(const char *vm_name); int add_channels(const char *vm_name, unsigned *channel_list, unsigned num_channels); +/** + * Set up a fifo by which host applications can send command an policies + * through a fifo to the vm_power_manager + * + * @return + * - 0 for success + */ +int add_host_channel(void); + /** * Remove a channel definition from the channel manager. This must only be * called from the channel monitor thread. diff --git a/examples/vm_power_manager/channel_monitor.c b/examples/vm_power_manager/channel_monitor.c index f180d74e6..0ffa1112a 100644 --- a/examples/vm_power_manager/channel_monitor.c +++ b/examples/vm_power_manager/channel_monitor.c @@ -85,6 +85,33 @@ core_share_status(int pNo) } } + +static int +pcpu_monitor(struct policy *pol, struct core_info *ci, int pcpu, int count) +{ + int ret = 0; + + if (pol->pkt.policy_to_use == BRANCH_RATIO) { + ci->cd[pcpu].oob_enabled = 1; + ret = add_core_to_monitor(pcpu); + if (ret == 0) + RTE_LOG(INFO, CHANNEL_MONITOR, + "Monitoring pcpu %d OOB for %s\n", + pcpu, pol->pkt.vm_name); + else + RTE_LOG(ERR, CHANNEL_MONITOR, + "Error monitoring pcpu %d OOB for %s\n", + pcpu, pol->pkt.vm_name); + + } else { + pol->core_share[count].pcpu = pcpu; + RTE_LOG(INFO, CHANNEL_MONITOR, + "Monitoring pcpu %d for %s\n", + pcpu, pol->pkt.vm_name); + } + return ret; +} + static void get_pcpu_to_control(struct policy *pol) { @@ -94,34 +121,46 @@ get_pcpu_to_control(struct policy *pol) int pcpu, count; uint64_t mask_u64b; struct core_info *ci; - int ret; ci = get_core_info(); - RTE_LOG(INFO, CHANNEL_MONITOR, "Looking for pcpu for %s\n", - pol->pkt.vm_name); - get_info_vm(pol->pkt.vm_name, &info); - - for (count = 0; count < pol->pkt.num_vcpu; count++) { - mask_u64b = info.pcpu_mask[pol->pkt.vcpu_to_control[count]]; - for (pcpu = 0; mask_u64b; mask_u64b &= ~(1ULL << pcpu++)) { - if ((mask_u64b >> pcpu) & 1) { - if (pol->pkt.policy_to_use == BRANCH_RATIO) { - ci->cd[pcpu].oob_enabled = 1; - ret = add_core_to_monitor(pcpu); - if (ret == 0) - printf("Monitoring pcpu %d via Branch Ratio\n", - pcpu); - else - printf("Failed to start OOB Monitoring pcpu %d\n", - pcpu); - - } else { - pol->core_share[count].pcpu = pcpu; - printf("Monitoring pcpu %d\n", pcpu); - } + RTE_LOG(INFO, CHANNEL_MONITOR, + "Looking for pcpu for %s\n", pol->pkt.vm_name); + + /* + * So now that we're handling virtual and physical cores, we need to + * differenciate between them when adding them to the branch monitor. + * Virtual cores need to be converted to physical cores. + */ + + + + + if (pol->pkt.core_type == VIRTUAL) { + /* + * If the cores in the policy are virtual, we need to map them + * to physical core. We look up the vm info and use that for + * the mapping. + */ + get_info_vm(pol->pkt.vm_name, &info); + for (count = 0; count < pol->pkt.num_vcpu; count++) { + mask_u64b = + info.pcpu_mask[pol->pkt.vcpu_to_control[count]]; + for (pcpu = 0; mask_u64b; + mask_u64b &= ~(1ULL << pcpu++)) { + if ((mask_u64b >> pcpu) & 1) + pcpu_monitor(pol, ci, pcpu, count); } } + } else { + /* + * If the cores in the policy are physical, we just use + * those core id's directly. + */ + for (count = 0; count < pol->pkt.num_vcpu; count++) { + pcpu = pol->pkt.vcpu_to_control[count]; + pcpu_monitor(pol, ci, pcpu, count); + } } } @@ -160,8 +199,13 @@ update_policy(struct channel_packet *pkt) unsigned int updated = 0; int i; + + RTE_LOG(INFO, CHANNEL_MONITOR, + "Updating policy for %s\n", pkt->vm_name); + for (i = 0; i < MAX_VMS; i++) { if (strcmp(policies[i].pkt.vm_name, pkt->vm_name) == 0) { + /* Copy the contents of *pkt into the policy.pkt */ policies[i].pkt = *pkt; get_pcpu_to_control(&policies[i]); if (get_pfid(&policies[i]) == -1) { @@ -189,6 +233,24 @@ update_policy(struct channel_packet *pkt) return 0; } +static int +remove_policy(struct channel_packet *pkt __rte_unused) +{ + int i; + + /* + * Disabling the policy is simply a case of setting + * enabled to 0 + */ + for (i = 0; i < MAX_VMS; i++) { + if (strcmp(policies[i].pkt.vm_name, pkt->vm_name) == 0) { + policies[i].enabled = 0; + return 0; + } + } + return -1; +} + static uint64_t get_pkt_diff(struct policy *pol) { @@ -346,7 +408,6 @@ apply_policy(struct policy *pol) apply_workload_profile(pol); } - static int process_request(struct channel_packet *pkt, struct channel_info *chan_info) { @@ -355,6 +416,8 @@ process_request(struct channel_packet *pkt, struct channel_info *chan_info) if (chan_info == NULL) return -1; + RTE_LOG(INFO, CHANNEL_MONITOR, "Processing Request %s\n", pkt->vm_name); + if (rte_atomic32_cmpset(&(chan_info->status), CHANNEL_MGR_CHANNEL_CONNECTED, CHANNEL_MGR_CHANNEL_PROCESSING) == 0) return -1; @@ -362,10 +425,12 @@ process_request(struct channel_packet *pkt, struct channel_info *chan_info) if (pkt->command == CPU_POWER) { core_mask = get_pcpus_mask(chan_info, pkt->resource_id); if (core_mask == 0) { - RTE_LOG(ERR, CHANNEL_MONITOR, "Error get physical CPU mask for " - "channel '%s' using vCPU(%u)\n", chan_info->channel_path, - (unsigned)pkt->unit); - return -1; + /* + * Core mask will be 0 in the case where + * hypervisor is not available so we're working in + * the host, so use the core as the mask. + */ + core_mask = 1 << pkt->resource_id; } if (__builtin_popcountll(core_mask) == 1) { @@ -421,12 +486,20 @@ process_request(struct channel_packet *pkt, struct channel_info *chan_info) } if (pkt->command == PKT_POLICY) { - RTE_LOG(INFO, CHANNEL_MONITOR, "\nProcessing Policy request from Guest\n"); + RTE_LOG(INFO, CHANNEL_MONITOR, + "\nProcessing Policy request\n"); update_policy(pkt); policy_is_set = 1; } - /* Return is not checked as channel status may have been set to DISABLED + if (pkt->command == PKT_POLICY_REMOVE) { + RTE_LOG(INFO, CHANNEL_MONITOR, + "Removing policy %s\n", pkt->vm_name); + remove_policy(pkt); + } + + /* + * Return is not checked as channel status may have been set to DISABLED * from management thread */ rte_atomic32_cmpset(&(chan_info->status), CHANNEL_MGR_CHANNEL_PROCESSING, @@ -448,13 +521,16 @@ add_channel_to_monitor(struct channel_info **chan_info) "to epoll\n", info->channel_path); return -1; } + RTE_LOG(ERR, CHANNEL_MONITOR, "Added channel '%s' " + "to monitor\n", info->channel_path); return 0; } int remove_channel_from_monitor(struct channel_info *chan_info) { - if (epoll_ctl(global_event_fd, EPOLL_CTL_DEL, chan_info->fd, NULL) < 0) { + if (epoll_ctl(global_event_fd, EPOLL_CTL_DEL, + chan_info->fd, NULL) < 0) { RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to remove channel '%s' " "from epoll\n", chan_info->channel_path); return -1; @@ -467,11 +543,13 @@ channel_monitor_init(void) { global_event_fd = epoll_create1(0); if (global_event_fd == 0) { - RTE_LOG(ERR, CHANNEL_MONITOR, "Error creating epoll context with " - "error %s\n", strerror(errno)); + RTE_LOG(ERR, CHANNEL_MONITOR, + "Error creating epoll context with error %s\n", + strerror(errno)); return -1; } - global_events_list = rte_malloc("epoll_events", sizeof(*global_events_list) + global_events_list = rte_malloc("epoll_events", + sizeof(*global_events_list) * MAX_EVENTS, RTE_CACHE_LINE_SIZE); if (global_events_list == NULL) { RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to rte_malloc for " diff --git a/examples/vm_power_manager/main.c b/examples/vm_power_manager/main.c index 58c5fa45c..893bf4cdd 100644 --- a/examples/vm_power_manager/main.c +++ b/examples/vm_power_manager/main.c @@ -421,6 +421,8 @@ main(int argc, char **argv) return -1; } + add_host_channel(); + printf("Running core monitor on lcore id %d\n", lcore_id); rte_eal_remote_launch(run_core_monitor, NULL, lcore_id); From patchwork Thu Aug 30 10:54:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Hunt, David" X-Patchwork-Id: 44014 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 2EC3B4F9B; Thu, 30 Aug 2018 12:55:09 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id 5EC712BF7 for ; Thu, 30 Aug 2018 12:55:02 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 30 Aug 2018 03:55:02 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.53,306,1531810800"; d="scan'208";a="84641508" Received: from silpixa00399952.ir.intel.com (HELO silpixa00399952.ger.corp.intel.com) ([10.237.223.64]) by fmsmga004.fm.intel.com with ESMTP; 30 Aug 2018 03:55:01 -0700 From: David Hunt To: dev@dpdk.org Cc: john.mcnamara@intel.com, david.hunt@intel.com Date: Thu, 30 Aug 2018 11:54:20 +0100 Message-Id: <20180830105422.1198-6-david.hunt@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180830105422.1198-1-david.hunt@intel.com> References: <20180830105422.1198-1-david.hunt@intel.com> Subject: [dpdk-dev] [PATCH v1 5/7] examples/power: add json string handling X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add JSON string handling to vm_power_manager for JSON strings received through the fifo. The format of the JSON strings are detailed in the next patch, the vm_power_manager user guide documentation updates. This patch introduces a new dependency on Jansson, a C library for encoding, decoding and manipulating JSON data. To compile the sample app you now need to have installed libjansson4 and libjansson-dev (these may be named slightly differently depending on your Operating System) Signed-off-by: David Hunt --- examples/vm_power_manager/Makefile | 2 +- examples/vm_power_manager/channel_monitor.c | 295 +++++++++++++++++--- 2 files changed, 252 insertions(+), 45 deletions(-) diff --git a/examples/vm_power_manager/Makefile b/examples/vm_power_manager/Makefile index 13a5205ba..72f9e9075 100644 --- a/examples/vm_power_manager/Makefile +++ b/examples/vm_power_manager/Makefile @@ -29,7 +29,7 @@ endif CFLAGS += -O3 -I$(RTE_SDK)/lib/librte_power/ CFLAGS += $(WERROR_FLAGS) -LDLIBS += -lvirt +LDLIBS += -lvirt -ljansson ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y) diff --git a/examples/vm_power_manager/channel_monitor.c b/examples/vm_power_manager/channel_monitor.c index 0ffa1112a..b3f2852b4 100644 --- a/examples/vm_power_manager/channel_monitor.c +++ b/examples/vm_power_manager/channel_monitor.c @@ -9,10 +9,14 @@ #include #include #include +#include #include #include #include #include +#include +#include +#include #include #include @@ -35,6 +39,8 @@ uint64_t vsi_pkt_count_prev[384]; uint64_t rdtsc_prev[384]; +#define MAX_JSON_STRING_LEN 1024 +char json_data[MAX_JSON_STRING_LEN]; double time_period_ms = 1; static volatile unsigned run_loop = 1; @@ -43,6 +49,134 @@ static unsigned int policy_is_set; static struct epoll_event *global_events_list; static struct policy policies[MAX_VMS]; + +static int +parse_json_to_pkt(json_t *element, struct channel_packet *pkt) +{ + const char *key; + json_t *value; + int ret; + + memset(pkt, 0, sizeof(struct channel_packet)); + + pkt->nb_mac_to_monitor = 0; + pkt->t_boost_status.tbEnabled = false; + pkt->workload = LOW; + pkt->policy_to_use = TIME; + pkt->command = PKT_POLICY; + pkt->core_type = PHYSICAL; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "policy")) { + /* Recurse in to get the contents of profile */ + ret = parse_json_to_pkt(value, pkt); + if (ret) + return ret; + } else if (!strcmp(key, "instruction")) { + /* Recurse in to get the contents of instruction */ + ret = parse_json_to_pkt(value, pkt); + if (ret) + return ret; + } else if (!strcmp(key, "name")) { + strcpy(pkt->vm_name, json_string_value(value)); + } else if (!strcmp(key, "command")) { + char command[32]; + snprintf(command, 32, "%s", json_string_value(value)); + if (!strcmp(command, "power")) { + pkt->command = CPU_POWER; + } else if (!strcmp(command, "create")) { + pkt->command = PKT_POLICY; + } else if (!strcmp(command, "destroy")) { + pkt->command = PKT_POLICY_REMOVE; + } else { + RTE_LOG(ERR, CHANNEL_MONITOR, + "Invalid command received in JSON\n"); + return -1; + } + } else if (!strcmp(key, "policy_type")) { + char command[32]; + snprintf(command, 32, "%s", json_string_value(value)); + if (!strcmp(command, "TIME")) { + pkt->policy_to_use = TIME; + } else if (!strcmp(command, "TRAFFIC")) { + pkt->policy_to_use = TRAFFIC; + } else if (!strcmp(command, "WORKLOAD")) { + pkt->policy_to_use = WORKLOAD; + } else if (!strcmp(command, "BRANCH_RATIO")) { + pkt->policy_to_use = BRANCH_RATIO; + } else { + RTE_LOG(ERR, CHANNEL_MONITOR, + "Wrong policy_type received in JSON\n"); + return -1; + } + } else if (!strcmp(key, "busy_hours")) { + unsigned int i; + size_t size = json_array_size(value); + + for (i = 0; i < size; i++) { + int hour = (int)json_integer_value( + json_array_get(value, i)); + pkt->timer_policy.busy_hours[i] = hour; + } + } else if (!strcmp(key, "quiet_hours")) { + unsigned int i; + size_t size = json_array_size(value); + + for (i = 0; i < size; i++) { + int hour = (int)json_integer_value( + json_array_get(value, i)); + pkt->timer_policy.quiet_hours[i] = hour; + } + } else if (!strcmp(key, "core_list")) { + unsigned int i; + size_t size = json_array_size(value); + + for (i = 0; i < size; i++) { + int core = (int)json_integer_value( + json_array_get(value, i)); + pkt->vcpu_to_control[i] = core; + } + pkt->num_vcpu = size; + } else if (!strcmp(key, "min_packet_thresh")) { + pkt->traffic_policy.min_packet_thresh = + (uint32_t)json_integer_value(value); + } else if (!strcmp(key, "avg_packet_thresh")) { + pkt->traffic_policy.avg_max_packet_thresh = + (uint32_t)json_integer_value(value); + } else if (!strcmp(key, "max_packet_thresh")) { + pkt->traffic_policy.max_max_packet_thresh = + (uint32_t)json_integer_value(value); + } else if (!strcmp(key, "unit")) { + char unit[32]; + snprintf(unit, 32, "%s", json_string_value(value)); + if (!strcmp(unit, "SCALE_UP")) { + pkt->unit = CPU_POWER_SCALE_UP; + } else if (!strcmp(unit, "SCALE_DOWN")) { + pkt->unit = CPU_POWER_SCALE_DOWN; + } else if (!strcmp(unit, "SCALE_MAX")) { + pkt->unit = CPU_POWER_SCALE_MAX; + } else if (!strcmp(unit, "SCALE_MIN")) { + pkt->unit = CPU_POWER_SCALE_MIN; + } else if (!strcmp(unit, "ENABLE_TURBO")) { + pkt->unit = CPU_POWER_ENABLE_TURBO; + } else if (!strcmp(unit, "DISABLE_TURBO")) { + pkt->unit = CPU_POWER_DISABLE_TURBO; + } else { + RTE_LOG(ERR, CHANNEL_MONITOR, + "Invalid command received in JSON\n"); + return -1; + } + } else if (!strcmp(key, "resource_id")) { + pkt->resource_id = (uint32_t)json_integer_value(value); + } else { + RTE_LOG(ERR, CHANNEL_MONITOR, + "Unknown key received in JSON string: %s\n", + key); + } + } + return 0; +} + void channel_monitor_exit(void) { run_loop = 0; @@ -124,18 +258,11 @@ get_pcpu_to_control(struct policy *pol) ci = get_core_info(); - RTE_LOG(INFO, CHANNEL_MONITOR, - "Looking for pcpu for %s\n", pol->pkt.vm_name); - /* * So now that we're handling virtual and physical cores, we need to * differenciate between them when adding them to the branch monitor. * Virtual cores need to be converted to physical cores. */ - - - - if (pol->pkt.core_type == VIRTUAL) { /* * If the cores in the policy are virtual, we need to map them @@ -295,8 +422,6 @@ apply_traffic_profile(struct policy *pol) diff = get_pkt_diff(pol); - RTE_LOG(INFO, CHANNEL_MONITOR, "Applying traffic profile\n"); - if (diff >= (pol->pkt.traffic_policy.max_max_packet_thresh)) { for (count = 0; count < pol->pkt.num_vcpu; count++) { if (pol->core_share[count].status != 1) @@ -340,9 +465,6 @@ apply_time_profile(struct policy *pol) if (pol->core_share[count].status != 1) { power_manager_scale_core_max( pol->core_share[count].pcpu); - RTE_LOG(INFO, CHANNEL_MONITOR, - "Scaling up core %d to max\n", - pol->core_share[count].pcpu); } } break; @@ -352,9 +474,6 @@ apply_time_profile(struct policy *pol) if (pol->core_share[count].status != 1) { power_manager_scale_core_min( pol->core_share[count].pcpu); - RTE_LOG(INFO, CHANNEL_MONITOR, - "Scaling down core %d to min\n", - pol->core_share[count].pcpu); } } break; @@ -416,8 +535,6 @@ process_request(struct channel_packet *pkt, struct channel_info *chan_info) if (chan_info == NULL) return -1; - RTE_LOG(INFO, CHANNEL_MONITOR, "Processing Request %s\n", pkt->vm_name); - if (rte_atomic32_cmpset(&(chan_info->status), CHANNEL_MGR_CHANNEL_CONNECTED, CHANNEL_MGR_CHANNEL_PROCESSING) == 0) return -1; @@ -486,8 +603,8 @@ process_request(struct channel_packet *pkt, struct channel_info *chan_info) } if (pkt->command == PKT_POLICY) { - RTE_LOG(INFO, CHANNEL_MONITOR, - "\nProcessing Policy request\n"); + RTE_LOG(INFO, CHANNEL_MONITOR, "Processing policy request %s\n", + pkt->vm_name); update_policy(pkt); policy_is_set = 1; } @@ -559,6 +676,106 @@ channel_monitor_init(void) return 0; } +static void +read_binary_packet(struct channel_info *chan_info) +{ + struct channel_packet pkt; + void *buffer = &pkt; + int buffer_len = sizeof(pkt); + int n_bytes, err = 0; + + while (buffer_len > 0) { + n_bytes = read(chan_info->fd, + buffer, buffer_len); + if (n_bytes == buffer_len) + break; + if (n_bytes == -1) { + err = errno; + RTE_LOG(DEBUG, CHANNEL_MONITOR, + "Received error on " + "channel '%s' read: %s\n", + chan_info->channel_path, + strerror(err)); + remove_channel(&chan_info); + break; + } + buffer = (char *)buffer + n_bytes; + buffer_len -= n_bytes; + } + if (!err) + process_request(&pkt, chan_info); +} + + +static void +read_json_packet(struct channel_info *chan_info) +{ + struct channel_packet pkt; + int n_bytes, ret; + json_t *root; + json_error_t error; + + /* read opening brace to closing brace */ + do { + int idx = 0; + int indent = 0; + do { + n_bytes = read(chan_info->fd, &json_data[idx], 1); + if (n_bytes == 0) + break; + if (json_data[idx] == '{') + indent++; + if (json_data[idx] == '}') + indent--; + if ((indent > 0) || (idx >> 0)) + idx++; + if (indent == 0) + json_data[idx] = 0; + if (idx >= MAX_JSON_STRING_LEN) + break; + } while (indent > 0); + + if (indent > 0) + /* + * We've broken out of the read loop without getting + * a closing brace, so throw away the datai + */ + json_data[idx] = 0; + + if (strlen(json_data) == 0) + continue; + + printf("got [%s]\n", json_data); + + root = json_loads(json_data, 0, &error); + + if (root) { + /* + * Because our data is now in the json + * object, we can overwrite the pkt + * with a channel_packet struct, using + * parse_json_to_pkt() + */ + ret = parse_json_to_pkt(root, &pkt); + json_decref(root); + if (ret) { + RTE_LOG(ERR, CHANNEL_MONITOR, + "Error validating JSON profile data\n"); + break; + } + process_request(&pkt, chan_info); + } else { + RTE_LOG(ERR, CHANNEL_MONITOR, + "JSON error on line %d: %s\n", + error.line, error.text); + } + } while (n_bytes > 0); +} + + + + + void run_channel_monitor(void) { @@ -570,11 +787,16 @@ run_channel_monitor(void) if (!run_loop) break; for (i = 0; i < n_events; i++) { + if (!global_events_list[i].data.ptr) { + fflush(stdout); + continue; + } struct channel_info *chan_info = (struct channel_info *) global_events_list[i].data.ptr; if ((global_events_list[i].events & EPOLLERR) || (global_events_list[i].events & EPOLLHUP)) { - RTE_LOG(DEBUG, CHANNEL_MONITOR, "Remote closed connection for " + RTE_LOG(INFO, CHANNEL_MONITOR, + "Remote closed connection for " "channel '%s'\n", chan_info->channel_path); remove_channel(&chan_info); @@ -582,31 +804,16 @@ run_channel_monitor(void) } if (global_events_list[i].events & EPOLLIN) { - int n_bytes, err = 0; - struct channel_packet pkt; - void *buffer = &pkt; - int buffer_len = sizeof(pkt); - - while (buffer_len > 0) { - n_bytes = read(chan_info->fd, - buffer, buffer_len); - if (n_bytes == buffer_len) - break; - if (n_bytes == -1) { - err = errno; - RTE_LOG(DEBUG, CHANNEL_MONITOR, - "Received error on " - "channel '%s' read: %s\n", - chan_info->channel_path, - strerror(err)); - remove_channel(&chan_info); - break; - } - buffer = (char *)buffer + n_bytes; - buffer_len -= n_bytes; + switch (chan_info->type) { + case CHANNEL_TYPE_BINARY: + read_binary_packet(chan_info); + break; + case CHANNEL_TYPE_JSON: + read_json_packet(chan_info); + break; + default: + break; } - if (!err) - process_request(&pkt, chan_info); } } rte_delay_us(time_period_ms*1000); From patchwork Thu Aug 30 10:54:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Hunt, David" X-Patchwork-Id: 44015 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 7AC695592; Thu, 30 Aug 2018 12:55:10 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id 529034CAF for ; Thu, 30 Aug 2018 12:55:03 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 30 Aug 2018 03:55:02 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.53,306,1531810800"; d="scan'208";a="84641520" Received: from silpixa00399952.ir.intel.com (HELO silpixa00399952.ger.corp.intel.com) ([10.237.223.64]) by fmsmga004.fm.intel.com with ESMTP; 30 Aug 2018 03:55:02 -0700 From: David Hunt To: dev@dpdk.org Cc: john.mcnamara@intel.com, david.hunt@intel.com Date: Thu, 30 Aug 2018 11:54:21 +0100 Message-Id: <20180830105422.1198-7-david.hunt@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180830105422.1198-1-david.hunt@intel.com> References: <20180830105422.1198-1-david.hunt@intel.com> Subject: [dpdk-dev] [PATCH v1 6/7] doc/vm_power_manager: add JSON interface API info X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Signed-off-by: David Hunt --- .../sample_app_ug/vm_power_management.rst | 195 ++++++++++++++++++ 1 file changed, 195 insertions(+) diff --git a/doc/guides/sample_app_ug/vm_power_management.rst b/doc/guides/sample_app_ug/vm_power_management.rst index 855570d6b..13a325eae 100644 --- a/doc/guides/sample_app_ug/vm_power_management.rst +++ b/doc/guides/sample_app_ug/vm_power_management.rst @@ -337,6 +337,201 @@ monitoring of branch ratio on cores doing busy polling via PMDs. and will need to be adjusted for different workloads. + +JSON API +~~~~~~~~ + +In addition to the command line interface for host command and a virtio-serial +interface for VM power policies, there is also a JSON interface through which +power commands and policies can be sent. Sending a command or policy to the +power manager application is achieved by simply opening a fifo file, writing +a JSON string to that fifo, and closing the file. + +The fifo is at /tmp/powermonitor/fifo.0 + +The jason string can be a policy or instruction, and takes the following +format: + + .. code-block:: console + + {"packet_type": { + "pair_1": value, + "pair_2": value + }} + +The 'packet_type' header can contain one of two values, depending on +whether a policy or power command is being sent. The two possible values are +"policy" and "instruction", and the expected name-value pairs is different +depending on which type is being sent. + +The pairs are the format of standard JSON name-value pairs. The value type +varies between the different name/value pairs, and may be intgers, strings, +arrays, etc. Examples of policies follow later in this document. The allowed +names and value types are as follows: + + +:Pair Name: "name" +:Description: Name of the VM or Host. Allows the parser to associate the + policy with the relevant VM or Host OS. +:Type: string +:Values: any valid string +:Required: yes +:Example: + + .. code-block:: console + + ""name", "ubuntu2" + + +:Pair Name: "command" +:Description: The type of packet we're sending to the power manager. We can be + creating or destroying a policy, or sending a direct command to adjust + the frequency of a core, similar to the command line interface. +:Type: string +:Values: + + :"CREATE": used when creating a new policy, + :"DESTROY": used when removing a policy, + :"POWER": used when sending an immediate command, max, min, etc. +:Required: yes +:Example: + + .. code-block:: console + + "command", "CREATE" + + +:Pair Name: "policy_type" +:Description: Type of policy to apply. Please see vm_power_manager documentation + for more information on the types of policies that may be used. +:Type: string +:Values: + + :"TIME": Time-of-day policy. Frequencies of the relevant cores are + scaled up/down depending on busy and quiet hours. + :"TRAFFIC": This policy takes statistics from the NIC and scales up + and down accordingly. + :"WORKLOAD": This policy looks at how heavily loaded the cores are, + and scales up and down accordingly. + :"BRANCH_RATIO": This out-of-band policy can look at the ratio between + branch hits and misses on a core, and is useful for detecting + how much packet processing a core is doing. +:Required: only for CREATE/DESTROY command +:Example: + + .. code-block:: console + + "policy_type", "TIME" + +:Pair Name: "busy_hours" +:Description: The hours of the day in which we scale up the cores for busy + times. +:Type: array of integers +:Values: array with list of hour numbers, (0-23) +:Required: only for TIME policy +:Example: + + .. code-block:: console + + "busy_hours":[ 17, 18, 19, 20, 21, 22, 23 ] + +:Pair Name: "quiet_hours" +:Description: The hours of the day in which we scale down the cores for quiet + times. +:Type: array of integers +:Values: array with list of hour numbers, (0-23) +:Required: only for TIME policy +:Example: + + .. code-block:: console + + "quiet_hours":[ 2, 3, 4, 5, 6 ] + +:Pair Name: "core_list" +:Description: The cores to which to apply the policy. +:Type: array of integers +:Values: array with list of virtual CPUs. +:Required: only policy CREATE/DESTROY +:Example: + + .. code-block:: console + + "core_list":[ 10, 11 ] + +:Pair Name: "unit" +:Description: the type of power operation to apply in the command +:Type: string +:Values: + + :"SCALE_MAX": Scale frequency of this core to maximum + :"SCALE_MIN": Scale frequency of this core to minimum + :"SCALE_UP": Scale up frequency of this core + :"SCALE_DOWN": Scale down frequency of this core + :"ENABLE_TURBO": Enable Turbo Boost for this core + :"DISABLE_TURBO": Disable Turbo Boost for this core +:Required: only for POWER instruction +:Example: + + .. code-block:: console + + "unit", "SCALE_MAX" + +:Pair Name: "resource_id" +:Description: The core to which to apply the power command. +:Type: integer +:Values: valid core id for VM or host OS. +:Required: only POWER instruction +:Example: + + .. code-block:: console + + "resource_id": 10 + +JSON API Examples +~~~~~~~~~~~~~~~~~ + +Profile create example: + + .. code-block:: console + + {"policy": { + "name": "ubuntu", + "command": "create", + "policy_type": "TIME", + "busy_hours":[ 17, 18, 19, 20, 21, 22, 23 ], + "quiet_hours":[ 2, 3, 4, 5, 6 ], + "core_list":[ 11 ] + }} + +Profile destroy example: + + .. code-block:: console + + {"profile": { + "name": "ubuntu", + "command": "destroy", + }} + +Power command example: + + .. code-block:: console + + {"command": { + "name": "ubuntu", + "unit": "SCALE_MAX", + "resource_id": 10 + }} + +To send a JSON string to the Power Manager application, simply paste the +example JSON string into a text file and cat it into the fifo: + + .. code-block:: console + + cat file.json >/tmp/powermonitor/fifo.0 + +The console of the Power Manager application should indicate the command that +was just received via the fifo. + Compiling and Running the Guest Applications -------------------------------------------- From patchwork Thu Aug 30 10:54:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Hunt, David" X-Patchwork-Id: 44016 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 2693058C6; Thu, 30 Aug 2018 12:55:12 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id 3C8DD2BA3 for ; Thu, 30 Aug 2018 12:55:04 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 30 Aug 2018 03:55:03 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.53,306,1531810800"; d="scan'208";a="84641527" Received: from silpixa00399952.ir.intel.com (HELO silpixa00399952.ger.corp.intel.com) ([10.237.223.64]) by fmsmga004.fm.intel.com with ESMTP; 30 Aug 2018 03:55:03 -0700 From: David Hunt To: dev@dpdk.org Cc: john.mcnamara@intel.com, david.hunt@intel.com Date: Thu, 30 Aug 2018 11:54:22 +0100 Message-Id: <20180830105422.1198-8-david.hunt@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180830105422.1198-1-david.hunt@intel.com> References: <20180830105422.1198-1-david.hunt@intel.com> Subject: [dpdk-dev] [PATCH v1 7/7] examples/power: add json example files X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This patch provides some example files in the json_examples sub-directory for sending to the fifo. Signed-off-by: David Hunt --- examples/vm_power_manager/json_examples/README | 6 ++++++ examples/vm_power_manager/json_examples/create.json | 8 ++++++++ examples/vm_power_manager/json_examples/destroy.json | 4 ++++ examples/vm_power_manager/json_examples/set_core_max.json | 6 ++++++ examples/vm_power_manager/json_examples/set_core_min.json | 6 ++++++ 5 files changed, 30 insertions(+) create mode 100644 examples/vm_power_manager/json_examples/README create mode 100644 examples/vm_power_manager/json_examples/create.json create mode 100644 examples/vm_power_manager/json_examples/destroy.json create mode 100644 examples/vm_power_manager/json_examples/set_core_max.json create mode 100644 examples/vm_power_manager/json_examples/set_core_min.json diff --git a/examples/vm_power_manager/json_examples/README b/examples/vm_power_manager/json_examples/README new file mode 100644 index 000000000..a94c6b14b --- /dev/null +++ b/examples/vm_power_manager/json_examples/README @@ -0,0 +1,6 @@ +Sample files for sending to the vm_power_manager through the fifo. + +Simply cat the file to /tmp/powermonitor/fifo.0 when the vm_power_manager +application is running. + +E.g. cat create.json >/tmp/powermonitor/fifo.0 diff --git a/examples/vm_power_manager/json_examples/create.json b/examples/vm_power_manager/json_examples/create.json new file mode 100644 index 000000000..a7133d9a1 --- /dev/null +++ b/examples/vm_power_manager/json_examples/create.json @@ -0,0 +1,8 @@ +{"policy": { + "name": "policy-1", + "command": "create", + "policy_type": "TIME", + "busy_hours":[ 17, 18, 19, 20, 21, 22, 23 ], + "quiet_hours":[ 2, 3, 4, 5, 6 ], + "core_list":[ 11, 12 ] +}} diff --git a/examples/vm_power_manager/json_examples/destroy.json b/examples/vm_power_manager/json_examples/destroy.json new file mode 100644 index 000000000..587c9e7e9 --- /dev/null +++ b/examples/vm_power_manager/json_examples/destroy.json @@ -0,0 +1,4 @@ +{"policy": { + "name": "policy-1", + "command": "destroy" +}} diff --git a/examples/vm_power_manager/json_examples/set_core_max.json b/examples/vm_power_manager/json_examples/set_core_max.json new file mode 100644 index 000000000..497030a44 --- /dev/null +++ b/examples/vm_power_manager/json_examples/set_core_max.json @@ -0,0 +1,6 @@ +{"instruction": { + "name": "set_power", + "command": "power", + "unit": "SCALE_MAX", + "resource_id": 10 +}} diff --git a/examples/vm_power_manager/json_examples/set_core_min.json b/examples/vm_power_manager/json_examples/set_core_min.json new file mode 100644 index 000000000..76d934fd8 --- /dev/null +++ b/examples/vm_power_manager/json_examples/set_core_min.json @@ -0,0 +1,6 @@ +{"instruction": { + "name": "set_power", + "command": "power", + "unit": "SCALE_MIN", + "resource_id": 10 +}}