From patchwork Fri Aug 4 13:54:42 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Hunt, David" X-Patchwork-Id: 27451 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id DF9885699; Fri, 4 Aug 2017 15:55:13 +0200 (CEST) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by dpdk.org (Postfix) with ESMTP id 265284C57 for ; Fri, 4 Aug 2017 15:55:10 +0200 (CEST) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 04 Aug 2017 06:55:09 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.41,321,1498546800"; d="scan'208";a="119769069" Received: from silpixa00397898.ir.intel.com (HELO silpixa00397898.ger.corp.intel.com) ([10.237.223.116]) by orsmga002.jf.intel.com with ESMTP; 04 Aug 2017 06:55:08 -0700 From: David Hunt To: dev@dpdk.org Cc: thomas@monjalon.net, jingjing.wu@intel.com, David Hunt , Nemanja Marjanovic , Rory Sexton Date: Fri, 4 Aug 2017 14:54:42 +0100 Message-Id: <1501854887-42427-6-git-send-email-david.hunt@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1501854887-42427-1-git-send-email-david.hunt@intel.com> References: <1501854887-42427-1-git-send-email-david.hunt@intel.com> Subject: [dpdk-dev] [RFC 05/10] examples/vm_power_mgr: add policy to channels 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: Nemanja Marjanovic Signed-off-by: Rory Sexton Signed-off-by: David Hunt --- examples/vm_power_manager/channel_monitor.c | 353 +++++++++++++++++++++++----- examples/vm_power_manager/channel_monitor.h | 18 ++ 2 files changed, 315 insertions(+), 56 deletions(-) diff --git a/examples/vm_power_manager/channel_monitor.c b/examples/vm_power_manager/channel_monitor.c index e7f5cc4..822f2cb 100644 --- a/examples/vm_power_manager/channel_monitor.c +++ b/examples/vm_power_manager/channel_monitor.c @@ -41,13 +41,16 @@ #include #include #include +#include #include #include #include #include +#include +#include - +#include #include "channel_monitor.h" #include "channel_commands.h" #include "channel_manager.h" @@ -57,10 +60,15 @@ #define MAX_EVENTS 256 - +uint64_t vsi_pkt_count_prev[384]; +uint64_t rdtsc_prev[384]; +double time_period_s = 1; +double cpu_tsc_hz = 2200000000; static volatile unsigned run_loop = 1; static int global_event_fd; +static unsigned int policy_is_set; static struct epoll_event *global_events_list; +static struct policy policies[MAX_VMS]; void channel_monitor_exit(void) { @@ -68,70 +76,292 @@ void channel_monitor_exit(void) rte_free(global_events_list); } -static int -process_request(struct channel_packet *pkt, struct channel_info *chan_info) +static void +core_share(int pNo, int z, int x, int t) { - uint64_t core_mask; + if (policies[pNo].core_share[z].pcpu == lvm_info[x].pcpus[t]) { + if (strcmp(policies[pNo].pkt.vm_name, + lvm_info[x].vm_name) != 0) { + policies[pNo].core_share[z].status = 1; + power_manager_scale_core_max( + policies[pNo].core_share[z].pcpu); + } + } +} - if (chan_info == NULL) - return -1; +static void +core_share_status(int pNo) { - if (rte_atomic32_cmpset(&(chan_info->status), CHANNEL_MGR_CHANNEL_CONNECTED, - CHANNEL_MGR_CHANNEL_PROCESSING) == 0) - return -1; + int noVms, noVcpus, z, x, t; - 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; + get_all_vm(&noVms, &noVcpus); + + /* Reset Core Share Status. */ + for (z = 0; z < noVcpus; z++) + policies[pNo].core_share[z].status = 0; + + /* Foreach vcpu in a policy. */ + for (z = 0; z < noVcpus; z++) { + /* Foreach VM on the platform. */ + for (x = 0; x < noVms; x++) { + /* Foreach vcpu of VMs on platform. */ + for (t = 0; t < noVcpus; t++) + core_share(pNo, z, x, t); } - if (__builtin_popcountll(core_mask) == 1) { + } +} - unsigned core_num = __builtin_ffsll(core_mask) - 1; +#define ITERATIVE_BITMASK_CHECK_64(mask_u64b, i) \ + for (i = 0; mask_u64b; mask_u64b &= ~(1ULL << i++)) \ + if ((mask_u64b >> i) & 1) \ - switch (pkt->unit) { - case(CPU_POWER_SCALE_MIN): - power_manager_scale_core_min(core_num); - break; - case(CPU_POWER_SCALE_MAX): - power_manager_scale_core_max(core_num); - break; - case(CPU_POWER_SCALE_DOWN): - power_manager_scale_core_down(core_num); - break; - case(CPU_POWER_SCALE_UP): - power_manager_scale_core_up(core_num); - break; - default: +static void +get_pcpu_to_control(struct policy *pol) { + + /* Convert vcpu to pcpu. */ + struct vm_info info; + int pcpu, count; + + printf("Looking for pcpu for %s\n", pol->pkt.vm_name); + get_info_vm(pol->pkt.vm_name, &info); + + for (count = 0; count < 2; count++) { + ITERATIVE_BITMASK_CHECK_64( + info.pcpu_mask[pol->pkt.vcpu_to_control[count]], + pcpu) { + pol->core_share[count].pcpu = pcpu; + printf("pcpu is %d\n", pcpu); + } + } +} + +static int +get_pfid(struct policy *pol) { + + int i, x, ret = 0, nb_ports; + + nb_ports = rte_eth_dev_count(); + for (i = 0; i < pol->pkt.nb_mac_to_monitor; i++) { + + for (x = 0; x < nb_ports; x++) { + ret = vfid_to_pfid_direct(x, pol->pkt.vfid[i]); + if (ret != -1) { + pol->port[i] = x; break; } - } else { - switch (pkt->unit) { - case(CPU_POWER_SCALE_MIN): - power_manager_scale_mask_min(core_mask); - break; - case(CPU_POWER_SCALE_MAX): - power_manager_scale_mask_max(core_mask); + } + if (ret == -1) { + RTE_LOG(ERR, CHANNEL_MONITOR, + "Error with Policy. MAC not found on " + "attached ports "); + pol->enabled = 0; + return ret; + } + pol->pfid[i] = ret; + } + return 1; +} + +static int +update_policy(struct channel_packet *pkt) { + + unsigned int updated = 0; + + for (int i = 0; i < MAX_VMS; i++) { + if (strcmp(policies[i].pkt.vm_name, pkt->vm_name) == 0) { + policies[i].pkt = *pkt; + get_pcpu_to_control(&policies[i]); + if (get_pfid(&policies[i]) == -1) { + updated = 1; + break; + } + core_share_status(i); + policies[i].enabled = 1; + updated = 1; + } + } + if (!updated) { + for (int i = 0; i < MAX_VMS; i++) { + if (policies[i].enabled == 0) { + policies[i].pkt = *pkt; + get_pcpu_to_control(&policies[i]); + if (get_pfid(&policies[i]) == -1) + break; + core_share_status(i); + policies[i].enabled = 1; + break; + } + } + } + return 0; +} + +static uint64_t +get_pkt_diff(struct policy *pol) { + + uint64_t vsi_pkt_count, + vsi_pkt_total = 0, + vsi_pkt_count_prev_total = 0; + double rdtsc_curr, rdtsc_diff, diff; + int x; + + for (x = 0; x < pol->pkt.nb_mac_to_monitor; x++) { + + /*Read vsi stats*/ + vsi_pkt_count = read_pf_stats_direct(x, pol->pfid[x]); + vsi_pkt_total += vsi_pkt_count; + + vsi_pkt_count_prev_total += vsi_pkt_count_prev[pol->pfid[x]]; + vsi_pkt_count_prev[pol->pfid[x]] = vsi_pkt_count; + } + + rdtsc_curr = rte_rdtsc_precise(); + rdtsc_diff = rdtsc_curr - rdtsc_prev[pol->pfid[x-1]]; + rdtsc_prev[pol->pfid[x-1]] = rdtsc_curr; + + diff = (vsi_pkt_total - vsi_pkt_count_prev_total) * + (cpu_tsc_hz / rdtsc_diff); + + return diff; +} + +static void +apply_traffic_profile(struct policy *pol) { + + int count; + uint64_t diff = 0; + + diff = get_pkt_diff(pol); + + printf("Applying traffic profile\n"); + + if (diff >= (pol->pkt.traffic_policy.max_max_packet_thresh)) { + for (count = 0; count < 2; count++) { + if (pol->core_share[count].status != 1) + power_manager_scale_core_max( + pol->core_share[count].pcpu); + } + } else if (diff >= (pol->pkt.traffic_policy.avg_max_packet_thresh)) { + for (count = 0; count < 2; count++) { + if (pol->core_share[count].status != 1) + power_manager_scale_core_med( + pol->core_share[count].pcpu); + } + } else if (diff < (pol->pkt.traffic_policy.avg_max_packet_thresh)) { + for (count = 0; count < 2; count++) { + if (pol->core_share[count].status != 1) + power_manager_scale_core_min( + pol->core_share[count].pcpu); + } + } +} + +static void +apply_time_profile(struct policy *pol) { + + int count, x; + struct timeval tv; + struct tm *ptm; + char time_string[40]; + + /* Obtain the time of day, and convert it to a tm struct. */ + gettimeofday(&tv, NULL); + ptm = localtime(&tv.tv_sec); + /* Format the date and time, down to a single second. */ + strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", ptm); + + for (x = 0; x < HOURS; x++) { + + if (ptm->tm_hour == pol->pkt.timer_policy.busy_hours[x]) { + for (count = 0; count < 2; count++) { + if (pol->core_share[count].status != 1) + printf("Scaling up core %d to max\n", + pol->core_share[count].pcpu); + power_manager_scale_core_max( + pol->core_share[count].pcpu); + } break; - case(CPU_POWER_SCALE_DOWN): - power_manager_scale_mask_down(core_mask); + } else if (ptm->tm_hour == + pol->pkt.timer_policy.quiet_hours[x]) { + for (count = 0; count < 2; count++) { + if (pol->core_share[count].status != 1) + printf("Scaling down core %d to min\n", + pol->core_share[count].pcpu); + power_manager_scale_core_min( + pol->core_share[count].pcpu); + } break; - case(CPU_POWER_SCALE_UP): - power_manager_scale_mask_up(core_mask); + } else if (ptm->tm_hour == + pol->pkt.timer_policy.hours_to_use_traffic_profile[x]) { + apply_traffic_profile(pol); break; - default: - break; - } + } + } +} + +static void +apply_workload_profile(struct policy *pol) { + + int count; + if (pol->pkt.workload == HIGH) { + for (count = 0; count < 2; count++) { + if (pol->core_share[count].status != 1) + power_manager_scale_core_max( + pol->core_share[count].pcpu); } + } else if (pol->pkt.workload == MEDIUM) { + for (count = 0; count < 2; count++) { + if (pol->core_share[count].status != 1) + power_manager_scale_core_med( + pol->core_share[count].pcpu); + } + } else if (pol->pkt.workload == LOW) { + for (count = 0; count < 2; count++) { + if (pol->core_share[count].status != 1) + power_manager_scale_core_min( + pol->core_share[count].pcpu); + } + } +} + +static void +apply_policy(struct policy *pol) { + + struct channel_packet *pkt = &pol->pkt; + + /*Check policy to use*/ + if (pkt->policy_to_use == TRAFFIC) + apply_traffic_profile(pol); + else if (pkt->policy_to_use == TIME) + apply_time_profile(pol); + else if (pkt->policy_to_use == WORKLOAD) + apply_workload_profile(pol); +} + + + +static int +process_request(struct channel_packet *pkt, struct channel_info *chan_info) +{ + if (chan_info == NULL) + return -1; + + if (rte_atomic32_cmpset(&(chan_info->status), + CHANNEL_MGR_CHANNEL_CONNECTED, + CHANNEL_MGR_CHANNEL_PROCESSING) == 0) + return -1; + + if (pkt->command == PKT_POLICY) { + printf("\nProcessing Policy request from Guest\n"); + update_policy(pkt); + policy_is_set = 1; } - /* Return is not checked as channel status may have been set to DISABLED - * from management thread + /* 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, + rte_atomic32_cmpset(&(chan_info->status), + CHANNEL_MGR_CHANNEL_PROCESSING, CHANNEL_MGR_CHANNEL_CONNECTED); return 0; @@ -197,9 +427,10 @@ run_channel_monitor(void) 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)) { + (global_events_list[i].events & EPOLLHUP)) { RTE_LOG(DEBUG, CHANNEL_MONITOR, "Remote closed connection for " - "channel '%s'\n", chan_info->channel_path); + "channel '%s'\n", + chan_info->channel_path); remove_channel(&chan_info); continue; } @@ -211,14 +442,17 @@ run_channel_monitor(void) int buffer_len = sizeof(pkt); while (buffer_len > 0) { - n_bytes = read(chan_info->fd, buffer, buffer_len); + 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)); + RTE_LOG(DEBUG, CHANNEL_MONITOR, + "Received error on " + "channel '%s' read: %s\n", + chan_info->channel_path, + strerror(err)); remove_channel(&chan_info); break; } @@ -229,5 +463,12 @@ run_channel_monitor(void) process_request(&pkt, chan_info); } } + rte_delay_us(time_period_s*1000000); + if (policy_is_set) { + for (int j = 0; j < MAX_VMS; j++) { + if (policies[j].enabled == 1) + apply_policy(&policies[j]); + } + } } } diff --git a/examples/vm_power_manager/channel_monitor.h b/examples/vm_power_manager/channel_monitor.h index c138607..eb1383f 100644 --- a/examples/vm_power_manager/channel_monitor.h +++ b/examples/vm_power_manager/channel_monitor.h @@ -35,6 +35,24 @@ #define CHANNEL_MONITOR_H_ #include "channel_manager.h" +#include "channel_commands.h" + +struct core_share { + unsigned int pcpu; + /* + * 1 CORE SHARE + * 0 NOT SHARED + */ + int status; +}; + +struct policy { + struct channel_packet pkt; + uint32_t pfid[MAX_VFS]; + uint32_t port[MAX_VFS]; + unsigned int enabled; + struct core_share core_share[2]; +}; #ifdef __cplusplus extern "C" {