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> 12*a63504a9SDavid 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> 17*a63504a9SDavid Hunt #include <sys/socket.h> 18*a63504a9SDavid Hunt #include <sys/select.h> 19*a63504a9SDavid Hunt #ifdef USE_JANSSON 20*a63504a9SDavid Hunt #include <jansson.h> 21*a63504a9SDavid Hunt #else 22*a63504a9SDavid Hunt #pragma message "Jansson dev libs unavailable, not including JSON parsing" 23*a63504a9SDavid 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]; 45*a63504a9SDavid Hunt #define MAX_JSON_STRING_LEN 1024 46*a63504a9SDavid 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 55*a63504a9SDavid Hunt #ifdef USE_JANSSON 56*a63504a9SDavid Hunt 57*a63504a9SDavid Hunt union PFID { 58*a63504a9SDavid Hunt struct ether_addr addr; 59*a63504a9SDavid Hunt uint64_t pfid; 60*a63504a9SDavid Hunt }; 61*a63504a9SDavid Hunt 62*a63504a9SDavid Hunt static int 63*a63504a9SDavid Hunt str_to_ether_addr(const char *a, struct ether_addr *ether_addr) 64*a63504a9SDavid Hunt { 65*a63504a9SDavid Hunt int i; 66*a63504a9SDavid Hunt char *end; 67*a63504a9SDavid Hunt unsigned long o[ETHER_ADDR_LEN]; 68*a63504a9SDavid Hunt 69*a63504a9SDavid Hunt i = 0; 70*a63504a9SDavid Hunt do { 71*a63504a9SDavid Hunt errno = 0; 72*a63504a9SDavid Hunt o[i] = strtoul(a, &end, 16); 73*a63504a9SDavid Hunt if (errno != 0 || end == a || (end[0] != ':' && end[0] != 0)) 74*a63504a9SDavid Hunt return -1; 75*a63504a9SDavid Hunt a = end + 1; 76*a63504a9SDavid Hunt } while (++i != RTE_DIM(o) / sizeof(o[0]) && end[0] != 0); 77*a63504a9SDavid Hunt 78*a63504a9SDavid Hunt /* Junk at the end of line */ 79*a63504a9SDavid Hunt if (end[0] != 0) 80*a63504a9SDavid Hunt return -1; 81*a63504a9SDavid Hunt 82*a63504a9SDavid Hunt /* Support the format XX:XX:XX:XX:XX:XX */ 83*a63504a9SDavid Hunt if (i == ETHER_ADDR_LEN) { 84*a63504a9SDavid Hunt while (i-- != 0) { 85*a63504a9SDavid Hunt if (o[i] > UINT8_MAX) 86*a63504a9SDavid Hunt return -1; 87*a63504a9SDavid Hunt ether_addr->addr_bytes[i] = (uint8_t)o[i]; 88*a63504a9SDavid Hunt } 89*a63504a9SDavid Hunt /* Support the format XXXX:XXXX:XXXX */ 90*a63504a9SDavid Hunt } else if (i == ETHER_ADDR_LEN / 2) { 91*a63504a9SDavid Hunt while (i-- != 0) { 92*a63504a9SDavid Hunt if (o[i] > UINT16_MAX) 93*a63504a9SDavid Hunt return -1; 94*a63504a9SDavid Hunt ether_addr->addr_bytes[i * 2] = 95*a63504a9SDavid Hunt (uint8_t)(o[i] >> 8); 96*a63504a9SDavid Hunt ether_addr->addr_bytes[i * 2 + 1] = 97*a63504a9SDavid Hunt (uint8_t)(o[i] & 0xff); 98*a63504a9SDavid Hunt } 99*a63504a9SDavid Hunt /* unknown format */ 100*a63504a9SDavid Hunt } else 101*a63504a9SDavid Hunt return -1; 102*a63504a9SDavid Hunt 103*a63504a9SDavid Hunt return 0; 104*a63504a9SDavid Hunt } 105*a63504a9SDavid Hunt 106*a63504a9SDavid Hunt static int 107*a63504a9SDavid Hunt set_policy_mac(struct channel_packet *pkt, int idx, char *mac) 108*a63504a9SDavid Hunt { 109*a63504a9SDavid Hunt union PFID pfid; 110*a63504a9SDavid Hunt int ret; 111*a63504a9SDavid Hunt 112*a63504a9SDavid Hunt /* Use port MAC address as the vfid */ 113*a63504a9SDavid Hunt ret = str_to_ether_addr(mac, &pfid.addr); 114*a63504a9SDavid Hunt 115*a63504a9SDavid Hunt if (ret != 0) { 116*a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 117*a63504a9SDavid Hunt "Invalid mac address received in JSON\n"); 118*a63504a9SDavid Hunt pkt->vfid[idx] = 0; 119*a63504a9SDavid Hunt return -1; 120*a63504a9SDavid Hunt } 121*a63504a9SDavid Hunt 122*a63504a9SDavid Hunt printf("Received MAC Address: %02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 ":" 123*a63504a9SDavid Hunt "%02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 "\n", 124*a63504a9SDavid Hunt pfid.addr.addr_bytes[0], pfid.addr.addr_bytes[1], 125*a63504a9SDavid Hunt pfid.addr.addr_bytes[2], pfid.addr.addr_bytes[3], 126*a63504a9SDavid Hunt pfid.addr.addr_bytes[4], pfid.addr.addr_bytes[5]); 127*a63504a9SDavid Hunt 128*a63504a9SDavid Hunt pkt->vfid[idx] = pfid.pfid; 129*a63504a9SDavid Hunt return 0; 130*a63504a9SDavid Hunt } 131*a63504a9SDavid Hunt 132*a63504a9SDavid Hunt 133*a63504a9SDavid Hunt static int 134*a63504a9SDavid Hunt parse_json_to_pkt(json_t *element, struct channel_packet *pkt) 135*a63504a9SDavid Hunt { 136*a63504a9SDavid Hunt const char *key; 137*a63504a9SDavid Hunt json_t *value; 138*a63504a9SDavid Hunt int ret; 139*a63504a9SDavid Hunt 140*a63504a9SDavid Hunt memset(pkt, 0, sizeof(struct channel_packet)); 141*a63504a9SDavid Hunt 142*a63504a9SDavid Hunt pkt->nb_mac_to_monitor = 0; 143*a63504a9SDavid Hunt pkt->t_boost_status.tbEnabled = false; 144*a63504a9SDavid Hunt pkt->workload = LOW; 145*a63504a9SDavid Hunt pkt->policy_to_use = TIME; 146*a63504a9SDavid Hunt pkt->command = PKT_POLICY; 147*a63504a9SDavid Hunt pkt->core_type = CORE_TYPE_PHYSICAL; 148*a63504a9SDavid Hunt 149*a63504a9SDavid Hunt json_object_foreach(element, key, value) { 150*a63504a9SDavid Hunt if (!strcmp(key, "policy")) { 151*a63504a9SDavid Hunt /* Recurse in to get the contents of profile */ 152*a63504a9SDavid Hunt ret = parse_json_to_pkt(value, pkt); 153*a63504a9SDavid Hunt if (ret) 154*a63504a9SDavid Hunt return ret; 155*a63504a9SDavid Hunt } else if (!strcmp(key, "instruction")) { 156*a63504a9SDavid Hunt /* Recurse in to get the contents of instruction */ 157*a63504a9SDavid Hunt ret = parse_json_to_pkt(value, pkt); 158*a63504a9SDavid Hunt if (ret) 159*a63504a9SDavid Hunt return ret; 160*a63504a9SDavid Hunt } else if (!strcmp(key, "name")) { 161*a63504a9SDavid Hunt strcpy(pkt->vm_name, json_string_value(value)); 162*a63504a9SDavid Hunt } else if (!strcmp(key, "command")) { 163*a63504a9SDavid Hunt char command[32]; 164*a63504a9SDavid Hunt snprintf(command, 32, "%s", json_string_value(value)); 165*a63504a9SDavid Hunt if (!strcmp(command, "power")) { 166*a63504a9SDavid Hunt pkt->command = CPU_POWER; 167*a63504a9SDavid Hunt } else if (!strcmp(command, "create")) { 168*a63504a9SDavid Hunt pkt->command = PKT_POLICY; 169*a63504a9SDavid Hunt } else if (!strcmp(command, "destroy")) { 170*a63504a9SDavid Hunt pkt->command = PKT_POLICY_REMOVE; 171*a63504a9SDavid Hunt } else { 172*a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 173*a63504a9SDavid Hunt "Invalid command received in JSON\n"); 174*a63504a9SDavid Hunt return -1; 175*a63504a9SDavid Hunt } 176*a63504a9SDavid Hunt } else if (!strcmp(key, "policy_type")) { 177*a63504a9SDavid Hunt char command[32]; 178*a63504a9SDavid Hunt snprintf(command, 32, "%s", json_string_value(value)); 179*a63504a9SDavid Hunt if (!strcmp(command, "TIME")) { 180*a63504a9SDavid Hunt pkt->policy_to_use = TIME; 181*a63504a9SDavid Hunt } else if (!strcmp(command, "TRAFFIC")) { 182*a63504a9SDavid Hunt pkt->policy_to_use = TRAFFIC; 183*a63504a9SDavid Hunt } else if (!strcmp(command, "WORKLOAD")) { 184*a63504a9SDavid Hunt pkt->policy_to_use = WORKLOAD; 185*a63504a9SDavid Hunt } else if (!strcmp(command, "BRANCH_RATIO")) { 186*a63504a9SDavid Hunt pkt->policy_to_use = BRANCH_RATIO; 187*a63504a9SDavid Hunt } else { 188*a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 189*a63504a9SDavid Hunt "Wrong policy_type received in JSON\n"); 190*a63504a9SDavid Hunt return -1; 191*a63504a9SDavid Hunt } 192*a63504a9SDavid Hunt } else if (!strcmp(key, "workload")) { 193*a63504a9SDavid Hunt char command[32]; 194*a63504a9SDavid Hunt snprintf(command, 32, "%s", json_string_value(value)); 195*a63504a9SDavid Hunt if (!strcmp(command, "HIGH")) { 196*a63504a9SDavid Hunt pkt->workload = HIGH; 197*a63504a9SDavid Hunt } else if (!strcmp(command, "MEDIUM")) { 198*a63504a9SDavid Hunt pkt->workload = MEDIUM; 199*a63504a9SDavid Hunt } else if (!strcmp(command, "LOW")) { 200*a63504a9SDavid Hunt pkt->workload = LOW; 201*a63504a9SDavid Hunt } else { 202*a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 203*a63504a9SDavid Hunt "Wrong workload received in JSON\n"); 204*a63504a9SDavid Hunt return -1; 205*a63504a9SDavid Hunt } 206*a63504a9SDavid Hunt } else if (!strcmp(key, "busy_hours")) { 207*a63504a9SDavid Hunt unsigned int i; 208*a63504a9SDavid Hunt size_t size = json_array_size(value); 209*a63504a9SDavid Hunt 210*a63504a9SDavid Hunt for (i = 0; i < size; i++) { 211*a63504a9SDavid Hunt int hour = (int)json_integer_value( 212*a63504a9SDavid Hunt json_array_get(value, i)); 213*a63504a9SDavid Hunt pkt->timer_policy.busy_hours[i] = hour; 214*a63504a9SDavid Hunt } 215*a63504a9SDavid Hunt } else if (!strcmp(key, "quiet_hours")) { 216*a63504a9SDavid Hunt unsigned int i; 217*a63504a9SDavid Hunt size_t size = json_array_size(value); 218*a63504a9SDavid Hunt 219*a63504a9SDavid Hunt for (i = 0; i < size; i++) { 220*a63504a9SDavid Hunt int hour = (int)json_integer_value( 221*a63504a9SDavid Hunt json_array_get(value, i)); 222*a63504a9SDavid Hunt pkt->timer_policy.quiet_hours[i] = hour; 223*a63504a9SDavid Hunt } 224*a63504a9SDavid Hunt } else if (!strcmp(key, "core_list")) { 225*a63504a9SDavid Hunt unsigned int i; 226*a63504a9SDavid Hunt size_t size = json_array_size(value); 227*a63504a9SDavid Hunt 228*a63504a9SDavid Hunt for (i = 0; i < size; i++) { 229*a63504a9SDavid Hunt int core = (int)json_integer_value( 230*a63504a9SDavid Hunt json_array_get(value, i)); 231*a63504a9SDavid Hunt pkt->vcpu_to_control[i] = core; 232*a63504a9SDavid Hunt } 233*a63504a9SDavid Hunt pkt->num_vcpu = size; 234*a63504a9SDavid Hunt } else if (!strcmp(key, "mac_list")) { 235*a63504a9SDavid Hunt unsigned int i; 236*a63504a9SDavid Hunt size_t size = json_array_size(value); 237*a63504a9SDavid Hunt 238*a63504a9SDavid Hunt for (i = 0; i < size; i++) { 239*a63504a9SDavid Hunt char mac[32]; 240*a63504a9SDavid Hunt snprintf(mac, 32, "%s", json_string_value( 241*a63504a9SDavid Hunt json_array_get(value, i))); 242*a63504a9SDavid Hunt set_policy_mac(pkt, i, mac); 243*a63504a9SDavid Hunt } 244*a63504a9SDavid Hunt pkt->nb_mac_to_monitor = size; 245*a63504a9SDavid Hunt } else if (!strcmp(key, "avg_packet_thresh")) { 246*a63504a9SDavid Hunt pkt->traffic_policy.avg_max_packet_thresh = 247*a63504a9SDavid Hunt (uint32_t)json_integer_value(value); 248*a63504a9SDavid Hunt } else if (!strcmp(key, "max_packet_thresh")) { 249*a63504a9SDavid Hunt pkt->traffic_policy.max_max_packet_thresh = 250*a63504a9SDavid Hunt (uint32_t)json_integer_value(value); 251*a63504a9SDavid Hunt } else if (!strcmp(key, "unit")) { 252*a63504a9SDavid Hunt char unit[32]; 253*a63504a9SDavid Hunt snprintf(unit, 32, "%s", json_string_value(value)); 254*a63504a9SDavid Hunt if (!strcmp(unit, "SCALE_UP")) { 255*a63504a9SDavid Hunt pkt->unit = CPU_POWER_SCALE_UP; 256*a63504a9SDavid Hunt } else if (!strcmp(unit, "SCALE_DOWN")) { 257*a63504a9SDavid Hunt pkt->unit = CPU_POWER_SCALE_DOWN; 258*a63504a9SDavid Hunt } else if (!strcmp(unit, "SCALE_MAX")) { 259*a63504a9SDavid Hunt pkt->unit = CPU_POWER_SCALE_MAX; 260*a63504a9SDavid Hunt } else if (!strcmp(unit, "SCALE_MIN")) { 261*a63504a9SDavid Hunt pkt->unit = CPU_POWER_SCALE_MIN; 262*a63504a9SDavid Hunt } else if (!strcmp(unit, "ENABLE_TURBO")) { 263*a63504a9SDavid Hunt pkt->unit = CPU_POWER_ENABLE_TURBO; 264*a63504a9SDavid Hunt } else if (!strcmp(unit, "DISABLE_TURBO")) { 265*a63504a9SDavid Hunt pkt->unit = CPU_POWER_DISABLE_TURBO; 266*a63504a9SDavid Hunt } else { 267*a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 268*a63504a9SDavid Hunt "Invalid command received in JSON\n"); 269*a63504a9SDavid Hunt return -1; 270*a63504a9SDavid Hunt } 271*a63504a9SDavid Hunt } else if (!strcmp(key, "resource_id")) { 272*a63504a9SDavid Hunt pkt->resource_id = (uint32_t)json_integer_value(value); 273*a63504a9SDavid Hunt } else { 274*a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 275*a63504a9SDavid Hunt "Unknown key received in JSON string: %s\n", 276*a63504a9SDavid Hunt key); 277*a63504a9SDavid Hunt } 278*a63504a9SDavid Hunt } 279*a63504a9SDavid Hunt return 0; 280*a63504a9SDavid Hunt } 281*a63504a9SDavid Hunt #endif 282*a63504a9SDavid 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 3643618326fSDavid Hunt RTE_LOG(INFO, 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 RTE_LOG(INFO, CHANNEL_MONITOR, "Applying traffic profile\n"); 532f14791a8SRory Sexton 533f14791a8SRory Sexton if (diff >= (pol->pkt.traffic_policy.max_max_packet_thresh)) { 534f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 535f14791a8SRory Sexton if (pol->core_share[count].status != 1) 536f14791a8SRory Sexton power_manager_scale_core_max( 537f14791a8SRory Sexton pol->core_share[count].pcpu); 538f14791a8SRory Sexton } 539f14791a8SRory Sexton } else if (diff >= (pol->pkt.traffic_policy.avg_max_packet_thresh)) { 540f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 541f14791a8SRory Sexton if (pol->core_share[count].status != 1) 542f14791a8SRory Sexton power_manager_scale_core_med( 543f14791a8SRory Sexton pol->core_share[count].pcpu); 544f14791a8SRory Sexton } 545f14791a8SRory Sexton } else if (diff < (pol->pkt.traffic_policy.avg_max_packet_thresh)) { 546f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 547f14791a8SRory Sexton if (pol->core_share[count].status != 1) 548f14791a8SRory Sexton power_manager_scale_core_min( 549f14791a8SRory Sexton pol->core_share[count].pcpu); 550f14791a8SRory Sexton } 551f14791a8SRory Sexton } 552f14791a8SRory Sexton } 553f14791a8SRory Sexton 554f14791a8SRory Sexton static void 555f14791a8SRory Sexton apply_time_profile(struct policy *pol) 556f14791a8SRory Sexton { 557f14791a8SRory Sexton 558f14791a8SRory Sexton int count, x; 559f14791a8SRory Sexton struct timeval tv; 560f14791a8SRory Sexton struct tm *ptm; 561f14791a8SRory Sexton char time_string[40]; 562f14791a8SRory Sexton 563f14791a8SRory Sexton /* Obtain the time of day, and convert it to a tm struct. */ 564f14791a8SRory Sexton gettimeofday(&tv, NULL); 565f14791a8SRory Sexton ptm = localtime(&tv.tv_sec); 566f14791a8SRory Sexton /* Format the date and time, down to a single second. */ 567f14791a8SRory Sexton strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", ptm); 568f14791a8SRory Sexton 569f14791a8SRory Sexton for (x = 0; x < HOURS; x++) { 570f14791a8SRory Sexton 571f14791a8SRory Sexton if (ptm->tm_hour == pol->pkt.timer_policy.busy_hours[x]) { 572f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 573f14791a8SRory Sexton if (pol->core_share[count].status != 1) { 574f14791a8SRory Sexton power_manager_scale_core_max( 575f14791a8SRory Sexton pol->core_share[count].pcpu); 576f14791a8SRory Sexton RTE_LOG(INFO, CHANNEL_MONITOR, 577f14791a8SRory Sexton "Scaling up core %d to max\n", 578f14791a8SRory Sexton pol->core_share[count].pcpu); 579f14791a8SRory Sexton } 580f14791a8SRory Sexton } 581f14791a8SRory Sexton break; 582f14791a8SRory Sexton } else if (ptm->tm_hour == 583f14791a8SRory Sexton pol->pkt.timer_policy.quiet_hours[x]) { 584f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 585f14791a8SRory Sexton if (pol->core_share[count].status != 1) { 586f14791a8SRory Sexton power_manager_scale_core_min( 587f14791a8SRory Sexton pol->core_share[count].pcpu); 588f14791a8SRory Sexton RTE_LOG(INFO, CHANNEL_MONITOR, 589f14791a8SRory Sexton "Scaling down core %d to min\n", 590f14791a8SRory Sexton pol->core_share[count].pcpu); 591f14791a8SRory Sexton } 592f14791a8SRory Sexton } 593f14791a8SRory Sexton break; 594f14791a8SRory Sexton } else if (ptm->tm_hour == 595f14791a8SRory Sexton pol->pkt.timer_policy.hours_to_use_traffic_profile[x]) { 596f14791a8SRory Sexton apply_traffic_profile(pol); 597f14791a8SRory Sexton break; 598f14791a8SRory Sexton } 599f14791a8SRory Sexton } 600f14791a8SRory Sexton } 601f14791a8SRory Sexton 602f14791a8SRory Sexton static void 603f14791a8SRory Sexton apply_workload_profile(struct policy *pol) 604f14791a8SRory Sexton { 605f14791a8SRory Sexton 606f14791a8SRory Sexton int count; 607f14791a8SRory Sexton 608f14791a8SRory Sexton if (pol->pkt.workload == HIGH) { 609f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 610f14791a8SRory Sexton if (pol->core_share[count].status != 1) 611f14791a8SRory Sexton power_manager_scale_core_max( 612f14791a8SRory Sexton pol->core_share[count].pcpu); 613f14791a8SRory Sexton } 614f14791a8SRory Sexton } else if (pol->pkt.workload == MEDIUM) { 615f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 616f14791a8SRory Sexton if (pol->core_share[count].status != 1) 617f14791a8SRory Sexton power_manager_scale_core_med( 618f14791a8SRory Sexton pol->core_share[count].pcpu); 619f14791a8SRory Sexton } 620f14791a8SRory Sexton } else if (pol->pkt.workload == LOW) { 621f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 622f14791a8SRory Sexton if (pol->core_share[count].status != 1) 623f14791a8SRory Sexton power_manager_scale_core_min( 624f14791a8SRory Sexton pol->core_share[count].pcpu); 625f14791a8SRory Sexton } 626f14791a8SRory Sexton } 627f14791a8SRory Sexton } 628f14791a8SRory Sexton 629f14791a8SRory Sexton static void 630f14791a8SRory Sexton apply_policy(struct policy *pol) 631f14791a8SRory Sexton { 632f14791a8SRory Sexton 633f14791a8SRory Sexton struct channel_packet *pkt = &pol->pkt; 634f14791a8SRory Sexton 635f14791a8SRory Sexton /*Check policy to use*/ 636f14791a8SRory Sexton if (pkt->policy_to_use == TRAFFIC) 637f14791a8SRory Sexton apply_traffic_profile(pol); 638f14791a8SRory Sexton else if (pkt->policy_to_use == TIME) 639f14791a8SRory Sexton apply_time_profile(pol); 640f14791a8SRory Sexton else if (pkt->policy_to_use == WORKLOAD) 641f14791a8SRory Sexton apply_workload_profile(pol); 642f14791a8SRory Sexton } 643f14791a8SRory Sexton 644e8ae9b66SAlan Carew static int 645e8ae9b66SAlan Carew process_request(struct channel_packet *pkt, struct channel_info *chan_info) 646e8ae9b66SAlan Carew { 647e8ae9b66SAlan Carew uint64_t core_mask; 648e8ae9b66SAlan Carew 649e8ae9b66SAlan Carew if (chan_info == NULL) 650e8ae9b66SAlan Carew return -1; 651e8ae9b66SAlan Carew 6523618326fSDavid Hunt RTE_LOG(INFO, CHANNEL_MONITOR, "Processing Request %s\n", pkt->vm_name); 6533618326fSDavid Hunt 654e8ae9b66SAlan Carew if (rte_atomic32_cmpset(&(chan_info->status), CHANNEL_MGR_CHANNEL_CONNECTED, 655e8ae9b66SAlan Carew CHANNEL_MGR_CHANNEL_PROCESSING) == 0) 656e8ae9b66SAlan Carew return -1; 657e8ae9b66SAlan Carew 658e8ae9b66SAlan Carew if (pkt->command == CPU_POWER) { 659e8ae9b66SAlan Carew core_mask = get_pcpus_mask(chan_info, pkt->resource_id); 660e8ae9b66SAlan Carew if (core_mask == 0) { 6613618326fSDavid Hunt /* 6623618326fSDavid Hunt * Core mask will be 0 in the case where 6633618326fSDavid Hunt * hypervisor is not available so we're working in 6643618326fSDavid Hunt * the host, so use the core as the mask. 6653618326fSDavid Hunt */ 6663618326fSDavid Hunt core_mask = 1ULL << pkt->resource_id; 667e8ae9b66SAlan Carew } 668e8ae9b66SAlan Carew if (__builtin_popcountll(core_mask) == 1) { 669e8ae9b66SAlan Carew 670e8ae9b66SAlan Carew unsigned core_num = __builtin_ffsll(core_mask) - 1; 671e8ae9b66SAlan Carew 672e8ae9b66SAlan Carew switch (pkt->unit) { 673e8ae9b66SAlan Carew case(CPU_POWER_SCALE_MIN): 674e8ae9b66SAlan Carew power_manager_scale_core_min(core_num); 675e8ae9b66SAlan Carew break; 676e8ae9b66SAlan Carew case(CPU_POWER_SCALE_MAX): 677e8ae9b66SAlan Carew power_manager_scale_core_max(core_num); 678e8ae9b66SAlan Carew break; 679e8ae9b66SAlan Carew case(CPU_POWER_SCALE_DOWN): 680e8ae9b66SAlan Carew power_manager_scale_core_down(core_num); 681e8ae9b66SAlan Carew break; 682e8ae9b66SAlan Carew case(CPU_POWER_SCALE_UP): 683e8ae9b66SAlan Carew power_manager_scale_core_up(core_num); 684e8ae9b66SAlan Carew break; 685567997b9SDavid Hunt case(CPU_POWER_ENABLE_TURBO): 686567997b9SDavid Hunt power_manager_enable_turbo_core(core_num); 687567997b9SDavid Hunt break; 688567997b9SDavid Hunt case(CPU_POWER_DISABLE_TURBO): 689567997b9SDavid Hunt power_manager_disable_turbo_core(core_num); 690567997b9SDavid Hunt break; 691e8ae9b66SAlan Carew default: 692e8ae9b66SAlan Carew break; 693e8ae9b66SAlan Carew } 694e8ae9b66SAlan Carew } else { 695e8ae9b66SAlan Carew switch (pkt->unit) { 696e8ae9b66SAlan Carew case(CPU_POWER_SCALE_MIN): 697e8ae9b66SAlan Carew power_manager_scale_mask_min(core_mask); 698e8ae9b66SAlan Carew break; 699e8ae9b66SAlan Carew case(CPU_POWER_SCALE_MAX): 700e8ae9b66SAlan Carew power_manager_scale_mask_max(core_mask); 701e8ae9b66SAlan Carew break; 702e8ae9b66SAlan Carew case(CPU_POWER_SCALE_DOWN): 703e8ae9b66SAlan Carew power_manager_scale_mask_down(core_mask); 704e8ae9b66SAlan Carew break; 705e8ae9b66SAlan Carew case(CPU_POWER_SCALE_UP): 706e8ae9b66SAlan Carew power_manager_scale_mask_up(core_mask); 707e8ae9b66SAlan Carew break; 708567997b9SDavid Hunt case(CPU_POWER_ENABLE_TURBO): 709567997b9SDavid Hunt power_manager_enable_turbo_mask(core_mask); 710567997b9SDavid Hunt break; 711567997b9SDavid Hunt case(CPU_POWER_DISABLE_TURBO): 712567997b9SDavid Hunt power_manager_disable_turbo_mask(core_mask); 713567997b9SDavid Hunt break; 714e8ae9b66SAlan Carew default: 715e8ae9b66SAlan Carew break; 716e8ae9b66SAlan Carew } 717e8ae9b66SAlan Carew 718e8ae9b66SAlan Carew } 719e8ae9b66SAlan Carew } 720f14791a8SRory Sexton 721f14791a8SRory Sexton if (pkt->command == PKT_POLICY) { 7223618326fSDavid Hunt RTE_LOG(INFO, CHANNEL_MONITOR, 7233618326fSDavid Hunt "\nProcessing Policy request\n"); 724f14791a8SRory Sexton update_policy(pkt); 725f14791a8SRory Sexton policy_is_set = 1; 726f14791a8SRory Sexton } 727f14791a8SRory Sexton 7283618326fSDavid Hunt if (pkt->command == PKT_POLICY_REMOVE) { 7293618326fSDavid Hunt RTE_LOG(INFO, CHANNEL_MONITOR, 7303618326fSDavid Hunt "Removing policy %s\n", pkt->vm_name); 7313618326fSDavid Hunt remove_policy(pkt); 7323618326fSDavid Hunt } 7333618326fSDavid Hunt 7343618326fSDavid Hunt /* 7353618326fSDavid Hunt * Return is not checked as channel status may have been set to DISABLED 736e8ae9b66SAlan Carew * from management thread 737e8ae9b66SAlan Carew */ 738e8ae9b66SAlan Carew rte_atomic32_cmpset(&(chan_info->status), CHANNEL_MGR_CHANNEL_PROCESSING, 739e8ae9b66SAlan Carew CHANNEL_MGR_CHANNEL_CONNECTED); 740e8ae9b66SAlan Carew return 0; 741e8ae9b66SAlan Carew 742e8ae9b66SAlan Carew } 743e8ae9b66SAlan Carew 744e8ae9b66SAlan Carew int 745e8ae9b66SAlan Carew add_channel_to_monitor(struct channel_info **chan_info) 746e8ae9b66SAlan Carew { 747e8ae9b66SAlan Carew struct channel_info *info = *chan_info; 748e8ae9b66SAlan Carew struct epoll_event event; 749e8ae9b66SAlan Carew 750e8ae9b66SAlan Carew event.events = EPOLLIN; 751e8ae9b66SAlan Carew event.data.ptr = info; 752e8ae9b66SAlan Carew if (epoll_ctl(global_event_fd, EPOLL_CTL_ADD, info->fd, &event) < 0) { 753e8ae9b66SAlan Carew RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to add channel '%s' " 754e8ae9b66SAlan Carew "to epoll\n", info->channel_path); 755e8ae9b66SAlan Carew return -1; 756e8ae9b66SAlan Carew } 7573618326fSDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, "Added channel '%s' " 7583618326fSDavid Hunt "to monitor\n", info->channel_path); 759e8ae9b66SAlan Carew return 0; 760e8ae9b66SAlan Carew } 761e8ae9b66SAlan Carew 762e8ae9b66SAlan Carew int 763e8ae9b66SAlan Carew remove_channel_from_monitor(struct channel_info *chan_info) 764e8ae9b66SAlan Carew { 7653618326fSDavid Hunt if (epoll_ctl(global_event_fd, EPOLL_CTL_DEL, 7663618326fSDavid Hunt chan_info->fd, NULL) < 0) { 767e8ae9b66SAlan Carew RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to remove channel '%s' " 768e8ae9b66SAlan Carew "from epoll\n", chan_info->channel_path); 769e8ae9b66SAlan Carew return -1; 770e8ae9b66SAlan Carew } 771e8ae9b66SAlan Carew return 0; 772e8ae9b66SAlan Carew } 773e8ae9b66SAlan Carew 774e8ae9b66SAlan Carew int 775e8ae9b66SAlan Carew channel_monitor_init(void) 776e8ae9b66SAlan Carew { 777e8ae9b66SAlan Carew global_event_fd = epoll_create1(0); 778e8ae9b66SAlan Carew if (global_event_fd == 0) { 7793618326fSDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 7803618326fSDavid Hunt "Error creating epoll context with error %s\n", 7813618326fSDavid Hunt strerror(errno)); 782e8ae9b66SAlan Carew return -1; 783e8ae9b66SAlan Carew } 7843618326fSDavid Hunt global_events_list = rte_malloc("epoll_events", 7853618326fSDavid Hunt sizeof(*global_events_list) 786fdf20fa7SSergio Gonzalez Monroy * MAX_EVENTS, RTE_CACHE_LINE_SIZE); 787e8ae9b66SAlan Carew if (global_events_list == NULL) { 788e8ae9b66SAlan Carew RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to rte_malloc for " 789e8ae9b66SAlan Carew "epoll events\n"); 790e8ae9b66SAlan Carew return -1; 791e8ae9b66SAlan Carew } 792e8ae9b66SAlan Carew return 0; 793e8ae9b66SAlan Carew } 794e8ae9b66SAlan Carew 795*a63504a9SDavid Hunt static void 796*a63504a9SDavid Hunt read_binary_packet(struct channel_info *chan_info) 797*a63504a9SDavid Hunt { 798*a63504a9SDavid Hunt struct channel_packet pkt; 799*a63504a9SDavid Hunt void *buffer = &pkt; 800*a63504a9SDavid Hunt int buffer_len = sizeof(pkt); 801*a63504a9SDavid Hunt int n_bytes, err = 0; 802*a63504a9SDavid Hunt 803*a63504a9SDavid Hunt while (buffer_len > 0) { 804*a63504a9SDavid Hunt n_bytes = read(chan_info->fd, 805*a63504a9SDavid Hunt buffer, buffer_len); 806*a63504a9SDavid Hunt if (n_bytes == buffer_len) 807*a63504a9SDavid Hunt break; 808*a63504a9SDavid Hunt if (n_bytes == -1) { 809*a63504a9SDavid Hunt err = errno; 810*a63504a9SDavid Hunt RTE_LOG(DEBUG, CHANNEL_MONITOR, 811*a63504a9SDavid Hunt "Received error on " 812*a63504a9SDavid Hunt "channel '%s' read: %s\n", 813*a63504a9SDavid Hunt chan_info->channel_path, 814*a63504a9SDavid Hunt strerror(err)); 815*a63504a9SDavid Hunt remove_channel(&chan_info); 816*a63504a9SDavid Hunt break; 817*a63504a9SDavid Hunt } 818*a63504a9SDavid Hunt buffer = (char *)buffer + n_bytes; 819*a63504a9SDavid Hunt buffer_len -= n_bytes; 820*a63504a9SDavid Hunt } 821*a63504a9SDavid Hunt if (!err) 822*a63504a9SDavid Hunt process_request(&pkt, chan_info); 823*a63504a9SDavid Hunt } 824*a63504a9SDavid Hunt 825*a63504a9SDavid Hunt #ifdef USE_JANSSON 826*a63504a9SDavid Hunt static void 827*a63504a9SDavid Hunt read_json_packet(struct channel_info *chan_info) 828*a63504a9SDavid Hunt { 829*a63504a9SDavid Hunt struct channel_packet pkt; 830*a63504a9SDavid Hunt int n_bytes, ret; 831*a63504a9SDavid Hunt json_t *root; 832*a63504a9SDavid Hunt json_error_t error; 833*a63504a9SDavid Hunt 834*a63504a9SDavid Hunt /* read opening brace to closing brace */ 835*a63504a9SDavid Hunt do { 836*a63504a9SDavid Hunt int idx = 0; 837*a63504a9SDavid Hunt int indent = 0; 838*a63504a9SDavid Hunt do { 839*a63504a9SDavid Hunt n_bytes = read(chan_info->fd, &json_data[idx], 1); 840*a63504a9SDavid Hunt if (n_bytes == 0) 841*a63504a9SDavid Hunt break; 842*a63504a9SDavid Hunt if (json_data[idx] == '{') 843*a63504a9SDavid Hunt indent++; 844*a63504a9SDavid Hunt if (json_data[idx] == '}') 845*a63504a9SDavid Hunt indent--; 846*a63504a9SDavid Hunt if ((indent > 0) || (idx > 0)) 847*a63504a9SDavid Hunt idx++; 848*a63504a9SDavid Hunt if (indent == 0) 849*a63504a9SDavid Hunt json_data[idx] = 0; 850*a63504a9SDavid Hunt if (idx >= MAX_JSON_STRING_LEN-1) 851*a63504a9SDavid Hunt break; 852*a63504a9SDavid Hunt } while (indent > 0); 853*a63504a9SDavid Hunt 854*a63504a9SDavid Hunt if (indent > 0) 855*a63504a9SDavid Hunt /* 856*a63504a9SDavid Hunt * We've broken out of the read loop without getting 857*a63504a9SDavid Hunt * a closing brace, so throw away the data 858*a63504a9SDavid Hunt */ 859*a63504a9SDavid Hunt json_data[idx] = 0; 860*a63504a9SDavid Hunt 861*a63504a9SDavid Hunt if (strlen(json_data) == 0) 862*a63504a9SDavid Hunt continue; 863*a63504a9SDavid Hunt 864*a63504a9SDavid Hunt printf("got [%s]\n", json_data); 865*a63504a9SDavid Hunt 866*a63504a9SDavid Hunt root = json_loads(json_data, 0, &error); 867*a63504a9SDavid Hunt 868*a63504a9SDavid Hunt if (root) { 869*a63504a9SDavid Hunt /* 870*a63504a9SDavid Hunt * Because our data is now in the json 871*a63504a9SDavid Hunt * object, we can overwrite the pkt 872*a63504a9SDavid Hunt * with a channel_packet struct, using 873*a63504a9SDavid Hunt * parse_json_to_pkt() 874*a63504a9SDavid Hunt */ 875*a63504a9SDavid Hunt ret = parse_json_to_pkt(root, &pkt); 876*a63504a9SDavid Hunt json_decref(root); 877*a63504a9SDavid Hunt if (ret) { 878*a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 879*a63504a9SDavid Hunt "Error validating JSON profile data\n"); 880*a63504a9SDavid Hunt break; 881*a63504a9SDavid Hunt } 882*a63504a9SDavid Hunt process_request(&pkt, chan_info); 883*a63504a9SDavid Hunt } else { 884*a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 885*a63504a9SDavid Hunt "JSON error on line %d: %s\n", 886*a63504a9SDavid Hunt error.line, error.text); 887*a63504a9SDavid Hunt } 888*a63504a9SDavid Hunt } while (n_bytes > 0); 889*a63504a9SDavid Hunt } 890*a63504a9SDavid Hunt #endif 891*a63504a9SDavid Hunt 892e8ae9b66SAlan Carew void 893e8ae9b66SAlan Carew run_channel_monitor(void) 894e8ae9b66SAlan Carew { 895e8ae9b66SAlan Carew while (run_loop) { 896e8ae9b66SAlan Carew int n_events, i; 897e8ae9b66SAlan Carew 898e8ae9b66SAlan Carew n_events = epoll_wait(global_event_fd, global_events_list, 899e8ae9b66SAlan Carew MAX_EVENTS, 1); 900e8ae9b66SAlan Carew if (!run_loop) 901e8ae9b66SAlan Carew break; 902e8ae9b66SAlan Carew for (i = 0; i < n_events; i++) { 903e8ae9b66SAlan Carew struct channel_info *chan_info = (struct channel_info *) 904e8ae9b66SAlan Carew global_events_list[i].data.ptr; 905e8ae9b66SAlan Carew if ((global_events_list[i].events & EPOLLERR) || 906e8ae9b66SAlan Carew (global_events_list[i].events & EPOLLHUP)) { 907e8ae9b66SAlan Carew RTE_LOG(DEBUG, CHANNEL_MONITOR, "Remote closed connection for " 908f14791a8SRory Sexton "channel '%s'\n", 909f14791a8SRory Sexton chan_info->channel_path); 910e8ae9b66SAlan Carew remove_channel(&chan_info); 911e8ae9b66SAlan Carew continue; 912e8ae9b66SAlan Carew } 913e8ae9b66SAlan Carew if (global_events_list[i].events & EPOLLIN) { 914e8ae9b66SAlan Carew 915*a63504a9SDavid Hunt switch (chan_info->type) { 916*a63504a9SDavid Hunt case CHANNEL_TYPE_BINARY: 917*a63504a9SDavid Hunt read_binary_packet(chan_info); 918e8ae9b66SAlan Carew break; 919*a63504a9SDavid Hunt #ifdef USE_JANSSON 920*a63504a9SDavid Hunt case CHANNEL_TYPE_JSON: 921*a63504a9SDavid Hunt read_json_packet(chan_info); 922*a63504a9SDavid Hunt break; 923*a63504a9SDavid Hunt #endif 924*a63504a9SDavid Hunt default: 925e8ae9b66SAlan Carew break; 926e8ae9b66SAlan Carew } 927e8ae9b66SAlan Carew } 928e8ae9b66SAlan Carew } 929e4f66da3SDavid Hunt rte_delay_us(time_period_ms*1000); 930f14791a8SRory Sexton if (policy_is_set) { 9317abd801fSDavid Hunt int j; 9327abd801fSDavid Hunt 93390a774c4SDavid Hunt for (j = 0; j < MAX_CLIENTS; j++) { 934f14791a8SRory Sexton if (policies[j].enabled == 1) 935f14791a8SRory Sexton apply_policy(&policies[j]); 936f14791a8SRory Sexton } 937f14791a8SRory Sexton } 938e8ae9b66SAlan Carew } 939e8ae9b66SAlan Carew } 940