13998e2a0SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 23998e2a0SBruce Richardson * Copyright(c) 2010-2014 Intel Corporation 3e8ae9b66SAlan Carew */ 4e8ae9b66SAlan Carew 5e8ae9b66SAlan Carew #include <unistd.h> 6e8ae9b66SAlan Carew #include <stdio.h> 7e8ae9b66SAlan Carew #include <stdlib.h> 8e8ae9b66SAlan Carew #include <stdint.h> 9e8ae9b66SAlan Carew #include <signal.h> 10e8ae9b66SAlan Carew #include <errno.h> 11e8ae9b66SAlan Carew #include <string.h> 12a63504a9SDavid Hunt #include <fcntl.h> 13e8ae9b66SAlan Carew #include <sys/types.h> 14e8ae9b66SAlan Carew #include <sys/epoll.h> 15e8ae9b66SAlan Carew #include <sys/queue.h> 16f14791a8SRory Sexton #include <sys/time.h> 17a63504a9SDavid Hunt #include <sys/socket.h> 18a63504a9SDavid Hunt #include <sys/select.h> 19a63504a9SDavid Hunt #ifdef USE_JANSSON 20a63504a9SDavid Hunt #include <jansson.h> 21a63504a9SDavid Hunt #else 22a63504a9SDavid Hunt #pragma message "Jansson dev libs unavailable, not including JSON parsing" 23a63504a9SDavid Hunt #endif 24e8ae9b66SAlan Carew #include <rte_log.h> 25e8ae9b66SAlan Carew #include <rte_memory.h> 26e8ae9b66SAlan Carew #include <rte_malloc.h> 27e8ae9b66SAlan Carew #include <rte_atomic.h> 28f14791a8SRory Sexton #include <rte_cycles.h> 29f14791a8SRory Sexton #include <rte_ethdev.h> 30f14791a8SRory Sexton #include <rte_pmd_i40e.h> 31e8ae9b66SAlan Carew 32f14791a8SRory Sexton #include <libvirt/libvirt.h> 33e8ae9b66SAlan Carew #include "channel_monitor.h" 34e8ae9b66SAlan Carew #include "channel_commands.h" 35e8ae9b66SAlan Carew #include "channel_manager.h" 36e8ae9b66SAlan Carew #include "power_manager.h" 37b89168efSDavid Hunt #include "oob_monitor.h" 38e8ae9b66SAlan Carew 39e8ae9b66SAlan Carew #define RTE_LOGTYPE_CHANNEL_MONITOR RTE_LOGTYPE_USER1 40e8ae9b66SAlan Carew 41e8ae9b66SAlan Carew #define MAX_EVENTS 256 42e8ae9b66SAlan Carew 43f14791a8SRory Sexton uint64_t vsi_pkt_count_prev[384]; 44f14791a8SRory Sexton uint64_t rdtsc_prev[384]; 45a63504a9SDavid Hunt #define MAX_JSON_STRING_LEN 1024 46a63504a9SDavid Hunt char json_data[MAX_JSON_STRING_LEN]; 47e8ae9b66SAlan Carew 48e4f66da3SDavid Hunt double time_period_ms = 1; 49e8ae9b66SAlan Carew static volatile unsigned run_loop = 1; 50e8ae9b66SAlan Carew static int global_event_fd; 51f14791a8SRory Sexton static unsigned int policy_is_set; 52e8ae9b66SAlan Carew static struct epoll_event *global_events_list; 5390a774c4SDavid Hunt static struct policy policies[MAX_CLIENTS]; 54e8ae9b66SAlan Carew 55a63504a9SDavid Hunt #ifdef USE_JANSSON 56a63504a9SDavid Hunt 57a63504a9SDavid Hunt union PFID { 58a63504a9SDavid Hunt struct ether_addr addr; 59a63504a9SDavid Hunt uint64_t pfid; 60a63504a9SDavid Hunt }; 61a63504a9SDavid Hunt 62a63504a9SDavid Hunt static int 63a63504a9SDavid Hunt str_to_ether_addr(const char *a, struct ether_addr *ether_addr) 64a63504a9SDavid Hunt { 65a63504a9SDavid Hunt int i; 66a63504a9SDavid Hunt char *end; 67a63504a9SDavid Hunt unsigned long o[ETHER_ADDR_LEN]; 68a63504a9SDavid Hunt 69a63504a9SDavid Hunt i = 0; 70a63504a9SDavid Hunt do { 71a63504a9SDavid Hunt errno = 0; 72a63504a9SDavid Hunt o[i] = strtoul(a, &end, 16); 73a63504a9SDavid Hunt if (errno != 0 || end == a || (end[0] != ':' && end[0] != 0)) 74a63504a9SDavid Hunt return -1; 75a63504a9SDavid Hunt a = end + 1; 76a63504a9SDavid Hunt } while (++i != RTE_DIM(o) / sizeof(o[0]) && end[0] != 0); 77a63504a9SDavid Hunt 78a63504a9SDavid Hunt /* Junk at the end of line */ 79a63504a9SDavid Hunt if (end[0] != 0) 80a63504a9SDavid Hunt return -1; 81a63504a9SDavid Hunt 82a63504a9SDavid Hunt /* Support the format XX:XX:XX:XX:XX:XX */ 83a63504a9SDavid Hunt if (i == ETHER_ADDR_LEN) { 84a63504a9SDavid Hunt while (i-- != 0) { 85a63504a9SDavid Hunt if (o[i] > UINT8_MAX) 86a63504a9SDavid Hunt return -1; 87a63504a9SDavid Hunt ether_addr->addr_bytes[i] = (uint8_t)o[i]; 88a63504a9SDavid Hunt } 89a63504a9SDavid Hunt /* Support the format XXXX:XXXX:XXXX */ 90a63504a9SDavid Hunt } else if (i == ETHER_ADDR_LEN / 2) { 91a63504a9SDavid Hunt while (i-- != 0) { 92a63504a9SDavid Hunt if (o[i] > UINT16_MAX) 93a63504a9SDavid Hunt return -1; 94a63504a9SDavid Hunt ether_addr->addr_bytes[i * 2] = 95a63504a9SDavid Hunt (uint8_t)(o[i] >> 8); 96a63504a9SDavid Hunt ether_addr->addr_bytes[i * 2 + 1] = 97a63504a9SDavid Hunt (uint8_t)(o[i] & 0xff); 98a63504a9SDavid Hunt } 99a63504a9SDavid Hunt /* unknown format */ 100a63504a9SDavid Hunt } else 101a63504a9SDavid Hunt return -1; 102a63504a9SDavid Hunt 103a63504a9SDavid Hunt return 0; 104a63504a9SDavid Hunt } 105a63504a9SDavid Hunt 106a63504a9SDavid Hunt static int 107a63504a9SDavid Hunt set_policy_mac(struct channel_packet *pkt, int idx, char *mac) 108a63504a9SDavid Hunt { 109a63504a9SDavid Hunt union PFID pfid; 110a63504a9SDavid Hunt int ret; 111a63504a9SDavid Hunt 112a63504a9SDavid Hunt /* Use port MAC address as the vfid */ 113a63504a9SDavid Hunt ret = str_to_ether_addr(mac, &pfid.addr); 114a63504a9SDavid Hunt 115a63504a9SDavid Hunt if (ret != 0) { 116a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 117a63504a9SDavid Hunt "Invalid mac address received in JSON\n"); 118a63504a9SDavid Hunt pkt->vfid[idx] = 0; 119a63504a9SDavid Hunt return -1; 120a63504a9SDavid Hunt } 121a63504a9SDavid Hunt 122a63504a9SDavid Hunt printf("Received MAC Address: %02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 ":" 123a63504a9SDavid Hunt "%02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 "\n", 124a63504a9SDavid Hunt pfid.addr.addr_bytes[0], pfid.addr.addr_bytes[1], 125a63504a9SDavid Hunt pfid.addr.addr_bytes[2], pfid.addr.addr_bytes[3], 126a63504a9SDavid Hunt pfid.addr.addr_bytes[4], pfid.addr.addr_bytes[5]); 127a63504a9SDavid Hunt 128a63504a9SDavid Hunt pkt->vfid[idx] = pfid.pfid; 129a63504a9SDavid Hunt return 0; 130a63504a9SDavid Hunt } 131a63504a9SDavid Hunt 132a63504a9SDavid Hunt 133a63504a9SDavid Hunt static int 134a63504a9SDavid Hunt parse_json_to_pkt(json_t *element, struct channel_packet *pkt) 135a63504a9SDavid Hunt { 136a63504a9SDavid Hunt const char *key; 137a63504a9SDavid Hunt json_t *value; 138a63504a9SDavid Hunt int ret; 139a63504a9SDavid Hunt 140a63504a9SDavid Hunt memset(pkt, 0, sizeof(struct channel_packet)); 141a63504a9SDavid Hunt 142a63504a9SDavid Hunt pkt->nb_mac_to_monitor = 0; 143a63504a9SDavid Hunt pkt->t_boost_status.tbEnabled = false; 144a63504a9SDavid Hunt pkt->workload = LOW; 145a63504a9SDavid Hunt pkt->policy_to_use = TIME; 146a63504a9SDavid Hunt pkt->command = PKT_POLICY; 147a63504a9SDavid Hunt pkt->core_type = CORE_TYPE_PHYSICAL; 148a63504a9SDavid Hunt 149a63504a9SDavid Hunt json_object_foreach(element, key, value) { 150a63504a9SDavid Hunt if (!strcmp(key, "policy")) { 151a63504a9SDavid Hunt /* Recurse in to get the contents of profile */ 152a63504a9SDavid Hunt ret = parse_json_to_pkt(value, pkt); 153a63504a9SDavid Hunt if (ret) 154a63504a9SDavid Hunt return ret; 155a63504a9SDavid Hunt } else if (!strcmp(key, "instruction")) { 156a63504a9SDavid Hunt /* Recurse in to get the contents of instruction */ 157a63504a9SDavid Hunt ret = parse_json_to_pkt(value, pkt); 158a63504a9SDavid Hunt if (ret) 159a63504a9SDavid Hunt return ret; 160a63504a9SDavid Hunt } else if (!strcmp(key, "name")) { 161a63504a9SDavid Hunt strcpy(pkt->vm_name, json_string_value(value)); 162a63504a9SDavid Hunt } else if (!strcmp(key, "command")) { 163a63504a9SDavid Hunt char command[32]; 164a63504a9SDavid Hunt snprintf(command, 32, "%s", json_string_value(value)); 165a63504a9SDavid Hunt if (!strcmp(command, "power")) { 166a63504a9SDavid Hunt pkt->command = CPU_POWER; 167a63504a9SDavid Hunt } else if (!strcmp(command, "create")) { 168a63504a9SDavid Hunt pkt->command = PKT_POLICY; 169a63504a9SDavid Hunt } else if (!strcmp(command, "destroy")) { 170a63504a9SDavid Hunt pkt->command = PKT_POLICY_REMOVE; 171a63504a9SDavid Hunt } else { 172a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 173a63504a9SDavid Hunt "Invalid command received in JSON\n"); 174a63504a9SDavid Hunt return -1; 175a63504a9SDavid Hunt } 176a63504a9SDavid Hunt } else if (!strcmp(key, "policy_type")) { 177a63504a9SDavid Hunt char command[32]; 178a63504a9SDavid Hunt snprintf(command, 32, "%s", json_string_value(value)); 179a63504a9SDavid Hunt if (!strcmp(command, "TIME")) { 180a63504a9SDavid Hunt pkt->policy_to_use = TIME; 181a63504a9SDavid Hunt } else if (!strcmp(command, "TRAFFIC")) { 182a63504a9SDavid Hunt pkt->policy_to_use = TRAFFIC; 183a63504a9SDavid Hunt } else if (!strcmp(command, "WORKLOAD")) { 184a63504a9SDavid Hunt pkt->policy_to_use = WORKLOAD; 185a63504a9SDavid Hunt } else if (!strcmp(command, "BRANCH_RATIO")) { 186a63504a9SDavid Hunt pkt->policy_to_use = BRANCH_RATIO; 187a63504a9SDavid Hunt } else { 188a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 189a63504a9SDavid Hunt "Wrong policy_type received in JSON\n"); 190a63504a9SDavid Hunt return -1; 191a63504a9SDavid Hunt } 192a63504a9SDavid Hunt } else if (!strcmp(key, "workload")) { 193a63504a9SDavid Hunt char command[32]; 194a63504a9SDavid Hunt snprintf(command, 32, "%s", json_string_value(value)); 195a63504a9SDavid Hunt if (!strcmp(command, "HIGH")) { 196a63504a9SDavid Hunt pkt->workload = HIGH; 197a63504a9SDavid Hunt } else if (!strcmp(command, "MEDIUM")) { 198a63504a9SDavid Hunt pkt->workload = MEDIUM; 199a63504a9SDavid Hunt } else if (!strcmp(command, "LOW")) { 200a63504a9SDavid Hunt pkt->workload = LOW; 201a63504a9SDavid Hunt } else { 202a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 203a63504a9SDavid Hunt "Wrong workload received in JSON\n"); 204a63504a9SDavid Hunt return -1; 205a63504a9SDavid Hunt } 206a63504a9SDavid Hunt } else if (!strcmp(key, "busy_hours")) { 207a63504a9SDavid Hunt unsigned int i; 208a63504a9SDavid Hunt size_t size = json_array_size(value); 209a63504a9SDavid Hunt 210a63504a9SDavid Hunt for (i = 0; i < size; i++) { 211a63504a9SDavid Hunt int hour = (int)json_integer_value( 212a63504a9SDavid Hunt json_array_get(value, i)); 213a63504a9SDavid Hunt pkt->timer_policy.busy_hours[i] = hour; 214a63504a9SDavid Hunt } 215a63504a9SDavid Hunt } else if (!strcmp(key, "quiet_hours")) { 216a63504a9SDavid Hunt unsigned int i; 217a63504a9SDavid Hunt size_t size = json_array_size(value); 218a63504a9SDavid Hunt 219a63504a9SDavid Hunt for (i = 0; i < size; i++) { 220a63504a9SDavid Hunt int hour = (int)json_integer_value( 221a63504a9SDavid Hunt json_array_get(value, i)); 222a63504a9SDavid Hunt pkt->timer_policy.quiet_hours[i] = hour; 223a63504a9SDavid Hunt } 224a63504a9SDavid Hunt } else if (!strcmp(key, "core_list")) { 225a63504a9SDavid Hunt unsigned int i; 226a63504a9SDavid Hunt size_t size = json_array_size(value); 227a63504a9SDavid Hunt 228a63504a9SDavid Hunt for (i = 0; i < size; i++) { 229a63504a9SDavid Hunt int core = (int)json_integer_value( 230a63504a9SDavid Hunt json_array_get(value, i)); 231a63504a9SDavid Hunt pkt->vcpu_to_control[i] = core; 232a63504a9SDavid Hunt } 233a63504a9SDavid Hunt pkt->num_vcpu = size; 234a63504a9SDavid Hunt } else if (!strcmp(key, "mac_list")) { 235a63504a9SDavid Hunt unsigned int i; 236a63504a9SDavid Hunt size_t size = json_array_size(value); 237a63504a9SDavid Hunt 238a63504a9SDavid Hunt for (i = 0; i < size; i++) { 239a63504a9SDavid Hunt char mac[32]; 240a63504a9SDavid Hunt snprintf(mac, 32, "%s", json_string_value( 241a63504a9SDavid Hunt json_array_get(value, i))); 242a63504a9SDavid Hunt set_policy_mac(pkt, i, mac); 243a63504a9SDavid Hunt } 244a63504a9SDavid Hunt pkt->nb_mac_to_monitor = size; 245a63504a9SDavid Hunt } else if (!strcmp(key, "avg_packet_thresh")) { 246a63504a9SDavid Hunt pkt->traffic_policy.avg_max_packet_thresh = 247a63504a9SDavid Hunt (uint32_t)json_integer_value(value); 248a63504a9SDavid Hunt } else if (!strcmp(key, "max_packet_thresh")) { 249a63504a9SDavid Hunt pkt->traffic_policy.max_max_packet_thresh = 250a63504a9SDavid Hunt (uint32_t)json_integer_value(value); 251a63504a9SDavid Hunt } else if (!strcmp(key, "unit")) { 252a63504a9SDavid Hunt char unit[32]; 253a63504a9SDavid Hunt snprintf(unit, 32, "%s", json_string_value(value)); 254a63504a9SDavid Hunt if (!strcmp(unit, "SCALE_UP")) { 255a63504a9SDavid Hunt pkt->unit = CPU_POWER_SCALE_UP; 256a63504a9SDavid Hunt } else if (!strcmp(unit, "SCALE_DOWN")) { 257a63504a9SDavid Hunt pkt->unit = CPU_POWER_SCALE_DOWN; 258a63504a9SDavid Hunt } else if (!strcmp(unit, "SCALE_MAX")) { 259a63504a9SDavid Hunt pkt->unit = CPU_POWER_SCALE_MAX; 260a63504a9SDavid Hunt } else if (!strcmp(unit, "SCALE_MIN")) { 261a63504a9SDavid Hunt pkt->unit = CPU_POWER_SCALE_MIN; 262a63504a9SDavid Hunt } else if (!strcmp(unit, "ENABLE_TURBO")) { 263a63504a9SDavid Hunt pkt->unit = CPU_POWER_ENABLE_TURBO; 264a63504a9SDavid Hunt } else if (!strcmp(unit, "DISABLE_TURBO")) { 265a63504a9SDavid Hunt pkt->unit = CPU_POWER_DISABLE_TURBO; 266a63504a9SDavid Hunt } else { 267a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 268a63504a9SDavid Hunt "Invalid command received in JSON\n"); 269a63504a9SDavid Hunt return -1; 270a63504a9SDavid Hunt } 271a63504a9SDavid Hunt } else if (!strcmp(key, "resource_id")) { 272a63504a9SDavid Hunt pkt->resource_id = (uint32_t)json_integer_value(value); 273a63504a9SDavid Hunt } else { 274a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 275a63504a9SDavid Hunt "Unknown key received in JSON string: %s\n", 276a63504a9SDavid Hunt key); 277a63504a9SDavid Hunt } 278a63504a9SDavid Hunt } 279a63504a9SDavid Hunt return 0; 280a63504a9SDavid Hunt } 281a63504a9SDavid Hunt #endif 282a63504a9SDavid Hunt 283e8ae9b66SAlan Carew void channel_monitor_exit(void) 284e8ae9b66SAlan Carew { 285e8ae9b66SAlan Carew run_loop = 0; 286e8ae9b66SAlan Carew rte_free(global_events_list); 287e8ae9b66SAlan Carew } 288e8ae9b66SAlan Carew 289f14791a8SRory Sexton static void 290f14791a8SRory Sexton core_share(int pNo, int z, int x, int t) 291f14791a8SRory Sexton { 292f14791a8SRory Sexton if (policies[pNo].core_share[z].pcpu == lvm_info[x].pcpus[t]) { 293f14791a8SRory Sexton if (strcmp(policies[pNo].pkt.vm_name, 294f14791a8SRory Sexton lvm_info[x].vm_name) != 0) { 295f14791a8SRory Sexton policies[pNo].core_share[z].status = 1; 296f14791a8SRory Sexton power_manager_scale_core_max( 297f14791a8SRory Sexton policies[pNo].core_share[z].pcpu); 298f14791a8SRory Sexton } 299f14791a8SRory Sexton } 300f14791a8SRory Sexton } 301f14791a8SRory Sexton 302f14791a8SRory Sexton static void 303f14791a8SRory Sexton core_share_status(int pNo) 304f14791a8SRory Sexton { 305f14791a8SRory Sexton 306395e97bfSDavid Hunt int noVms = 0, noVcpus = 0, z, x, t; 307f14791a8SRory Sexton 308f14791a8SRory Sexton get_all_vm(&noVms, &noVcpus); 309f14791a8SRory Sexton 310f14791a8SRory Sexton /* Reset Core Share Status. */ 311f14791a8SRory Sexton for (z = 0; z < noVcpus; z++) 312f14791a8SRory Sexton policies[pNo].core_share[z].status = 0; 313f14791a8SRory Sexton 314f14791a8SRory Sexton /* Foreach vcpu in a policy. */ 315f14791a8SRory Sexton for (z = 0; z < policies[pNo].pkt.num_vcpu; z++) { 316f14791a8SRory Sexton /* Foreach VM on the platform. */ 317f14791a8SRory Sexton for (x = 0; x < noVms; x++) { 318f14791a8SRory Sexton /* Foreach vcpu of VMs on platform. */ 319f14791a8SRory Sexton for (t = 0; t < lvm_info[x].num_cpus; t++) 320f14791a8SRory Sexton core_share(pNo, z, x, t); 321f14791a8SRory Sexton } 322f14791a8SRory Sexton } 323f14791a8SRory Sexton } 324f14791a8SRory Sexton 3253618326fSDavid Hunt 3263618326fSDavid Hunt static int 3273618326fSDavid Hunt pcpu_monitor(struct policy *pol, struct core_info *ci, int pcpu, int count) 3283618326fSDavid Hunt { 3293618326fSDavid Hunt int ret = 0; 3303618326fSDavid Hunt 3313618326fSDavid Hunt if (pol->pkt.policy_to_use == BRANCH_RATIO) { 3323618326fSDavid Hunt ci->cd[pcpu].oob_enabled = 1; 3333618326fSDavid Hunt ret = add_core_to_monitor(pcpu); 3343618326fSDavid Hunt if (ret == 0) 3353618326fSDavid Hunt RTE_LOG(INFO, CHANNEL_MONITOR, 3363618326fSDavid Hunt "Monitoring pcpu %d OOB for %s\n", 3373618326fSDavid Hunt pcpu, pol->pkt.vm_name); 3383618326fSDavid Hunt else 3393618326fSDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 3403618326fSDavid Hunt "Error monitoring pcpu %d OOB for %s\n", 3413618326fSDavid Hunt pcpu, pol->pkt.vm_name); 3423618326fSDavid Hunt 3433618326fSDavid Hunt } else { 3443618326fSDavid Hunt pol->core_share[count].pcpu = pcpu; 3453618326fSDavid Hunt RTE_LOG(INFO, CHANNEL_MONITOR, 3463618326fSDavid Hunt "Monitoring pcpu %d for %s\n", 3473618326fSDavid Hunt pcpu, pol->pkt.vm_name); 3483618326fSDavid Hunt } 3493618326fSDavid Hunt return ret; 3503618326fSDavid Hunt } 3513618326fSDavid Hunt 352f14791a8SRory Sexton static void 353f14791a8SRory Sexton get_pcpu_to_control(struct policy *pol) 354f14791a8SRory Sexton { 355f14791a8SRory Sexton 356f14791a8SRory Sexton /* Convert vcpu to pcpu. */ 357f14791a8SRory Sexton struct vm_info info; 358f14791a8SRory Sexton int pcpu, count; 359f14791a8SRory Sexton uint64_t mask_u64b; 360b89168efSDavid Hunt struct core_info *ci; 361b89168efSDavid Hunt 362b89168efSDavid Hunt ci = get_core_info(); 363f14791a8SRory Sexton 364*ce4a2766SDavid Hunt RTE_LOG(DEBUG, CHANNEL_MONITOR, 3653618326fSDavid Hunt "Looking for pcpu for %s\n", pol->pkt.vm_name); 3663618326fSDavid Hunt 3673618326fSDavid Hunt /* 3683618326fSDavid Hunt * So now that we're handling virtual and physical cores, we need to 3693618326fSDavid Hunt * differenciate between them when adding them to the branch monitor. 3703618326fSDavid Hunt * Virtual cores need to be converted to physical cores. 3713618326fSDavid Hunt */ 3723618326fSDavid Hunt if (pol->pkt.core_type == CORE_TYPE_VIRTUAL) { 3733618326fSDavid Hunt /* 3743618326fSDavid Hunt * If the cores in the policy are virtual, we need to map them 3753618326fSDavid Hunt * to physical core. We look up the vm info and use that for 3763618326fSDavid Hunt * the mapping. 3773618326fSDavid Hunt */ 378f14791a8SRory Sexton get_info_vm(pol->pkt.vm_name, &info); 379f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 3803618326fSDavid Hunt mask_u64b = 3813618326fSDavid Hunt info.pcpu_mask[pol->pkt.vcpu_to_control[count]]; 3823618326fSDavid Hunt for (pcpu = 0; mask_u64b; 3833618326fSDavid Hunt mask_u64b &= ~(1ULL << pcpu++)) { 3843618326fSDavid Hunt if ((mask_u64b >> pcpu) & 1) 3853618326fSDavid Hunt pcpu_monitor(pol, ci, pcpu, count); 3863618326fSDavid Hunt } 3873618326fSDavid Hunt } 388b89168efSDavid Hunt } else { 3893618326fSDavid Hunt /* 3903618326fSDavid Hunt * If the cores in the policy are physical, we just use 3913618326fSDavid Hunt * those core id's directly. 3923618326fSDavid Hunt */ 3933618326fSDavid Hunt for (count = 0; count < pol->pkt.num_vcpu; count++) { 3943618326fSDavid Hunt pcpu = pol->pkt.vcpu_to_control[count]; 3953618326fSDavid Hunt pcpu_monitor(pol, ci, pcpu, count); 396f14791a8SRory Sexton } 397f14791a8SRory Sexton } 398f14791a8SRory Sexton } 399f14791a8SRory Sexton 400f14791a8SRory Sexton static int 401f14791a8SRory Sexton get_pfid(struct policy *pol) 402f14791a8SRory Sexton { 403f14791a8SRory Sexton 4048728ccf3SThomas Monjalon int i, x, ret = 0; 405f14791a8SRory Sexton 406f14791a8SRory Sexton for (i = 0; i < pol->pkt.nb_mac_to_monitor; i++) { 407f14791a8SRory Sexton 4088728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(x) { 409f14791a8SRory Sexton ret = rte_pmd_i40e_query_vfid_by_mac(x, 410f14791a8SRory Sexton (struct ether_addr *)&(pol->pkt.vfid[i])); 411f14791a8SRory Sexton if (ret != -EINVAL) { 412f14791a8SRory Sexton pol->port[i] = x; 413f14791a8SRory Sexton break; 414f14791a8SRory Sexton } 415f14791a8SRory Sexton } 416f14791a8SRory Sexton if (ret == -EINVAL || ret == -ENOTSUP || ret == ENODEV) { 417f14791a8SRory Sexton RTE_LOG(INFO, CHANNEL_MONITOR, 418f14791a8SRory Sexton "Error with Policy. MAC not found on " 419f14791a8SRory Sexton "attached ports "); 420f14791a8SRory Sexton pol->enabled = 0; 421f14791a8SRory Sexton return ret; 422f14791a8SRory Sexton } 423f14791a8SRory Sexton pol->pfid[i] = ret; 424f14791a8SRory Sexton } 425f14791a8SRory Sexton return 1; 426f14791a8SRory Sexton } 427f14791a8SRory Sexton 428f14791a8SRory Sexton static int 429f14791a8SRory Sexton update_policy(struct channel_packet *pkt) 430f14791a8SRory Sexton { 431f14791a8SRory Sexton 432f14791a8SRory Sexton unsigned int updated = 0; 4337abd801fSDavid Hunt int i; 434f14791a8SRory Sexton 4353618326fSDavid Hunt 4363618326fSDavid Hunt RTE_LOG(INFO, CHANNEL_MONITOR, 4373618326fSDavid Hunt "Applying policy for %s\n", pkt->vm_name); 4383618326fSDavid Hunt 43990a774c4SDavid Hunt for (i = 0; i < MAX_CLIENTS; i++) { 440f14791a8SRory Sexton if (strcmp(policies[i].pkt.vm_name, pkt->vm_name) == 0) { 4413618326fSDavid Hunt /* Copy the contents of *pkt into the policy.pkt */ 442f14791a8SRory Sexton policies[i].pkt = *pkt; 443f14791a8SRory Sexton get_pcpu_to_control(&policies[i]); 444f14791a8SRory Sexton if (get_pfid(&policies[i]) == -1) { 445f14791a8SRory Sexton updated = 1; 446f14791a8SRory Sexton break; 447f14791a8SRory Sexton } 448f14791a8SRory Sexton core_share_status(i); 449f14791a8SRory Sexton policies[i].enabled = 1; 450f14791a8SRory Sexton updated = 1; 451f14791a8SRory Sexton } 452f14791a8SRory Sexton } 453f14791a8SRory Sexton if (!updated) { 45490a774c4SDavid Hunt for (i = 0; i < MAX_CLIENTS; i++) { 455f14791a8SRory Sexton if (policies[i].enabled == 0) { 456f14791a8SRory Sexton policies[i].pkt = *pkt; 457f14791a8SRory Sexton get_pcpu_to_control(&policies[i]); 458f14791a8SRory Sexton if (get_pfid(&policies[i]) == -1) 459f14791a8SRory Sexton break; 460f14791a8SRory Sexton core_share_status(i); 461f14791a8SRory Sexton policies[i].enabled = 1; 462f14791a8SRory Sexton break; 463f14791a8SRory Sexton } 464f14791a8SRory Sexton } 465f14791a8SRory Sexton } 466f14791a8SRory Sexton return 0; 467f14791a8SRory Sexton } 468f14791a8SRory Sexton 4693618326fSDavid Hunt static int 4703618326fSDavid Hunt remove_policy(struct channel_packet *pkt __rte_unused) 4713618326fSDavid Hunt { 4723618326fSDavid Hunt int i; 4733618326fSDavid Hunt 4743618326fSDavid Hunt /* 4753618326fSDavid Hunt * Disabling the policy is simply a case of setting 4763618326fSDavid Hunt * enabled to 0 4773618326fSDavid Hunt */ 47890a774c4SDavid Hunt for (i = 0; i < MAX_CLIENTS; i++) { 4793618326fSDavid Hunt if (strcmp(policies[i].pkt.vm_name, pkt->vm_name) == 0) { 4803618326fSDavid Hunt policies[i].enabled = 0; 4813618326fSDavid Hunt return 0; 4823618326fSDavid Hunt } 4833618326fSDavid Hunt } 4843618326fSDavid Hunt return -1; 4853618326fSDavid Hunt } 4863618326fSDavid Hunt 487f14791a8SRory Sexton static uint64_t 488f14791a8SRory Sexton get_pkt_diff(struct policy *pol) 489f14791a8SRory Sexton { 490f14791a8SRory Sexton 491f14791a8SRory Sexton uint64_t vsi_pkt_count, 492f14791a8SRory Sexton vsi_pkt_total = 0, 493f14791a8SRory Sexton vsi_pkt_count_prev_total = 0; 494f14791a8SRory Sexton double rdtsc_curr, rdtsc_diff, diff; 495f14791a8SRory Sexton int x; 496f14791a8SRory Sexton struct rte_eth_stats vf_stats; 497f14791a8SRory Sexton 498f14791a8SRory Sexton for (x = 0; x < pol->pkt.nb_mac_to_monitor; x++) { 499f14791a8SRory Sexton 500f14791a8SRory Sexton /*Read vsi stats*/ 501f14791a8SRory Sexton if (rte_pmd_i40e_get_vf_stats(x, pol->pfid[x], &vf_stats) == 0) 502f14791a8SRory Sexton vsi_pkt_count = vf_stats.ipackets; 503f14791a8SRory Sexton else 504f14791a8SRory Sexton vsi_pkt_count = -1; 505f14791a8SRory Sexton 506f14791a8SRory Sexton vsi_pkt_total += vsi_pkt_count; 507f14791a8SRory Sexton 508f14791a8SRory Sexton vsi_pkt_count_prev_total += vsi_pkt_count_prev[pol->pfid[x]]; 509f14791a8SRory Sexton vsi_pkt_count_prev[pol->pfid[x]] = vsi_pkt_count; 510f14791a8SRory Sexton } 511f14791a8SRory Sexton 512f14791a8SRory Sexton rdtsc_curr = rte_rdtsc_precise(); 513f14791a8SRory Sexton rdtsc_diff = rdtsc_curr - rdtsc_prev[pol->pfid[x-1]]; 514f14791a8SRory Sexton rdtsc_prev[pol->pfid[x-1]] = rdtsc_curr; 515f14791a8SRory Sexton 516f14791a8SRory Sexton diff = (vsi_pkt_total - vsi_pkt_count_prev_total) * 517f14791a8SRory Sexton ((double)rte_get_tsc_hz() / rdtsc_diff); 518f14791a8SRory Sexton 519f14791a8SRory Sexton return diff; 520f14791a8SRory Sexton } 521f14791a8SRory Sexton 522f14791a8SRory Sexton static void 523f14791a8SRory Sexton apply_traffic_profile(struct policy *pol) 524f14791a8SRory Sexton { 525f14791a8SRory Sexton 526f14791a8SRory Sexton int count; 527f14791a8SRory Sexton uint64_t diff = 0; 528f14791a8SRory Sexton 529f14791a8SRory Sexton diff = get_pkt_diff(pol); 530f14791a8SRory Sexton 531f14791a8SRory Sexton if (diff >= (pol->pkt.traffic_policy.max_max_packet_thresh)) { 532f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 533f14791a8SRory Sexton if (pol->core_share[count].status != 1) 534f14791a8SRory Sexton power_manager_scale_core_max( 535f14791a8SRory Sexton pol->core_share[count].pcpu); 536f14791a8SRory Sexton } 537f14791a8SRory Sexton } else if (diff >= (pol->pkt.traffic_policy.avg_max_packet_thresh)) { 538f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 539f14791a8SRory Sexton if (pol->core_share[count].status != 1) 540f14791a8SRory Sexton power_manager_scale_core_med( 541f14791a8SRory Sexton pol->core_share[count].pcpu); 542f14791a8SRory Sexton } 543f14791a8SRory Sexton } else if (diff < (pol->pkt.traffic_policy.avg_max_packet_thresh)) { 544f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 545f14791a8SRory Sexton if (pol->core_share[count].status != 1) 546f14791a8SRory Sexton power_manager_scale_core_min( 547f14791a8SRory Sexton pol->core_share[count].pcpu); 548f14791a8SRory Sexton } 549f14791a8SRory Sexton } 550f14791a8SRory Sexton } 551f14791a8SRory Sexton 552f14791a8SRory Sexton static void 553f14791a8SRory Sexton apply_time_profile(struct policy *pol) 554f14791a8SRory Sexton { 555f14791a8SRory Sexton 556f14791a8SRory Sexton int count, x; 557f14791a8SRory Sexton struct timeval tv; 558f14791a8SRory Sexton struct tm *ptm; 559f14791a8SRory Sexton char time_string[40]; 560f14791a8SRory Sexton 561f14791a8SRory Sexton /* Obtain the time of day, and convert it to a tm struct. */ 562f14791a8SRory Sexton gettimeofday(&tv, NULL); 563f14791a8SRory Sexton ptm = localtime(&tv.tv_sec); 564f14791a8SRory Sexton /* Format the date and time, down to a single second. */ 565f14791a8SRory Sexton strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", ptm); 566f14791a8SRory Sexton 567f14791a8SRory Sexton for (x = 0; x < HOURS; x++) { 568f14791a8SRory Sexton 569f14791a8SRory Sexton if (ptm->tm_hour == pol->pkt.timer_policy.busy_hours[x]) { 570f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 571f14791a8SRory Sexton if (pol->core_share[count].status != 1) { 572f14791a8SRory Sexton power_manager_scale_core_max( 573f14791a8SRory Sexton pol->core_share[count].pcpu); 574f14791a8SRory Sexton } 575f14791a8SRory Sexton } 576f14791a8SRory Sexton break; 577f14791a8SRory Sexton } else if (ptm->tm_hour == 578f14791a8SRory Sexton pol->pkt.timer_policy.quiet_hours[x]) { 579f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 580f14791a8SRory Sexton if (pol->core_share[count].status != 1) { 581f14791a8SRory Sexton power_manager_scale_core_min( 582f14791a8SRory Sexton pol->core_share[count].pcpu); 583f14791a8SRory Sexton } 584f14791a8SRory Sexton } 585f14791a8SRory Sexton break; 586f14791a8SRory Sexton } else if (ptm->tm_hour == 587f14791a8SRory Sexton pol->pkt.timer_policy.hours_to_use_traffic_profile[x]) { 588f14791a8SRory Sexton apply_traffic_profile(pol); 589f14791a8SRory Sexton break; 590f14791a8SRory Sexton } 591f14791a8SRory Sexton } 592f14791a8SRory Sexton } 593f14791a8SRory Sexton 594f14791a8SRory Sexton static void 595f14791a8SRory Sexton apply_workload_profile(struct policy *pol) 596f14791a8SRory Sexton { 597f14791a8SRory Sexton 598f14791a8SRory Sexton int count; 599f14791a8SRory Sexton 600f14791a8SRory Sexton if (pol->pkt.workload == HIGH) { 601f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 602f14791a8SRory Sexton if (pol->core_share[count].status != 1) 603f14791a8SRory Sexton power_manager_scale_core_max( 604f14791a8SRory Sexton pol->core_share[count].pcpu); 605f14791a8SRory Sexton } 606f14791a8SRory Sexton } else if (pol->pkt.workload == MEDIUM) { 607f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 608f14791a8SRory Sexton if (pol->core_share[count].status != 1) 609f14791a8SRory Sexton power_manager_scale_core_med( 610f14791a8SRory Sexton pol->core_share[count].pcpu); 611f14791a8SRory Sexton } 612f14791a8SRory Sexton } else if (pol->pkt.workload == LOW) { 613f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 614f14791a8SRory Sexton if (pol->core_share[count].status != 1) 615f14791a8SRory Sexton power_manager_scale_core_min( 616f14791a8SRory Sexton pol->core_share[count].pcpu); 617f14791a8SRory Sexton } 618f14791a8SRory Sexton } 619f14791a8SRory Sexton } 620f14791a8SRory Sexton 621f14791a8SRory Sexton static void 622f14791a8SRory Sexton apply_policy(struct policy *pol) 623f14791a8SRory Sexton { 624f14791a8SRory Sexton 625f14791a8SRory Sexton struct channel_packet *pkt = &pol->pkt; 626f14791a8SRory Sexton 627f14791a8SRory Sexton /*Check policy to use*/ 628f14791a8SRory Sexton if (pkt->policy_to_use == TRAFFIC) 629f14791a8SRory Sexton apply_traffic_profile(pol); 630f14791a8SRory Sexton else if (pkt->policy_to_use == TIME) 631f14791a8SRory Sexton apply_time_profile(pol); 632f14791a8SRory Sexton else if (pkt->policy_to_use == WORKLOAD) 633f14791a8SRory Sexton apply_workload_profile(pol); 634f14791a8SRory Sexton } 635f14791a8SRory Sexton 636e8ae9b66SAlan Carew static int 637e8ae9b66SAlan Carew process_request(struct channel_packet *pkt, struct channel_info *chan_info) 638e8ae9b66SAlan Carew { 639e8ae9b66SAlan Carew uint64_t core_mask; 640e8ae9b66SAlan Carew 641e8ae9b66SAlan Carew if (chan_info == NULL) 642e8ae9b66SAlan Carew return -1; 643e8ae9b66SAlan Carew 644e8ae9b66SAlan Carew if (rte_atomic32_cmpset(&(chan_info->status), CHANNEL_MGR_CHANNEL_CONNECTED, 645e8ae9b66SAlan Carew CHANNEL_MGR_CHANNEL_PROCESSING) == 0) 646e8ae9b66SAlan Carew return -1; 647e8ae9b66SAlan Carew 648e8ae9b66SAlan Carew if (pkt->command == CPU_POWER) { 649e8ae9b66SAlan Carew core_mask = get_pcpus_mask(chan_info, pkt->resource_id); 650e8ae9b66SAlan Carew if (core_mask == 0) { 6513618326fSDavid Hunt /* 6523618326fSDavid Hunt * Core mask will be 0 in the case where 6533618326fSDavid Hunt * hypervisor is not available so we're working in 6543618326fSDavid Hunt * the host, so use the core as the mask. 6553618326fSDavid Hunt */ 6563618326fSDavid Hunt core_mask = 1ULL << pkt->resource_id; 657e8ae9b66SAlan Carew } 658e8ae9b66SAlan Carew if (__builtin_popcountll(core_mask) == 1) { 659e8ae9b66SAlan Carew 660e8ae9b66SAlan Carew unsigned core_num = __builtin_ffsll(core_mask) - 1; 661e8ae9b66SAlan Carew 662e8ae9b66SAlan Carew switch (pkt->unit) { 663e8ae9b66SAlan Carew case(CPU_POWER_SCALE_MIN): 664e8ae9b66SAlan Carew power_manager_scale_core_min(core_num); 665e8ae9b66SAlan Carew break; 666e8ae9b66SAlan Carew case(CPU_POWER_SCALE_MAX): 667e8ae9b66SAlan Carew power_manager_scale_core_max(core_num); 668e8ae9b66SAlan Carew break; 669e8ae9b66SAlan Carew case(CPU_POWER_SCALE_DOWN): 670e8ae9b66SAlan Carew power_manager_scale_core_down(core_num); 671e8ae9b66SAlan Carew break; 672e8ae9b66SAlan Carew case(CPU_POWER_SCALE_UP): 673e8ae9b66SAlan Carew power_manager_scale_core_up(core_num); 674e8ae9b66SAlan Carew break; 675567997b9SDavid Hunt case(CPU_POWER_ENABLE_TURBO): 676567997b9SDavid Hunt power_manager_enable_turbo_core(core_num); 677567997b9SDavid Hunt break; 678567997b9SDavid Hunt case(CPU_POWER_DISABLE_TURBO): 679567997b9SDavid Hunt power_manager_disable_turbo_core(core_num); 680567997b9SDavid Hunt break; 681e8ae9b66SAlan Carew default: 682e8ae9b66SAlan Carew break; 683e8ae9b66SAlan Carew } 684e8ae9b66SAlan Carew } else { 685e8ae9b66SAlan Carew switch (pkt->unit) { 686e8ae9b66SAlan Carew case(CPU_POWER_SCALE_MIN): 687e8ae9b66SAlan Carew power_manager_scale_mask_min(core_mask); 688e8ae9b66SAlan Carew break; 689e8ae9b66SAlan Carew case(CPU_POWER_SCALE_MAX): 690e8ae9b66SAlan Carew power_manager_scale_mask_max(core_mask); 691e8ae9b66SAlan Carew break; 692e8ae9b66SAlan Carew case(CPU_POWER_SCALE_DOWN): 693e8ae9b66SAlan Carew power_manager_scale_mask_down(core_mask); 694e8ae9b66SAlan Carew break; 695e8ae9b66SAlan Carew case(CPU_POWER_SCALE_UP): 696e8ae9b66SAlan Carew power_manager_scale_mask_up(core_mask); 697e8ae9b66SAlan Carew break; 698567997b9SDavid Hunt case(CPU_POWER_ENABLE_TURBO): 699567997b9SDavid Hunt power_manager_enable_turbo_mask(core_mask); 700567997b9SDavid Hunt break; 701567997b9SDavid Hunt case(CPU_POWER_DISABLE_TURBO): 702567997b9SDavid Hunt power_manager_disable_turbo_mask(core_mask); 703567997b9SDavid Hunt break; 704e8ae9b66SAlan Carew default: 705e8ae9b66SAlan Carew break; 706e8ae9b66SAlan Carew } 707e8ae9b66SAlan Carew 708e8ae9b66SAlan Carew } 709e8ae9b66SAlan Carew } 710f14791a8SRory Sexton 711f14791a8SRory Sexton if (pkt->command == PKT_POLICY) { 712*ce4a2766SDavid Hunt RTE_LOG(INFO, CHANNEL_MONITOR, "Processing policy request %s\n", 713*ce4a2766SDavid Hunt pkt->vm_name); 714f14791a8SRory Sexton update_policy(pkt); 715f14791a8SRory Sexton policy_is_set = 1; 716f14791a8SRory Sexton } 717f14791a8SRory Sexton 7183618326fSDavid Hunt if (pkt->command == PKT_POLICY_REMOVE) { 7193618326fSDavid Hunt RTE_LOG(INFO, CHANNEL_MONITOR, 7203618326fSDavid Hunt "Removing policy %s\n", pkt->vm_name); 7213618326fSDavid Hunt remove_policy(pkt); 7223618326fSDavid Hunt } 7233618326fSDavid Hunt 7243618326fSDavid Hunt /* 7253618326fSDavid Hunt * Return is not checked as channel status may have been set to DISABLED 726e8ae9b66SAlan Carew * from management thread 727e8ae9b66SAlan Carew */ 728e8ae9b66SAlan Carew rte_atomic32_cmpset(&(chan_info->status), CHANNEL_MGR_CHANNEL_PROCESSING, 729e8ae9b66SAlan Carew CHANNEL_MGR_CHANNEL_CONNECTED); 730e8ae9b66SAlan Carew return 0; 731e8ae9b66SAlan Carew 732e8ae9b66SAlan Carew } 733e8ae9b66SAlan Carew 734e8ae9b66SAlan Carew int 735e8ae9b66SAlan Carew add_channel_to_monitor(struct channel_info **chan_info) 736e8ae9b66SAlan Carew { 737e8ae9b66SAlan Carew struct channel_info *info = *chan_info; 738e8ae9b66SAlan Carew struct epoll_event event; 739e8ae9b66SAlan Carew 740e8ae9b66SAlan Carew event.events = EPOLLIN; 741e8ae9b66SAlan Carew event.data.ptr = info; 742e8ae9b66SAlan Carew if (epoll_ctl(global_event_fd, EPOLL_CTL_ADD, info->fd, &event) < 0) { 743e8ae9b66SAlan Carew RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to add channel '%s' " 744e8ae9b66SAlan Carew "to epoll\n", info->channel_path); 745e8ae9b66SAlan Carew return -1; 746e8ae9b66SAlan Carew } 7473618326fSDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, "Added channel '%s' " 7483618326fSDavid Hunt "to monitor\n", info->channel_path); 749e8ae9b66SAlan Carew return 0; 750e8ae9b66SAlan Carew } 751e8ae9b66SAlan Carew 752e8ae9b66SAlan Carew int 753e8ae9b66SAlan Carew remove_channel_from_monitor(struct channel_info *chan_info) 754e8ae9b66SAlan Carew { 7553618326fSDavid Hunt if (epoll_ctl(global_event_fd, EPOLL_CTL_DEL, 7563618326fSDavid Hunt chan_info->fd, NULL) < 0) { 757e8ae9b66SAlan Carew RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to remove channel '%s' " 758e8ae9b66SAlan Carew "from epoll\n", chan_info->channel_path); 759e8ae9b66SAlan Carew return -1; 760e8ae9b66SAlan Carew } 761e8ae9b66SAlan Carew return 0; 762e8ae9b66SAlan Carew } 763e8ae9b66SAlan Carew 764e8ae9b66SAlan Carew int 765e8ae9b66SAlan Carew channel_monitor_init(void) 766e8ae9b66SAlan Carew { 767e8ae9b66SAlan Carew global_event_fd = epoll_create1(0); 768e8ae9b66SAlan Carew if (global_event_fd == 0) { 7693618326fSDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 7703618326fSDavid Hunt "Error creating epoll context with error %s\n", 7713618326fSDavid Hunt strerror(errno)); 772e8ae9b66SAlan Carew return -1; 773e8ae9b66SAlan Carew } 7743618326fSDavid Hunt global_events_list = rte_malloc("epoll_events", 7753618326fSDavid Hunt sizeof(*global_events_list) 776fdf20fa7SSergio Gonzalez Monroy * MAX_EVENTS, RTE_CACHE_LINE_SIZE); 777e8ae9b66SAlan Carew if (global_events_list == NULL) { 778e8ae9b66SAlan Carew RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to rte_malloc for " 779e8ae9b66SAlan Carew "epoll events\n"); 780e8ae9b66SAlan Carew return -1; 781e8ae9b66SAlan Carew } 782e8ae9b66SAlan Carew return 0; 783e8ae9b66SAlan Carew } 784e8ae9b66SAlan Carew 785a63504a9SDavid Hunt static void 786a63504a9SDavid Hunt read_binary_packet(struct channel_info *chan_info) 787a63504a9SDavid Hunt { 788a63504a9SDavid Hunt struct channel_packet pkt; 789a63504a9SDavid Hunt void *buffer = &pkt; 790a63504a9SDavid Hunt int buffer_len = sizeof(pkt); 791a63504a9SDavid Hunt int n_bytes, err = 0; 792a63504a9SDavid Hunt 793a63504a9SDavid Hunt while (buffer_len > 0) { 794a63504a9SDavid Hunt n_bytes = read(chan_info->fd, 795a63504a9SDavid Hunt buffer, buffer_len); 796a63504a9SDavid Hunt if (n_bytes == buffer_len) 797a63504a9SDavid Hunt break; 798a63504a9SDavid Hunt if (n_bytes == -1) { 799a63504a9SDavid Hunt err = errno; 800a63504a9SDavid Hunt RTE_LOG(DEBUG, CHANNEL_MONITOR, 801a63504a9SDavid Hunt "Received error on " 802a63504a9SDavid Hunt "channel '%s' read: %s\n", 803a63504a9SDavid Hunt chan_info->channel_path, 804a63504a9SDavid Hunt strerror(err)); 805a63504a9SDavid Hunt remove_channel(&chan_info); 806a63504a9SDavid Hunt break; 807a63504a9SDavid Hunt } 808a63504a9SDavid Hunt buffer = (char *)buffer + n_bytes; 809a63504a9SDavid Hunt buffer_len -= n_bytes; 810a63504a9SDavid Hunt } 811a63504a9SDavid Hunt if (!err) 812a63504a9SDavid Hunt process_request(&pkt, chan_info); 813a63504a9SDavid Hunt } 814a63504a9SDavid Hunt 815a63504a9SDavid Hunt #ifdef USE_JANSSON 816a63504a9SDavid Hunt static void 817a63504a9SDavid Hunt read_json_packet(struct channel_info *chan_info) 818a63504a9SDavid Hunt { 819a63504a9SDavid Hunt struct channel_packet pkt; 820a63504a9SDavid Hunt int n_bytes, ret; 821a63504a9SDavid Hunt json_t *root; 822a63504a9SDavid Hunt json_error_t error; 823a63504a9SDavid Hunt 824a63504a9SDavid Hunt /* read opening brace to closing brace */ 825a63504a9SDavid Hunt do { 826a63504a9SDavid Hunt int idx = 0; 827a63504a9SDavid Hunt int indent = 0; 828a63504a9SDavid Hunt do { 829a63504a9SDavid Hunt n_bytes = read(chan_info->fd, &json_data[idx], 1); 830a63504a9SDavid Hunt if (n_bytes == 0) 831a63504a9SDavid Hunt break; 832a63504a9SDavid Hunt if (json_data[idx] == '{') 833a63504a9SDavid Hunt indent++; 834a63504a9SDavid Hunt if (json_data[idx] == '}') 835a63504a9SDavid Hunt indent--; 836a63504a9SDavid Hunt if ((indent > 0) || (idx > 0)) 837a63504a9SDavid Hunt idx++; 838a63504a9SDavid Hunt if (indent == 0) 839a63504a9SDavid Hunt json_data[idx] = 0; 840a63504a9SDavid Hunt if (idx >= MAX_JSON_STRING_LEN-1) 841a63504a9SDavid Hunt break; 842a63504a9SDavid Hunt } while (indent > 0); 843a63504a9SDavid Hunt 844a63504a9SDavid Hunt if (indent > 0) 845a63504a9SDavid Hunt /* 846a63504a9SDavid Hunt * We've broken out of the read loop without getting 847a63504a9SDavid Hunt * a closing brace, so throw away the data 848a63504a9SDavid Hunt */ 849a63504a9SDavid Hunt json_data[idx] = 0; 850a63504a9SDavid Hunt 851a63504a9SDavid Hunt if (strlen(json_data) == 0) 852a63504a9SDavid Hunt continue; 853a63504a9SDavid Hunt 854a63504a9SDavid Hunt printf("got [%s]\n", json_data); 855a63504a9SDavid Hunt 856a63504a9SDavid Hunt root = json_loads(json_data, 0, &error); 857a63504a9SDavid Hunt 858a63504a9SDavid Hunt if (root) { 859a63504a9SDavid Hunt /* 860a63504a9SDavid Hunt * Because our data is now in the json 861a63504a9SDavid Hunt * object, we can overwrite the pkt 862a63504a9SDavid Hunt * with a channel_packet struct, using 863a63504a9SDavid Hunt * parse_json_to_pkt() 864a63504a9SDavid Hunt */ 865a63504a9SDavid Hunt ret = parse_json_to_pkt(root, &pkt); 866a63504a9SDavid Hunt json_decref(root); 867a63504a9SDavid Hunt if (ret) { 868a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 869a63504a9SDavid Hunt "Error validating JSON profile data\n"); 870a63504a9SDavid Hunt break; 871a63504a9SDavid Hunt } 872a63504a9SDavid Hunt process_request(&pkt, chan_info); 873a63504a9SDavid Hunt } else { 874a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 875a63504a9SDavid Hunt "JSON error on line %d: %s\n", 876a63504a9SDavid Hunt error.line, error.text); 877a63504a9SDavid Hunt } 878a63504a9SDavid Hunt } while (n_bytes > 0); 879a63504a9SDavid Hunt } 880a63504a9SDavid Hunt #endif 881a63504a9SDavid Hunt 882e8ae9b66SAlan Carew void 883e8ae9b66SAlan Carew run_channel_monitor(void) 884e8ae9b66SAlan Carew { 885e8ae9b66SAlan Carew while (run_loop) { 886e8ae9b66SAlan Carew int n_events, i; 887e8ae9b66SAlan Carew 888e8ae9b66SAlan Carew n_events = epoll_wait(global_event_fd, global_events_list, 889e8ae9b66SAlan Carew MAX_EVENTS, 1); 890e8ae9b66SAlan Carew if (!run_loop) 891e8ae9b66SAlan Carew break; 892e8ae9b66SAlan Carew for (i = 0; i < n_events; i++) { 893e8ae9b66SAlan Carew struct channel_info *chan_info = (struct channel_info *) 894e8ae9b66SAlan Carew global_events_list[i].data.ptr; 895e8ae9b66SAlan Carew if ((global_events_list[i].events & EPOLLERR) || 896e8ae9b66SAlan Carew (global_events_list[i].events & EPOLLHUP)) { 897*ce4a2766SDavid Hunt RTE_LOG(INFO, CHANNEL_MONITOR, 898*ce4a2766SDavid Hunt "Remote closed connection for " 899f14791a8SRory Sexton "channel '%s'\n", 900f14791a8SRory Sexton chan_info->channel_path); 901e8ae9b66SAlan Carew remove_channel(&chan_info); 902e8ae9b66SAlan Carew continue; 903e8ae9b66SAlan Carew } 904e8ae9b66SAlan Carew if (global_events_list[i].events & EPOLLIN) { 905e8ae9b66SAlan Carew 906a63504a9SDavid Hunt switch (chan_info->type) { 907a63504a9SDavid Hunt case CHANNEL_TYPE_BINARY: 908a63504a9SDavid Hunt read_binary_packet(chan_info); 909e8ae9b66SAlan Carew break; 910a63504a9SDavid Hunt #ifdef USE_JANSSON 911a63504a9SDavid Hunt case CHANNEL_TYPE_JSON: 912a63504a9SDavid Hunt read_json_packet(chan_info); 913a63504a9SDavid Hunt break; 914a63504a9SDavid Hunt #endif 915a63504a9SDavid Hunt default: 916e8ae9b66SAlan Carew break; 917e8ae9b66SAlan Carew } 918e8ae9b66SAlan Carew } 919e8ae9b66SAlan Carew } 920e4f66da3SDavid Hunt rte_delay_us(time_period_ms*1000); 921f14791a8SRory Sexton if (policy_is_set) { 9227abd801fSDavid Hunt int j; 9237abd801fSDavid Hunt 92490a774c4SDavid Hunt for (j = 0; j < MAX_CLIENTS; j++) { 925f14791a8SRory Sexton if (policies[j].enabled == 1) 926f14791a8SRory Sexton apply_policy(&policies[j]); 927f14791a8SRory Sexton } 928f14791a8SRory Sexton } 929e8ae9b66SAlan Carew } 930e8ae9b66SAlan Carew } 931