1e8ae9b66SAlan Carew /*- 2e8ae9b66SAlan Carew * BSD LICENSE 3e8ae9b66SAlan Carew * 4e8ae9b66SAlan Carew * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 5e8ae9b66SAlan Carew * All rights reserved. 6e8ae9b66SAlan Carew * 7e8ae9b66SAlan Carew * Redistribution and use in source and binary forms, with or without 8e8ae9b66SAlan Carew * modification, are permitted provided that the following conditions 9e8ae9b66SAlan Carew * are met: 10e8ae9b66SAlan Carew * 11e8ae9b66SAlan Carew * * Redistributions of source code must retain the above copyright 12e8ae9b66SAlan Carew * notice, this list of conditions and the following disclaimer. 13e8ae9b66SAlan Carew * * Redistributions in binary form must reproduce the above copyright 14e8ae9b66SAlan Carew * notice, this list of conditions and the following disclaimer in 15e8ae9b66SAlan Carew * the documentation and/or other materials provided with the 16e8ae9b66SAlan Carew * distribution. 17e8ae9b66SAlan Carew * * Neither the name of Intel Corporation nor the names of its 18e8ae9b66SAlan Carew * contributors may be used to endorse or promote products derived 19e8ae9b66SAlan Carew * from this software without specific prior written permission. 20e8ae9b66SAlan Carew * 21e8ae9b66SAlan Carew * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22e8ae9b66SAlan Carew * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23e8ae9b66SAlan Carew * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24e8ae9b66SAlan Carew * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25e8ae9b66SAlan Carew * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26e8ae9b66SAlan Carew * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27e8ae9b66SAlan Carew * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28e8ae9b66SAlan Carew * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29e8ae9b66SAlan Carew * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30e8ae9b66SAlan Carew * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31e8ae9b66SAlan Carew * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32e8ae9b66SAlan Carew */ 33e8ae9b66SAlan Carew 34e8ae9b66SAlan Carew #include <unistd.h> 35e8ae9b66SAlan Carew #include <stdio.h> 36e8ae9b66SAlan Carew #include <stdlib.h> 37e8ae9b66SAlan Carew #include <stdint.h> 38e8ae9b66SAlan Carew #include <signal.h> 39e8ae9b66SAlan Carew #include <errno.h> 40e8ae9b66SAlan Carew #include <string.h> 41e8ae9b66SAlan Carew #include <sys/types.h> 42e8ae9b66SAlan Carew #include <sys/epoll.h> 43e8ae9b66SAlan Carew #include <sys/queue.h> 44f14791a8SRory Sexton #include <sys/time.h> 45e8ae9b66SAlan Carew 46e8ae9b66SAlan Carew #include <rte_log.h> 47e8ae9b66SAlan Carew #include <rte_memory.h> 48e8ae9b66SAlan Carew #include <rte_malloc.h> 49e8ae9b66SAlan Carew #include <rte_atomic.h> 50f14791a8SRory Sexton #include <rte_cycles.h> 51f14791a8SRory Sexton #include <rte_ethdev.h> 52f14791a8SRory Sexton #include <rte_pmd_i40e.h> 53e8ae9b66SAlan Carew 54f14791a8SRory Sexton #include <libvirt/libvirt.h> 55e8ae9b66SAlan Carew #include "channel_monitor.h" 56e8ae9b66SAlan Carew #include "channel_commands.h" 57e8ae9b66SAlan Carew #include "channel_manager.h" 58e8ae9b66SAlan Carew #include "power_manager.h" 59e8ae9b66SAlan Carew 60e8ae9b66SAlan Carew #define RTE_LOGTYPE_CHANNEL_MONITOR RTE_LOGTYPE_USER1 61e8ae9b66SAlan Carew 62e8ae9b66SAlan Carew #define MAX_EVENTS 256 63e8ae9b66SAlan Carew 64f14791a8SRory Sexton uint64_t vsi_pkt_count_prev[384]; 65f14791a8SRory Sexton uint64_t rdtsc_prev[384]; 66e8ae9b66SAlan Carew 67f14791a8SRory Sexton double time_period_s = 1; 68e8ae9b66SAlan Carew static volatile unsigned run_loop = 1; 69e8ae9b66SAlan Carew static int global_event_fd; 70f14791a8SRory Sexton static unsigned int policy_is_set; 71e8ae9b66SAlan Carew static struct epoll_event *global_events_list; 72f14791a8SRory Sexton static struct policy policies[MAX_VMS]; 73e8ae9b66SAlan Carew 74e8ae9b66SAlan Carew void channel_monitor_exit(void) 75e8ae9b66SAlan Carew { 76e8ae9b66SAlan Carew run_loop = 0; 77e8ae9b66SAlan Carew rte_free(global_events_list); 78e8ae9b66SAlan Carew } 79e8ae9b66SAlan Carew 80f14791a8SRory Sexton static void 81f14791a8SRory Sexton core_share(int pNo, int z, int x, int t) 82f14791a8SRory Sexton { 83f14791a8SRory Sexton if (policies[pNo].core_share[z].pcpu == lvm_info[x].pcpus[t]) { 84f14791a8SRory Sexton if (strcmp(policies[pNo].pkt.vm_name, 85f14791a8SRory Sexton lvm_info[x].vm_name) != 0) { 86f14791a8SRory Sexton policies[pNo].core_share[z].status = 1; 87f14791a8SRory Sexton power_manager_scale_core_max( 88f14791a8SRory Sexton policies[pNo].core_share[z].pcpu); 89f14791a8SRory Sexton } 90f14791a8SRory Sexton } 91f14791a8SRory Sexton } 92f14791a8SRory Sexton 93f14791a8SRory Sexton static void 94f14791a8SRory Sexton core_share_status(int pNo) 95f14791a8SRory Sexton { 96f14791a8SRory Sexton 97f14791a8SRory Sexton int noVms, noVcpus, z, x, t; 98f14791a8SRory Sexton 99f14791a8SRory Sexton get_all_vm(&noVms, &noVcpus); 100f14791a8SRory Sexton 101f14791a8SRory Sexton /* Reset Core Share Status. */ 102f14791a8SRory Sexton for (z = 0; z < noVcpus; z++) 103f14791a8SRory Sexton policies[pNo].core_share[z].status = 0; 104f14791a8SRory Sexton 105f14791a8SRory Sexton /* Foreach vcpu in a policy. */ 106f14791a8SRory Sexton for (z = 0; z < policies[pNo].pkt.num_vcpu; z++) { 107f14791a8SRory Sexton /* Foreach VM on the platform. */ 108f14791a8SRory Sexton for (x = 0; x < noVms; x++) { 109f14791a8SRory Sexton /* Foreach vcpu of VMs on platform. */ 110f14791a8SRory Sexton for (t = 0; t < lvm_info[x].num_cpus; t++) 111f14791a8SRory Sexton core_share(pNo, z, x, t); 112f14791a8SRory Sexton } 113f14791a8SRory Sexton } 114f14791a8SRory Sexton } 115f14791a8SRory Sexton 116f14791a8SRory Sexton static void 117f14791a8SRory Sexton get_pcpu_to_control(struct policy *pol) 118f14791a8SRory Sexton { 119f14791a8SRory Sexton 120f14791a8SRory Sexton /* Convert vcpu to pcpu. */ 121f14791a8SRory Sexton struct vm_info info; 122f14791a8SRory Sexton int pcpu, count; 123f14791a8SRory Sexton uint64_t mask_u64b; 124f14791a8SRory Sexton 125f14791a8SRory Sexton RTE_LOG(INFO, CHANNEL_MONITOR, "Looking for pcpu for %s\n", 126f14791a8SRory Sexton pol->pkt.vm_name); 127f14791a8SRory Sexton get_info_vm(pol->pkt.vm_name, &info); 128f14791a8SRory Sexton 129f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 130f14791a8SRory Sexton mask_u64b = info.pcpu_mask[pol->pkt.vcpu_to_control[count]]; 131f14791a8SRory Sexton for (pcpu = 0; mask_u64b; mask_u64b &= ~(1ULL << pcpu++)) { 132f14791a8SRory Sexton if ((mask_u64b >> pcpu) & 1) 133f14791a8SRory Sexton pol->core_share[count].pcpu = pcpu; 134f14791a8SRory Sexton } 135f14791a8SRory Sexton } 136f14791a8SRory Sexton } 137f14791a8SRory Sexton 138f14791a8SRory Sexton static int 139f14791a8SRory Sexton get_pfid(struct policy *pol) 140f14791a8SRory Sexton { 141f14791a8SRory Sexton 142f14791a8SRory Sexton int i, x, ret = 0, nb_ports; 143f14791a8SRory Sexton 144f14791a8SRory Sexton nb_ports = rte_eth_dev_count(); 145f14791a8SRory Sexton for (i = 0; i < pol->pkt.nb_mac_to_monitor; i++) { 146f14791a8SRory Sexton 147f14791a8SRory Sexton for (x = 0; x < nb_ports; x++) { 148f14791a8SRory Sexton ret = rte_pmd_i40e_query_vfid_by_mac(x, 149f14791a8SRory Sexton (struct ether_addr *)&(pol->pkt.vfid[i])); 150f14791a8SRory Sexton if (ret != -EINVAL) { 151f14791a8SRory Sexton pol->port[i] = x; 152f14791a8SRory Sexton break; 153f14791a8SRory Sexton } 154f14791a8SRory Sexton } 155f14791a8SRory Sexton if (ret == -EINVAL || ret == -ENOTSUP || ret == ENODEV) { 156f14791a8SRory Sexton RTE_LOG(INFO, CHANNEL_MONITOR, 157f14791a8SRory Sexton "Error with Policy. MAC not found on " 158f14791a8SRory Sexton "attached ports "); 159f14791a8SRory Sexton pol->enabled = 0; 160f14791a8SRory Sexton return ret; 161f14791a8SRory Sexton } 162f14791a8SRory Sexton pol->pfid[i] = ret; 163f14791a8SRory Sexton } 164f14791a8SRory Sexton return 1; 165f14791a8SRory Sexton } 166f14791a8SRory Sexton 167f14791a8SRory Sexton static int 168f14791a8SRory Sexton update_policy(struct channel_packet *pkt) 169f14791a8SRory Sexton { 170f14791a8SRory Sexton 171f14791a8SRory Sexton unsigned int updated = 0; 172*7abd801fSDavid Hunt int i; 173f14791a8SRory Sexton 174*7abd801fSDavid Hunt for (i = 0; i < MAX_VMS; i++) { 175f14791a8SRory Sexton if (strcmp(policies[i].pkt.vm_name, pkt->vm_name) == 0) { 176f14791a8SRory Sexton policies[i].pkt = *pkt; 177f14791a8SRory Sexton get_pcpu_to_control(&policies[i]); 178f14791a8SRory Sexton if (get_pfid(&policies[i]) == -1) { 179f14791a8SRory Sexton updated = 1; 180f14791a8SRory Sexton break; 181f14791a8SRory Sexton } 182f14791a8SRory Sexton core_share_status(i); 183f14791a8SRory Sexton policies[i].enabled = 1; 184f14791a8SRory Sexton updated = 1; 185f14791a8SRory Sexton } 186f14791a8SRory Sexton } 187f14791a8SRory Sexton if (!updated) { 188*7abd801fSDavid Hunt for (i = 0; i < MAX_VMS; i++) { 189f14791a8SRory Sexton if (policies[i].enabled == 0) { 190f14791a8SRory Sexton policies[i].pkt = *pkt; 191f14791a8SRory Sexton get_pcpu_to_control(&policies[i]); 192f14791a8SRory Sexton if (get_pfid(&policies[i]) == -1) 193f14791a8SRory Sexton break; 194f14791a8SRory Sexton core_share_status(i); 195f14791a8SRory Sexton policies[i].enabled = 1; 196f14791a8SRory Sexton break; 197f14791a8SRory Sexton } 198f14791a8SRory Sexton } 199f14791a8SRory Sexton } 200f14791a8SRory Sexton return 0; 201f14791a8SRory Sexton } 202f14791a8SRory Sexton 203f14791a8SRory Sexton static uint64_t 204f14791a8SRory Sexton get_pkt_diff(struct policy *pol) 205f14791a8SRory Sexton { 206f14791a8SRory Sexton 207f14791a8SRory Sexton uint64_t vsi_pkt_count, 208f14791a8SRory Sexton vsi_pkt_total = 0, 209f14791a8SRory Sexton vsi_pkt_count_prev_total = 0; 210f14791a8SRory Sexton double rdtsc_curr, rdtsc_diff, diff; 211f14791a8SRory Sexton int x; 212f14791a8SRory Sexton struct rte_eth_stats vf_stats; 213f14791a8SRory Sexton 214f14791a8SRory Sexton for (x = 0; x < pol->pkt.nb_mac_to_monitor; x++) { 215f14791a8SRory Sexton 216f14791a8SRory Sexton /*Read vsi stats*/ 217f14791a8SRory Sexton if (rte_pmd_i40e_get_vf_stats(x, pol->pfid[x], &vf_stats) == 0) 218f14791a8SRory Sexton vsi_pkt_count = vf_stats.ipackets; 219f14791a8SRory Sexton else 220f14791a8SRory Sexton vsi_pkt_count = -1; 221f14791a8SRory Sexton 222f14791a8SRory Sexton vsi_pkt_total += vsi_pkt_count; 223f14791a8SRory Sexton 224f14791a8SRory Sexton vsi_pkt_count_prev_total += vsi_pkt_count_prev[pol->pfid[x]]; 225f14791a8SRory Sexton vsi_pkt_count_prev[pol->pfid[x]] = vsi_pkt_count; 226f14791a8SRory Sexton } 227f14791a8SRory Sexton 228f14791a8SRory Sexton rdtsc_curr = rte_rdtsc_precise(); 229f14791a8SRory Sexton rdtsc_diff = rdtsc_curr - rdtsc_prev[pol->pfid[x-1]]; 230f14791a8SRory Sexton rdtsc_prev[pol->pfid[x-1]] = rdtsc_curr; 231f14791a8SRory Sexton 232f14791a8SRory Sexton diff = (vsi_pkt_total - vsi_pkt_count_prev_total) * 233f14791a8SRory Sexton ((double)rte_get_tsc_hz() / rdtsc_diff); 234f14791a8SRory Sexton 235f14791a8SRory Sexton return diff; 236f14791a8SRory Sexton } 237f14791a8SRory Sexton 238f14791a8SRory Sexton static void 239f14791a8SRory Sexton apply_traffic_profile(struct policy *pol) 240f14791a8SRory Sexton { 241f14791a8SRory Sexton 242f14791a8SRory Sexton int count; 243f14791a8SRory Sexton uint64_t diff = 0; 244f14791a8SRory Sexton 245f14791a8SRory Sexton diff = get_pkt_diff(pol); 246f14791a8SRory Sexton 247f14791a8SRory Sexton RTE_LOG(INFO, CHANNEL_MONITOR, "Applying traffic profile\n"); 248f14791a8SRory Sexton 249f14791a8SRory Sexton if (diff >= (pol->pkt.traffic_policy.max_max_packet_thresh)) { 250f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 251f14791a8SRory Sexton if (pol->core_share[count].status != 1) 252f14791a8SRory Sexton power_manager_scale_core_max( 253f14791a8SRory Sexton pol->core_share[count].pcpu); 254f14791a8SRory Sexton } 255f14791a8SRory Sexton } else if (diff >= (pol->pkt.traffic_policy.avg_max_packet_thresh)) { 256f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 257f14791a8SRory Sexton if (pol->core_share[count].status != 1) 258f14791a8SRory Sexton power_manager_scale_core_med( 259f14791a8SRory Sexton pol->core_share[count].pcpu); 260f14791a8SRory Sexton } 261f14791a8SRory Sexton } else if (diff < (pol->pkt.traffic_policy.avg_max_packet_thresh)) { 262f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 263f14791a8SRory Sexton if (pol->core_share[count].status != 1) 264f14791a8SRory Sexton power_manager_scale_core_min( 265f14791a8SRory Sexton pol->core_share[count].pcpu); 266f14791a8SRory Sexton } 267f14791a8SRory Sexton } 268f14791a8SRory Sexton } 269f14791a8SRory Sexton 270f14791a8SRory Sexton static void 271f14791a8SRory Sexton apply_time_profile(struct policy *pol) 272f14791a8SRory Sexton { 273f14791a8SRory Sexton 274f14791a8SRory Sexton int count, x; 275f14791a8SRory Sexton struct timeval tv; 276f14791a8SRory Sexton struct tm *ptm; 277f14791a8SRory Sexton char time_string[40]; 278f14791a8SRory Sexton 279f14791a8SRory Sexton /* Obtain the time of day, and convert it to a tm struct. */ 280f14791a8SRory Sexton gettimeofday(&tv, NULL); 281f14791a8SRory Sexton ptm = localtime(&tv.tv_sec); 282f14791a8SRory Sexton /* Format the date and time, down to a single second. */ 283f14791a8SRory Sexton strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", ptm); 284f14791a8SRory Sexton 285f14791a8SRory Sexton for (x = 0; x < HOURS; x++) { 286f14791a8SRory Sexton 287f14791a8SRory Sexton if (ptm->tm_hour == pol->pkt.timer_policy.busy_hours[x]) { 288f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 289f14791a8SRory Sexton if (pol->core_share[count].status != 1) { 290f14791a8SRory Sexton power_manager_scale_core_max( 291f14791a8SRory Sexton pol->core_share[count].pcpu); 292f14791a8SRory Sexton RTE_LOG(INFO, CHANNEL_MONITOR, 293f14791a8SRory Sexton "Scaling up core %d to max\n", 294f14791a8SRory Sexton pol->core_share[count].pcpu); 295f14791a8SRory Sexton } 296f14791a8SRory Sexton } 297f14791a8SRory Sexton break; 298f14791a8SRory Sexton } else if (ptm->tm_hour == 299f14791a8SRory Sexton pol->pkt.timer_policy.quiet_hours[x]) { 300f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 301f14791a8SRory Sexton if (pol->core_share[count].status != 1) { 302f14791a8SRory Sexton power_manager_scale_core_min( 303f14791a8SRory Sexton pol->core_share[count].pcpu); 304f14791a8SRory Sexton RTE_LOG(INFO, CHANNEL_MONITOR, 305f14791a8SRory Sexton "Scaling down core %d to min\n", 306f14791a8SRory Sexton pol->core_share[count].pcpu); 307f14791a8SRory Sexton } 308f14791a8SRory Sexton } 309f14791a8SRory Sexton break; 310f14791a8SRory Sexton } else if (ptm->tm_hour == 311f14791a8SRory Sexton pol->pkt.timer_policy.hours_to_use_traffic_profile[x]) { 312f14791a8SRory Sexton apply_traffic_profile(pol); 313f14791a8SRory Sexton break; 314f14791a8SRory Sexton } 315f14791a8SRory Sexton } 316f14791a8SRory Sexton } 317f14791a8SRory Sexton 318f14791a8SRory Sexton static void 319f14791a8SRory Sexton apply_workload_profile(struct policy *pol) 320f14791a8SRory Sexton { 321f14791a8SRory Sexton 322f14791a8SRory Sexton int count; 323f14791a8SRory Sexton 324f14791a8SRory Sexton if (pol->pkt.workload == HIGH) { 325f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 326f14791a8SRory Sexton if (pol->core_share[count].status != 1) 327f14791a8SRory Sexton power_manager_scale_core_max( 328f14791a8SRory Sexton pol->core_share[count].pcpu); 329f14791a8SRory Sexton } 330f14791a8SRory Sexton } else if (pol->pkt.workload == MEDIUM) { 331f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 332f14791a8SRory Sexton if (pol->core_share[count].status != 1) 333f14791a8SRory Sexton power_manager_scale_core_med( 334f14791a8SRory Sexton pol->core_share[count].pcpu); 335f14791a8SRory Sexton } 336f14791a8SRory Sexton } else if (pol->pkt.workload == LOW) { 337f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 338f14791a8SRory Sexton if (pol->core_share[count].status != 1) 339f14791a8SRory Sexton power_manager_scale_core_min( 340f14791a8SRory Sexton pol->core_share[count].pcpu); 341f14791a8SRory Sexton } 342f14791a8SRory Sexton } 343f14791a8SRory Sexton } 344f14791a8SRory Sexton 345f14791a8SRory Sexton static void 346f14791a8SRory Sexton apply_policy(struct policy *pol) 347f14791a8SRory Sexton { 348f14791a8SRory Sexton 349f14791a8SRory Sexton struct channel_packet *pkt = &pol->pkt; 350f14791a8SRory Sexton 351f14791a8SRory Sexton /*Check policy to use*/ 352f14791a8SRory Sexton if (pkt->policy_to_use == TRAFFIC) 353f14791a8SRory Sexton apply_traffic_profile(pol); 354f14791a8SRory Sexton else if (pkt->policy_to_use == TIME) 355f14791a8SRory Sexton apply_time_profile(pol); 356f14791a8SRory Sexton else if (pkt->policy_to_use == WORKLOAD) 357f14791a8SRory Sexton apply_workload_profile(pol); 358f14791a8SRory Sexton } 359f14791a8SRory Sexton 360f14791a8SRory Sexton 361e8ae9b66SAlan Carew static int 362e8ae9b66SAlan Carew process_request(struct channel_packet *pkt, struct channel_info *chan_info) 363e8ae9b66SAlan Carew { 364e8ae9b66SAlan Carew uint64_t core_mask; 365e8ae9b66SAlan Carew 366e8ae9b66SAlan Carew if (chan_info == NULL) 367e8ae9b66SAlan Carew return -1; 368e8ae9b66SAlan Carew 369e8ae9b66SAlan Carew if (rte_atomic32_cmpset(&(chan_info->status), CHANNEL_MGR_CHANNEL_CONNECTED, 370e8ae9b66SAlan Carew CHANNEL_MGR_CHANNEL_PROCESSING) == 0) 371e8ae9b66SAlan Carew return -1; 372e8ae9b66SAlan Carew 373e8ae9b66SAlan Carew if (pkt->command == CPU_POWER) { 374e8ae9b66SAlan Carew core_mask = get_pcpus_mask(chan_info, pkt->resource_id); 375e8ae9b66SAlan Carew if (core_mask == 0) { 376e8ae9b66SAlan Carew RTE_LOG(ERR, CHANNEL_MONITOR, "Error get physical CPU mask for " 377e8ae9b66SAlan Carew "channel '%s' using vCPU(%u)\n", chan_info->channel_path, 378e8ae9b66SAlan Carew (unsigned)pkt->unit); 379e8ae9b66SAlan Carew return -1; 380e8ae9b66SAlan Carew } 381e8ae9b66SAlan Carew if (__builtin_popcountll(core_mask) == 1) { 382e8ae9b66SAlan Carew 383e8ae9b66SAlan Carew unsigned core_num = __builtin_ffsll(core_mask) - 1; 384e8ae9b66SAlan Carew 385e8ae9b66SAlan Carew switch (pkt->unit) { 386e8ae9b66SAlan Carew case(CPU_POWER_SCALE_MIN): 387e8ae9b66SAlan Carew power_manager_scale_core_min(core_num); 388e8ae9b66SAlan Carew break; 389e8ae9b66SAlan Carew case(CPU_POWER_SCALE_MAX): 390e8ae9b66SAlan Carew power_manager_scale_core_max(core_num); 391e8ae9b66SAlan Carew break; 392e8ae9b66SAlan Carew case(CPU_POWER_SCALE_DOWN): 393e8ae9b66SAlan Carew power_manager_scale_core_down(core_num); 394e8ae9b66SAlan Carew break; 395e8ae9b66SAlan Carew case(CPU_POWER_SCALE_UP): 396e8ae9b66SAlan Carew power_manager_scale_core_up(core_num); 397e8ae9b66SAlan Carew break; 398567997b9SDavid Hunt case(CPU_POWER_ENABLE_TURBO): 399567997b9SDavid Hunt power_manager_enable_turbo_core(core_num); 400567997b9SDavid Hunt break; 401567997b9SDavid Hunt case(CPU_POWER_DISABLE_TURBO): 402567997b9SDavid Hunt power_manager_disable_turbo_core(core_num); 403567997b9SDavid Hunt break; 404e8ae9b66SAlan Carew default: 405e8ae9b66SAlan Carew break; 406e8ae9b66SAlan Carew } 407e8ae9b66SAlan Carew } else { 408e8ae9b66SAlan Carew switch (pkt->unit) { 409e8ae9b66SAlan Carew case(CPU_POWER_SCALE_MIN): 410e8ae9b66SAlan Carew power_manager_scale_mask_min(core_mask); 411e8ae9b66SAlan Carew break; 412e8ae9b66SAlan Carew case(CPU_POWER_SCALE_MAX): 413e8ae9b66SAlan Carew power_manager_scale_mask_max(core_mask); 414e8ae9b66SAlan Carew break; 415e8ae9b66SAlan Carew case(CPU_POWER_SCALE_DOWN): 416e8ae9b66SAlan Carew power_manager_scale_mask_down(core_mask); 417e8ae9b66SAlan Carew break; 418e8ae9b66SAlan Carew case(CPU_POWER_SCALE_UP): 419e8ae9b66SAlan Carew power_manager_scale_mask_up(core_mask); 420e8ae9b66SAlan Carew break; 421567997b9SDavid Hunt case(CPU_POWER_ENABLE_TURBO): 422567997b9SDavid Hunt power_manager_enable_turbo_mask(core_mask); 423567997b9SDavid Hunt break; 424567997b9SDavid Hunt case(CPU_POWER_DISABLE_TURBO): 425567997b9SDavid Hunt power_manager_disable_turbo_mask(core_mask); 426567997b9SDavid Hunt break; 427e8ae9b66SAlan Carew default: 428e8ae9b66SAlan Carew break; 429e8ae9b66SAlan Carew } 430e8ae9b66SAlan Carew 431e8ae9b66SAlan Carew } 432e8ae9b66SAlan Carew } 433f14791a8SRory Sexton 434f14791a8SRory Sexton if (pkt->command == PKT_POLICY) { 435f14791a8SRory Sexton RTE_LOG(INFO, CHANNEL_MONITOR, "\nProcessing Policy request from Guest\n"); 436f14791a8SRory Sexton update_policy(pkt); 437f14791a8SRory Sexton policy_is_set = 1; 438f14791a8SRory Sexton } 439f14791a8SRory Sexton 440e8ae9b66SAlan Carew /* Return is not checked as channel status may have been set to DISABLED 441e8ae9b66SAlan Carew * from management thread 442e8ae9b66SAlan Carew */ 443e8ae9b66SAlan Carew rte_atomic32_cmpset(&(chan_info->status), CHANNEL_MGR_CHANNEL_PROCESSING, 444e8ae9b66SAlan Carew CHANNEL_MGR_CHANNEL_CONNECTED); 445e8ae9b66SAlan Carew return 0; 446e8ae9b66SAlan Carew 447e8ae9b66SAlan Carew } 448e8ae9b66SAlan Carew 449e8ae9b66SAlan Carew int 450e8ae9b66SAlan Carew add_channel_to_monitor(struct channel_info **chan_info) 451e8ae9b66SAlan Carew { 452e8ae9b66SAlan Carew struct channel_info *info = *chan_info; 453e8ae9b66SAlan Carew struct epoll_event event; 454e8ae9b66SAlan Carew 455e8ae9b66SAlan Carew event.events = EPOLLIN; 456e8ae9b66SAlan Carew event.data.ptr = info; 457e8ae9b66SAlan Carew if (epoll_ctl(global_event_fd, EPOLL_CTL_ADD, info->fd, &event) < 0) { 458e8ae9b66SAlan Carew RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to add channel '%s' " 459e8ae9b66SAlan Carew "to epoll\n", info->channel_path); 460e8ae9b66SAlan Carew return -1; 461e8ae9b66SAlan Carew } 462e8ae9b66SAlan Carew return 0; 463e8ae9b66SAlan Carew } 464e8ae9b66SAlan Carew 465e8ae9b66SAlan Carew int 466e8ae9b66SAlan Carew remove_channel_from_monitor(struct channel_info *chan_info) 467e8ae9b66SAlan Carew { 468e8ae9b66SAlan Carew if (epoll_ctl(global_event_fd, EPOLL_CTL_DEL, chan_info->fd, NULL) < 0) { 469e8ae9b66SAlan Carew RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to remove channel '%s' " 470e8ae9b66SAlan Carew "from epoll\n", chan_info->channel_path); 471e8ae9b66SAlan Carew return -1; 472e8ae9b66SAlan Carew } 473e8ae9b66SAlan Carew return 0; 474e8ae9b66SAlan Carew } 475e8ae9b66SAlan Carew 476e8ae9b66SAlan Carew int 477e8ae9b66SAlan Carew channel_monitor_init(void) 478e8ae9b66SAlan Carew { 479e8ae9b66SAlan Carew global_event_fd = epoll_create1(0); 480e8ae9b66SAlan Carew if (global_event_fd == 0) { 481e8ae9b66SAlan Carew RTE_LOG(ERR, CHANNEL_MONITOR, "Error creating epoll context with " 482e8ae9b66SAlan Carew "error %s\n", strerror(errno)); 483e8ae9b66SAlan Carew return -1; 484e8ae9b66SAlan Carew } 485e8ae9b66SAlan Carew global_events_list = rte_malloc("epoll_events", sizeof(*global_events_list) 486fdf20fa7SSergio Gonzalez Monroy * MAX_EVENTS, RTE_CACHE_LINE_SIZE); 487e8ae9b66SAlan Carew if (global_events_list == NULL) { 488e8ae9b66SAlan Carew RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to rte_malloc for " 489e8ae9b66SAlan Carew "epoll events\n"); 490e8ae9b66SAlan Carew return -1; 491e8ae9b66SAlan Carew } 492e8ae9b66SAlan Carew return 0; 493e8ae9b66SAlan Carew } 494e8ae9b66SAlan Carew 495e8ae9b66SAlan Carew void 496e8ae9b66SAlan Carew run_channel_monitor(void) 497e8ae9b66SAlan Carew { 498e8ae9b66SAlan Carew while (run_loop) { 499e8ae9b66SAlan Carew int n_events, i; 500e8ae9b66SAlan Carew 501e8ae9b66SAlan Carew n_events = epoll_wait(global_event_fd, global_events_list, 502e8ae9b66SAlan Carew MAX_EVENTS, 1); 503e8ae9b66SAlan Carew if (!run_loop) 504e8ae9b66SAlan Carew break; 505e8ae9b66SAlan Carew for (i = 0; i < n_events; i++) { 506e8ae9b66SAlan Carew struct channel_info *chan_info = (struct channel_info *) 507e8ae9b66SAlan Carew global_events_list[i].data.ptr; 508e8ae9b66SAlan Carew if ((global_events_list[i].events & EPOLLERR) || 509e8ae9b66SAlan Carew (global_events_list[i].events & EPOLLHUP)) { 510e8ae9b66SAlan Carew RTE_LOG(DEBUG, CHANNEL_MONITOR, "Remote closed connection for " 511f14791a8SRory Sexton "channel '%s'\n", 512f14791a8SRory Sexton chan_info->channel_path); 513e8ae9b66SAlan Carew remove_channel(&chan_info); 514e8ae9b66SAlan Carew continue; 515e8ae9b66SAlan Carew } 516e8ae9b66SAlan Carew if (global_events_list[i].events & EPOLLIN) { 517e8ae9b66SAlan Carew 518e8ae9b66SAlan Carew int n_bytes, err = 0; 519e8ae9b66SAlan Carew struct channel_packet pkt; 520e8ae9b66SAlan Carew void *buffer = &pkt; 521e8ae9b66SAlan Carew int buffer_len = sizeof(pkt); 522e8ae9b66SAlan Carew 523e8ae9b66SAlan Carew while (buffer_len > 0) { 524f14791a8SRory Sexton n_bytes = read(chan_info->fd, 525f14791a8SRory Sexton buffer, buffer_len); 526e8ae9b66SAlan Carew if (n_bytes == buffer_len) 527e8ae9b66SAlan Carew break; 528e8ae9b66SAlan Carew if (n_bytes == -1) { 529e8ae9b66SAlan Carew err = errno; 530f14791a8SRory Sexton RTE_LOG(DEBUG, CHANNEL_MONITOR, 531f14791a8SRory Sexton "Received error on " 532e8ae9b66SAlan Carew "channel '%s' read: %s\n", 533f14791a8SRory Sexton chan_info->channel_path, 534f14791a8SRory Sexton strerror(err)); 535e8ae9b66SAlan Carew remove_channel(&chan_info); 536e8ae9b66SAlan Carew break; 537e8ae9b66SAlan Carew } 538e8ae9b66SAlan Carew buffer = (char *)buffer + n_bytes; 539e8ae9b66SAlan Carew buffer_len -= n_bytes; 540e8ae9b66SAlan Carew } 541e8ae9b66SAlan Carew if (!err) 542e8ae9b66SAlan Carew process_request(&pkt, chan_info); 543e8ae9b66SAlan Carew } 544e8ae9b66SAlan Carew } 545f14791a8SRory Sexton rte_delay_us(time_period_s*1000000); 546f14791a8SRory Sexton if (policy_is_set) { 547*7abd801fSDavid Hunt int j; 548*7abd801fSDavid Hunt 549*7abd801fSDavid Hunt for (j = 0; j < MAX_VMS; j++) { 550f14791a8SRory Sexton if (policies[j].enabled == 1) 551f14791a8SRory Sexton apply_policy(&policies[j]); 552f14791a8SRory Sexton } 553f14791a8SRory Sexton } 554e8ae9b66SAlan Carew } 555e8ae9b66SAlan Carew } 556