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 246723c0fcSBruce Richardson #include <rte_string_fns.h> 25e8ae9b66SAlan Carew #include <rte_log.h> 26e8ae9b66SAlan Carew #include <rte_memory.h> 27e8ae9b66SAlan Carew #include <rte_malloc.h> 28e8ae9b66SAlan Carew #include <rte_atomic.h> 29f14791a8SRory Sexton #include <rte_cycles.h> 30f14791a8SRory Sexton #include <rte_ethdev.h> 31f14791a8SRory Sexton #include <rte_pmd_i40e.h> 32e8ae9b66SAlan Carew 33f14791a8SRory Sexton #include <libvirt/libvirt.h> 34e8ae9b66SAlan Carew #include "channel_monitor.h" 35e8ae9b66SAlan Carew #include "channel_commands.h" 36e8ae9b66SAlan Carew #include "channel_manager.h" 37e8ae9b66SAlan Carew #include "power_manager.h" 38b89168efSDavid Hunt #include "oob_monitor.h" 39e8ae9b66SAlan Carew 40e8ae9b66SAlan Carew #define RTE_LOGTYPE_CHANNEL_MONITOR RTE_LOGTYPE_USER1 41e8ae9b66SAlan Carew 42e8ae9b66SAlan Carew #define MAX_EVENTS 256 43e8ae9b66SAlan Carew 44f14791a8SRory Sexton uint64_t vsi_pkt_count_prev[384]; 45f14791a8SRory Sexton uint64_t rdtsc_prev[384]; 46a63504a9SDavid Hunt #define MAX_JSON_STRING_LEN 1024 47a63504a9SDavid Hunt char json_data[MAX_JSON_STRING_LEN]; 48e8ae9b66SAlan Carew 49e4f66da3SDavid Hunt double time_period_ms = 1; 50e8ae9b66SAlan Carew static volatile unsigned run_loop = 1; 51e8ae9b66SAlan Carew static int global_event_fd; 52f14791a8SRory Sexton static unsigned int policy_is_set; 53e8ae9b66SAlan Carew static struct epoll_event *global_events_list; 54*221e7026SMarcin Hajkowski static struct policy policies[RTE_MAX_LCORE]; 55e8ae9b66SAlan Carew 56a63504a9SDavid Hunt #ifdef USE_JANSSON 57a63504a9SDavid Hunt 58a63504a9SDavid Hunt union PFID { 596d13ea8eSOlivier Matz struct rte_ether_addr addr; 60a63504a9SDavid Hunt uint64_t pfid; 61a63504a9SDavid Hunt }; 62a63504a9SDavid Hunt 63a63504a9SDavid Hunt static int 646d13ea8eSOlivier Matz str_to_ether_addr(const char *a, struct rte_ether_addr *ether_addr) 65a63504a9SDavid Hunt { 66a63504a9SDavid Hunt int i; 67a63504a9SDavid Hunt char *end; 6835b2d13fSOlivier Matz unsigned long o[RTE_ETHER_ADDR_LEN]; 69a63504a9SDavid Hunt 70a63504a9SDavid Hunt i = 0; 71a63504a9SDavid Hunt do { 72a63504a9SDavid Hunt errno = 0; 73a63504a9SDavid Hunt o[i] = strtoul(a, &end, 16); 74a63504a9SDavid Hunt if (errno != 0 || end == a || (end[0] != ':' && end[0] != 0)) 75a63504a9SDavid Hunt return -1; 76a63504a9SDavid Hunt a = end + 1; 77a63504a9SDavid Hunt } while (++i != RTE_DIM(o) / sizeof(o[0]) && end[0] != 0); 78a63504a9SDavid Hunt 79a63504a9SDavid Hunt /* Junk at the end of line */ 80a63504a9SDavid Hunt if (end[0] != 0) 81a63504a9SDavid Hunt return -1; 82a63504a9SDavid Hunt 83a63504a9SDavid Hunt /* Support the format XX:XX:XX:XX:XX:XX */ 8435b2d13fSOlivier Matz if (i == RTE_ETHER_ADDR_LEN) { 85a63504a9SDavid Hunt while (i-- != 0) { 86a63504a9SDavid Hunt if (o[i] > UINT8_MAX) 87a63504a9SDavid Hunt return -1; 88a63504a9SDavid Hunt ether_addr->addr_bytes[i] = (uint8_t)o[i]; 89a63504a9SDavid Hunt } 90a63504a9SDavid Hunt /* Support the format XXXX:XXXX:XXXX */ 9135b2d13fSOlivier Matz } else if (i == RTE_ETHER_ADDR_LEN / 2) { 92a63504a9SDavid Hunt while (i-- != 0) { 93a63504a9SDavid Hunt if (o[i] > UINT16_MAX) 94a63504a9SDavid Hunt return -1; 95a63504a9SDavid Hunt ether_addr->addr_bytes[i * 2] = 96a63504a9SDavid Hunt (uint8_t)(o[i] >> 8); 97a63504a9SDavid Hunt ether_addr->addr_bytes[i * 2 + 1] = 98a63504a9SDavid Hunt (uint8_t)(o[i] & 0xff); 99a63504a9SDavid Hunt } 100a63504a9SDavid Hunt /* unknown format */ 101a63504a9SDavid Hunt } else 102a63504a9SDavid Hunt return -1; 103a63504a9SDavid Hunt 104a63504a9SDavid Hunt return 0; 105a63504a9SDavid Hunt } 106a63504a9SDavid Hunt 107a63504a9SDavid Hunt static int 108a63504a9SDavid Hunt set_policy_mac(struct channel_packet *pkt, int idx, char *mac) 109a63504a9SDavid Hunt { 110a63504a9SDavid Hunt union PFID pfid; 111a63504a9SDavid Hunt int ret; 112a63504a9SDavid Hunt 113a63504a9SDavid Hunt /* Use port MAC address as the vfid */ 114a63504a9SDavid Hunt ret = str_to_ether_addr(mac, &pfid.addr); 115a63504a9SDavid Hunt 116a63504a9SDavid Hunt if (ret != 0) { 117a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 118a63504a9SDavid Hunt "Invalid mac address received in JSON\n"); 119a63504a9SDavid Hunt pkt->vfid[idx] = 0; 120a63504a9SDavid Hunt return -1; 121a63504a9SDavid Hunt } 122a63504a9SDavid Hunt 123a63504a9SDavid Hunt printf("Received MAC Address: %02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 ":" 124a63504a9SDavid Hunt "%02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 "\n", 125a63504a9SDavid Hunt pfid.addr.addr_bytes[0], pfid.addr.addr_bytes[1], 126a63504a9SDavid Hunt pfid.addr.addr_bytes[2], pfid.addr.addr_bytes[3], 127a63504a9SDavid Hunt pfid.addr.addr_bytes[4], pfid.addr.addr_bytes[5]); 128a63504a9SDavid Hunt 129a63504a9SDavid Hunt pkt->vfid[idx] = pfid.pfid; 130a63504a9SDavid Hunt return 0; 131a63504a9SDavid Hunt } 132a63504a9SDavid Hunt 133*221e7026SMarcin Hajkowski static char* 134*221e7026SMarcin Hajkowski get_resource_name_from_chn_path(const char *channel_path) 135*221e7026SMarcin Hajkowski { 136*221e7026SMarcin Hajkowski char *substr = NULL; 137*221e7026SMarcin Hajkowski 138*221e7026SMarcin Hajkowski substr = strstr(channel_path, CHANNEL_MGR_FIFO_PATTERN_NAME); 139*221e7026SMarcin Hajkowski 140*221e7026SMarcin Hajkowski return substr; 141*221e7026SMarcin Hajkowski } 142a63504a9SDavid Hunt 143a63504a9SDavid Hunt static int 144*221e7026SMarcin Hajkowski get_resource_id_from_vmname(const char *vm_name) 145*221e7026SMarcin Hajkowski { 146*221e7026SMarcin Hajkowski int result = -1; 147*221e7026SMarcin Hajkowski int off = 0; 148*221e7026SMarcin Hajkowski 149*221e7026SMarcin Hajkowski if (vm_name == NULL) 150*221e7026SMarcin Hajkowski return -1; 151*221e7026SMarcin Hajkowski 152*221e7026SMarcin Hajkowski while (vm_name[off] != '\0') { 153*221e7026SMarcin Hajkowski if (isdigit(vm_name[off])) 154*221e7026SMarcin Hajkowski break; 155*221e7026SMarcin Hajkowski off++; 156*221e7026SMarcin Hajkowski } 157*221e7026SMarcin Hajkowski result = atoi(&vm_name[off]); 158*221e7026SMarcin Hajkowski if ((result == 0) && (vm_name[off] != '0')) 159*221e7026SMarcin Hajkowski return -1; 160*221e7026SMarcin Hajkowski 161*221e7026SMarcin Hajkowski return result; 162*221e7026SMarcin Hajkowski } 163*221e7026SMarcin Hajkowski 164*221e7026SMarcin Hajkowski static int 165*221e7026SMarcin Hajkowski parse_json_to_pkt(json_t *element, struct channel_packet *pkt, 166*221e7026SMarcin Hajkowski const char *vm_name) 167a63504a9SDavid Hunt { 168a63504a9SDavid Hunt const char *key; 169a63504a9SDavid Hunt json_t *value; 170a63504a9SDavid Hunt int ret; 171*221e7026SMarcin Hajkowski int resource_id; 172a63504a9SDavid Hunt 173a63504a9SDavid Hunt memset(pkt, 0, sizeof(struct channel_packet)); 174a63504a9SDavid Hunt 175a63504a9SDavid Hunt pkt->nb_mac_to_monitor = 0; 176a63504a9SDavid Hunt pkt->t_boost_status.tbEnabled = false; 177a63504a9SDavid Hunt pkt->workload = LOW; 178a63504a9SDavid Hunt pkt->policy_to_use = TIME; 179a63504a9SDavid Hunt pkt->command = PKT_POLICY; 180a63504a9SDavid Hunt pkt->core_type = CORE_TYPE_PHYSICAL; 181a63504a9SDavid Hunt 182*221e7026SMarcin Hajkowski if (vm_name == NULL) { 183*221e7026SMarcin Hajkowski RTE_LOG(ERR, CHANNEL_MONITOR, 184*221e7026SMarcin Hajkowski "vm_name is NULL, request rejected !\n"); 185*221e7026SMarcin Hajkowski return -1; 186*221e7026SMarcin Hajkowski } 187*221e7026SMarcin Hajkowski 188a63504a9SDavid Hunt json_object_foreach(element, key, value) { 189a63504a9SDavid Hunt if (!strcmp(key, "policy")) { 190a63504a9SDavid Hunt /* Recurse in to get the contents of profile */ 191*221e7026SMarcin Hajkowski ret = parse_json_to_pkt(value, pkt, vm_name); 192a63504a9SDavid Hunt if (ret) 193a63504a9SDavid Hunt return ret; 194a63504a9SDavid Hunt } else if (!strcmp(key, "instruction")) { 195a63504a9SDavid Hunt /* Recurse in to get the contents of instruction */ 196*221e7026SMarcin Hajkowski ret = parse_json_to_pkt(value, pkt, vm_name); 197a63504a9SDavid Hunt if (ret) 198a63504a9SDavid Hunt return ret; 199a63504a9SDavid Hunt } else if (!strcmp(key, "command")) { 200a63504a9SDavid Hunt char command[32]; 2016723c0fcSBruce Richardson strlcpy(command, json_string_value(value), 32); 202a63504a9SDavid Hunt if (!strcmp(command, "power")) { 203a63504a9SDavid Hunt pkt->command = CPU_POWER; 204a63504a9SDavid Hunt } else if (!strcmp(command, "create")) { 205a63504a9SDavid Hunt pkt->command = PKT_POLICY; 206a63504a9SDavid Hunt } else if (!strcmp(command, "destroy")) { 207a63504a9SDavid Hunt pkt->command = PKT_POLICY_REMOVE; 208a63504a9SDavid Hunt } else { 209a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 210a63504a9SDavid Hunt "Invalid command received in JSON\n"); 211a63504a9SDavid Hunt return -1; 212a63504a9SDavid Hunt } 213a63504a9SDavid Hunt } else if (!strcmp(key, "policy_type")) { 214a63504a9SDavid Hunt char command[32]; 2156723c0fcSBruce Richardson strlcpy(command, json_string_value(value), 32); 216a63504a9SDavid Hunt if (!strcmp(command, "TIME")) { 217a63504a9SDavid Hunt pkt->policy_to_use = TIME; 218a63504a9SDavid Hunt } else if (!strcmp(command, "TRAFFIC")) { 219a63504a9SDavid Hunt pkt->policy_to_use = TRAFFIC; 220a63504a9SDavid Hunt } else if (!strcmp(command, "WORKLOAD")) { 221a63504a9SDavid Hunt pkt->policy_to_use = WORKLOAD; 222a63504a9SDavid Hunt } else if (!strcmp(command, "BRANCH_RATIO")) { 223a63504a9SDavid Hunt pkt->policy_to_use = BRANCH_RATIO; 224a63504a9SDavid Hunt } else { 225a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 226a63504a9SDavid Hunt "Wrong policy_type received in JSON\n"); 227a63504a9SDavid Hunt return -1; 228a63504a9SDavid Hunt } 229a63504a9SDavid Hunt } else if (!strcmp(key, "workload")) { 230a63504a9SDavid Hunt char command[32]; 2316723c0fcSBruce Richardson strlcpy(command, json_string_value(value), 32); 232a63504a9SDavid Hunt if (!strcmp(command, "HIGH")) { 233a63504a9SDavid Hunt pkt->workload = HIGH; 234a63504a9SDavid Hunt } else if (!strcmp(command, "MEDIUM")) { 235a63504a9SDavid Hunt pkt->workload = MEDIUM; 236a63504a9SDavid Hunt } else if (!strcmp(command, "LOW")) { 237a63504a9SDavid Hunt pkt->workload = LOW; 238a63504a9SDavid Hunt } else { 239a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 240a63504a9SDavid Hunt "Wrong workload received in JSON\n"); 241a63504a9SDavid Hunt return -1; 242a63504a9SDavid Hunt } 243a63504a9SDavid Hunt } else if (!strcmp(key, "busy_hours")) { 244a63504a9SDavid Hunt unsigned int i; 245a63504a9SDavid Hunt size_t size = json_array_size(value); 246a63504a9SDavid Hunt 247a63504a9SDavid Hunt for (i = 0; i < size; i++) { 248a63504a9SDavid Hunt int hour = (int)json_integer_value( 249a63504a9SDavid Hunt json_array_get(value, i)); 250a63504a9SDavid Hunt pkt->timer_policy.busy_hours[i] = hour; 251a63504a9SDavid Hunt } 252a63504a9SDavid Hunt } else if (!strcmp(key, "quiet_hours")) { 253a63504a9SDavid Hunt unsigned int i; 254a63504a9SDavid Hunt size_t size = json_array_size(value); 255a63504a9SDavid Hunt 256a63504a9SDavid Hunt for (i = 0; i < size; i++) { 257a63504a9SDavid Hunt int hour = (int)json_integer_value( 258a63504a9SDavid Hunt json_array_get(value, i)); 259a63504a9SDavid Hunt pkt->timer_policy.quiet_hours[i] = hour; 260a63504a9SDavid Hunt } 261a63504a9SDavid Hunt } else if (!strcmp(key, "mac_list")) { 262a63504a9SDavid Hunt unsigned int i; 263a63504a9SDavid Hunt size_t size = json_array_size(value); 264a63504a9SDavid Hunt 265a63504a9SDavid Hunt for (i = 0; i < size; i++) { 266a63504a9SDavid Hunt char mac[32]; 2676723c0fcSBruce Richardson strlcpy(mac, 2686723c0fcSBruce Richardson json_string_value(json_array_get(value, i)), 2696723c0fcSBruce Richardson 32); 270a63504a9SDavid Hunt set_policy_mac(pkt, i, mac); 271a63504a9SDavid Hunt } 272a63504a9SDavid Hunt pkt->nb_mac_to_monitor = size; 273a63504a9SDavid Hunt } else if (!strcmp(key, "avg_packet_thresh")) { 274a63504a9SDavid Hunt pkt->traffic_policy.avg_max_packet_thresh = 275a63504a9SDavid Hunt (uint32_t)json_integer_value(value); 276a63504a9SDavid Hunt } else if (!strcmp(key, "max_packet_thresh")) { 277a63504a9SDavid Hunt pkt->traffic_policy.max_max_packet_thresh = 278a63504a9SDavid Hunt (uint32_t)json_integer_value(value); 279a63504a9SDavid Hunt } else if (!strcmp(key, "unit")) { 280a63504a9SDavid Hunt char unit[32]; 2816723c0fcSBruce Richardson strlcpy(unit, json_string_value(value), 32); 282a63504a9SDavid Hunt if (!strcmp(unit, "SCALE_UP")) { 283a63504a9SDavid Hunt pkt->unit = CPU_POWER_SCALE_UP; 284a63504a9SDavid Hunt } else if (!strcmp(unit, "SCALE_DOWN")) { 285a63504a9SDavid Hunt pkt->unit = CPU_POWER_SCALE_DOWN; 286a63504a9SDavid Hunt } else if (!strcmp(unit, "SCALE_MAX")) { 287a63504a9SDavid Hunt pkt->unit = CPU_POWER_SCALE_MAX; 288a63504a9SDavid Hunt } else if (!strcmp(unit, "SCALE_MIN")) { 289a63504a9SDavid Hunt pkt->unit = CPU_POWER_SCALE_MIN; 290a63504a9SDavid Hunt } else if (!strcmp(unit, "ENABLE_TURBO")) { 291a63504a9SDavid Hunt pkt->unit = CPU_POWER_ENABLE_TURBO; 292a63504a9SDavid Hunt } else if (!strcmp(unit, "DISABLE_TURBO")) { 293a63504a9SDavid Hunt pkt->unit = CPU_POWER_DISABLE_TURBO; 294a63504a9SDavid Hunt } else { 295a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 296a63504a9SDavid Hunt "Invalid command received in JSON\n"); 297a63504a9SDavid Hunt return -1; 298a63504a9SDavid Hunt } 299a63504a9SDavid Hunt } else { 300a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 301a63504a9SDavid Hunt "Unknown key received in JSON string: %s\n", 302a63504a9SDavid Hunt key); 303a63504a9SDavid Hunt } 304*221e7026SMarcin Hajkowski 305*221e7026SMarcin Hajkowski resource_id = get_resource_id_from_vmname(vm_name); 306*221e7026SMarcin Hajkowski if (resource_id < 0) { 307*221e7026SMarcin Hajkowski RTE_LOG(ERR, CHANNEL_MONITOR, 308*221e7026SMarcin Hajkowski "Could not get resource_id from vm_name:%s\n", 309*221e7026SMarcin Hajkowski vm_name); 310*221e7026SMarcin Hajkowski return -1; 311*221e7026SMarcin Hajkowski } 312*221e7026SMarcin Hajkowski rte_strlcpy(pkt->vm_name, vm_name, VM_MAX_NAME_SZ); 313*221e7026SMarcin Hajkowski pkt->resource_id = resource_id; 314a63504a9SDavid Hunt } 315a63504a9SDavid Hunt return 0; 316a63504a9SDavid Hunt } 317a63504a9SDavid Hunt #endif 318a63504a9SDavid Hunt 319e8ae9b66SAlan Carew void channel_monitor_exit(void) 320e8ae9b66SAlan Carew { 321e8ae9b66SAlan Carew run_loop = 0; 322e8ae9b66SAlan Carew rte_free(global_events_list); 323e8ae9b66SAlan Carew } 324e8ae9b66SAlan Carew 325f14791a8SRory Sexton static void 326f14791a8SRory Sexton core_share(int pNo, int z, int x, int t) 327f14791a8SRory Sexton { 328f14791a8SRory Sexton if (policies[pNo].core_share[z].pcpu == lvm_info[x].pcpus[t]) { 329f14791a8SRory Sexton if (strcmp(policies[pNo].pkt.vm_name, 330f14791a8SRory Sexton lvm_info[x].vm_name) != 0) { 331f14791a8SRory Sexton policies[pNo].core_share[z].status = 1; 332f14791a8SRory Sexton power_manager_scale_core_max( 333f14791a8SRory Sexton policies[pNo].core_share[z].pcpu); 334f14791a8SRory Sexton } 335f14791a8SRory Sexton } 336f14791a8SRory Sexton } 337f14791a8SRory Sexton 338f14791a8SRory Sexton static void 339f14791a8SRory Sexton core_share_status(int pNo) 340f14791a8SRory Sexton { 341f14791a8SRory Sexton 342395e97bfSDavid Hunt int noVms = 0, noVcpus = 0, z, x, t; 343f14791a8SRory Sexton 344f14791a8SRory Sexton get_all_vm(&noVms, &noVcpus); 345f14791a8SRory Sexton 346f14791a8SRory Sexton /* Reset Core Share Status. */ 347f14791a8SRory Sexton for (z = 0; z < noVcpus; z++) 348f14791a8SRory Sexton policies[pNo].core_share[z].status = 0; 349f14791a8SRory Sexton 350f14791a8SRory Sexton /* Foreach vcpu in a policy. */ 351f14791a8SRory Sexton for (z = 0; z < policies[pNo].pkt.num_vcpu; z++) { 352f14791a8SRory Sexton /* Foreach VM on the platform. */ 353f14791a8SRory Sexton for (x = 0; x < noVms; x++) { 354f14791a8SRory Sexton /* Foreach vcpu of VMs on platform. */ 355f14791a8SRory Sexton for (t = 0; t < lvm_info[x].num_cpus; t++) 356f14791a8SRory Sexton core_share(pNo, z, x, t); 357f14791a8SRory Sexton } 358f14791a8SRory Sexton } 359f14791a8SRory Sexton } 360f14791a8SRory Sexton 3613618326fSDavid Hunt 3623618326fSDavid Hunt static int 3633618326fSDavid Hunt pcpu_monitor(struct policy *pol, struct core_info *ci, int pcpu, int count) 3643618326fSDavid Hunt { 3653618326fSDavid Hunt int ret = 0; 3663618326fSDavid Hunt 3673618326fSDavid Hunt if (pol->pkt.policy_to_use == BRANCH_RATIO) { 3683618326fSDavid Hunt ci->cd[pcpu].oob_enabled = 1; 3693618326fSDavid Hunt ret = add_core_to_monitor(pcpu); 3703618326fSDavid Hunt if (ret == 0) 3713618326fSDavid Hunt RTE_LOG(INFO, CHANNEL_MONITOR, 3723618326fSDavid Hunt "Monitoring pcpu %d OOB for %s\n", 3733618326fSDavid Hunt pcpu, pol->pkt.vm_name); 3743618326fSDavid Hunt else 3753618326fSDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 3763618326fSDavid Hunt "Error monitoring pcpu %d OOB for %s\n", 3773618326fSDavid Hunt pcpu, pol->pkt.vm_name); 3783618326fSDavid Hunt 3793618326fSDavid Hunt } else { 3803618326fSDavid Hunt pol->core_share[count].pcpu = pcpu; 3813618326fSDavid Hunt RTE_LOG(INFO, CHANNEL_MONITOR, 3823618326fSDavid Hunt "Monitoring pcpu %d for %s\n", 3833618326fSDavid Hunt pcpu, pol->pkt.vm_name); 3843618326fSDavid Hunt } 3853618326fSDavid Hunt return ret; 3863618326fSDavid Hunt } 3873618326fSDavid Hunt 388f14791a8SRory Sexton static void 389f14791a8SRory Sexton get_pcpu_to_control(struct policy *pol) 390f14791a8SRory Sexton { 391f14791a8SRory Sexton 392f14791a8SRory Sexton /* Convert vcpu to pcpu. */ 393f14791a8SRory Sexton struct vm_info info; 394f14791a8SRory Sexton int pcpu, count; 395b89168efSDavid Hunt struct core_info *ci; 396b89168efSDavid Hunt 397b89168efSDavid Hunt ci = get_core_info(); 398f14791a8SRory Sexton 399ce4a2766SDavid Hunt RTE_LOG(DEBUG, CHANNEL_MONITOR, 4003618326fSDavid Hunt "Looking for pcpu for %s\n", pol->pkt.vm_name); 4013618326fSDavid Hunt 4023618326fSDavid Hunt /* 4033618326fSDavid Hunt * So now that we're handling virtual and physical cores, we need to 4043618326fSDavid Hunt * differenciate between them when adding them to the branch monitor. 4053618326fSDavid Hunt * Virtual cores need to be converted to physical cores. 4063618326fSDavid Hunt */ 4073618326fSDavid Hunt if (pol->pkt.core_type == CORE_TYPE_VIRTUAL) { 4083618326fSDavid Hunt /* 4093618326fSDavid Hunt * If the cores in the policy are virtual, we need to map them 4103618326fSDavid Hunt * to physical core. We look up the vm info and use that for 4113618326fSDavid Hunt * the mapping. 4123618326fSDavid Hunt */ 413f14791a8SRory Sexton get_info_vm(pol->pkt.vm_name, &info); 414f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 4155776b7a3SDavid Hunt pcpu = info.pcpu_map[pol->pkt.vcpu_to_control[count]]; 4163618326fSDavid Hunt pcpu_monitor(pol, ci, pcpu, count); 4173618326fSDavid Hunt } 418b89168efSDavid Hunt } else { 4193618326fSDavid Hunt /* 4203618326fSDavid Hunt * If the cores in the policy are physical, we just use 4213618326fSDavid Hunt * those core id's directly. 4223618326fSDavid Hunt */ 4233618326fSDavid Hunt for (count = 0; count < pol->pkt.num_vcpu; count++) { 4243618326fSDavid Hunt pcpu = pol->pkt.vcpu_to_control[count]; 4253618326fSDavid Hunt pcpu_monitor(pol, ci, pcpu, count); 426f14791a8SRory Sexton } 427f14791a8SRory Sexton } 428f14791a8SRory Sexton } 429f14791a8SRory Sexton 430f14791a8SRory Sexton static int 431f14791a8SRory Sexton get_pfid(struct policy *pol) 432f14791a8SRory Sexton { 433f14791a8SRory Sexton 4348728ccf3SThomas Monjalon int i, x, ret = 0; 435f14791a8SRory Sexton 436f14791a8SRory Sexton for (i = 0; i < pol->pkt.nb_mac_to_monitor; i++) { 437f14791a8SRory Sexton 4388728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(x) { 439f14791a8SRory Sexton ret = rte_pmd_i40e_query_vfid_by_mac(x, 4406d13ea8eSOlivier Matz (struct rte_ether_addr *)&(pol->pkt.vfid[i])); 441f14791a8SRory Sexton if (ret != -EINVAL) { 442f14791a8SRory Sexton pol->port[i] = x; 443f14791a8SRory Sexton break; 444f14791a8SRory Sexton } 445f14791a8SRory Sexton } 446f14791a8SRory Sexton if (ret == -EINVAL || ret == -ENOTSUP || ret == ENODEV) { 447f14791a8SRory Sexton RTE_LOG(INFO, CHANNEL_MONITOR, 448f14791a8SRory Sexton "Error with Policy. MAC not found on " 449f14791a8SRory Sexton "attached ports "); 450f14791a8SRory Sexton pol->enabled = 0; 451f14791a8SRory Sexton return ret; 452f14791a8SRory Sexton } 453f14791a8SRory Sexton pol->pfid[i] = ret; 454f14791a8SRory Sexton } 455f14791a8SRory Sexton return 1; 456f14791a8SRory Sexton } 457f14791a8SRory Sexton 458f14791a8SRory Sexton static int 459f14791a8SRory Sexton update_policy(struct channel_packet *pkt) 460f14791a8SRory Sexton { 461f14791a8SRory Sexton 462f14791a8SRory Sexton unsigned int updated = 0; 463*221e7026SMarcin Hajkowski unsigned int i; 464f14791a8SRory Sexton 4653618326fSDavid Hunt 4663618326fSDavid Hunt RTE_LOG(INFO, CHANNEL_MONITOR, 4673618326fSDavid Hunt "Applying policy for %s\n", pkt->vm_name); 4683618326fSDavid Hunt 469*221e7026SMarcin Hajkowski for (i = 0; i < RTE_DIM(policies); i++) { 470f14791a8SRory Sexton if (strcmp(policies[i].pkt.vm_name, pkt->vm_name) == 0) { 4713618326fSDavid Hunt /* Copy the contents of *pkt into the policy.pkt */ 472f14791a8SRory Sexton policies[i].pkt = *pkt; 473f14791a8SRory Sexton get_pcpu_to_control(&policies[i]); 474236e164bSLukasz Krakowiak /* Check Eth dev only for Traffic policy */ 475236e164bSLukasz Krakowiak if (policies[i].pkt.policy_to_use == TRAFFIC) { 4761b897991SLukasz Krakowiak if (get_pfid(&policies[i]) < 0) { 477f14791a8SRory Sexton updated = 1; 478f14791a8SRory Sexton break; 479f14791a8SRory Sexton } 480236e164bSLukasz Krakowiak } 481f14791a8SRory Sexton core_share_status(i); 482f14791a8SRory Sexton policies[i].enabled = 1; 483f14791a8SRory Sexton updated = 1; 484f14791a8SRory Sexton } 485f14791a8SRory Sexton } 486f14791a8SRory Sexton if (!updated) { 487*221e7026SMarcin Hajkowski for (i = 0; i < RTE_DIM(policies); i++) { 488f14791a8SRory Sexton if (policies[i].enabled == 0) { 489f14791a8SRory Sexton policies[i].pkt = *pkt; 490f14791a8SRory Sexton get_pcpu_to_control(&policies[i]); 491236e164bSLukasz Krakowiak /* Check Eth dev only for Traffic policy */ 492236e164bSLukasz Krakowiak if (policies[i].pkt.policy_to_use == TRAFFIC) { 493236e164bSLukasz Krakowiak if (get_pfid(&policies[i]) < 0) { 494236e164bSLukasz Krakowiak updated = 1; 495f14791a8SRory Sexton break; 496236e164bSLukasz Krakowiak } 497236e164bSLukasz Krakowiak } 498f14791a8SRory Sexton core_share_status(i); 499f14791a8SRory Sexton policies[i].enabled = 1; 500f14791a8SRory Sexton break; 501f14791a8SRory Sexton } 502f14791a8SRory Sexton } 503f14791a8SRory Sexton } 504f14791a8SRory Sexton return 0; 505f14791a8SRory Sexton } 506f14791a8SRory Sexton 5073618326fSDavid Hunt static int 5083618326fSDavid Hunt remove_policy(struct channel_packet *pkt __rte_unused) 5093618326fSDavid Hunt { 510*221e7026SMarcin Hajkowski unsigned int i; 5113618326fSDavid Hunt 5123618326fSDavid Hunt /* 5133618326fSDavid Hunt * Disabling the policy is simply a case of setting 5143618326fSDavid Hunt * enabled to 0 5153618326fSDavid Hunt */ 516*221e7026SMarcin Hajkowski for (i = 0; i < RTE_DIM(policies); i++) { 5173618326fSDavid Hunt if (strcmp(policies[i].pkt.vm_name, pkt->vm_name) == 0) { 5183618326fSDavid Hunt policies[i].enabled = 0; 5193618326fSDavid Hunt return 0; 5203618326fSDavid Hunt } 5213618326fSDavid Hunt } 5223618326fSDavid Hunt return -1; 5233618326fSDavid Hunt } 5243618326fSDavid Hunt 525f14791a8SRory Sexton static uint64_t 526f14791a8SRory Sexton get_pkt_diff(struct policy *pol) 527f14791a8SRory Sexton { 528f14791a8SRory Sexton 529f14791a8SRory Sexton uint64_t vsi_pkt_count, 530f14791a8SRory Sexton vsi_pkt_total = 0, 531f14791a8SRory Sexton vsi_pkt_count_prev_total = 0; 532f14791a8SRory Sexton double rdtsc_curr, rdtsc_diff, diff; 533f14791a8SRory Sexton int x; 534f14791a8SRory Sexton struct rte_eth_stats vf_stats; 535f14791a8SRory Sexton 536f14791a8SRory Sexton for (x = 0; x < pol->pkt.nb_mac_to_monitor; x++) { 537f14791a8SRory Sexton 538f14791a8SRory Sexton /*Read vsi stats*/ 539f14791a8SRory Sexton if (rte_pmd_i40e_get_vf_stats(x, pol->pfid[x], &vf_stats) == 0) 540f14791a8SRory Sexton vsi_pkt_count = vf_stats.ipackets; 541f14791a8SRory Sexton else 542f14791a8SRory Sexton vsi_pkt_count = -1; 543f14791a8SRory Sexton 544f14791a8SRory Sexton vsi_pkt_total += vsi_pkt_count; 545f14791a8SRory Sexton 546f14791a8SRory Sexton vsi_pkt_count_prev_total += vsi_pkt_count_prev[pol->pfid[x]]; 547f14791a8SRory Sexton vsi_pkt_count_prev[pol->pfid[x]] = vsi_pkt_count; 548f14791a8SRory Sexton } 549f14791a8SRory Sexton 550f14791a8SRory Sexton rdtsc_curr = rte_rdtsc_precise(); 551f14791a8SRory Sexton rdtsc_diff = rdtsc_curr - rdtsc_prev[pol->pfid[x-1]]; 552f14791a8SRory Sexton rdtsc_prev[pol->pfid[x-1]] = rdtsc_curr; 553f14791a8SRory Sexton 554f14791a8SRory Sexton diff = (vsi_pkt_total - vsi_pkt_count_prev_total) * 555f14791a8SRory Sexton ((double)rte_get_tsc_hz() / rdtsc_diff); 556f14791a8SRory Sexton 557f14791a8SRory Sexton return diff; 558f14791a8SRory Sexton } 559f14791a8SRory Sexton 560f14791a8SRory Sexton static void 561f14791a8SRory Sexton apply_traffic_profile(struct policy *pol) 562f14791a8SRory Sexton { 563f14791a8SRory Sexton 564f14791a8SRory Sexton int count; 565f14791a8SRory Sexton uint64_t diff = 0; 566f14791a8SRory Sexton 567f14791a8SRory Sexton diff = get_pkt_diff(pol); 568f14791a8SRory Sexton 569f14791a8SRory Sexton if (diff >= (pol->pkt.traffic_policy.max_max_packet_thresh)) { 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 } else if (diff >= (pol->pkt.traffic_policy.avg_max_packet_thresh)) { 576f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 577f14791a8SRory Sexton if (pol->core_share[count].status != 1) 578f14791a8SRory Sexton power_manager_scale_core_med( 579f14791a8SRory Sexton pol->core_share[count].pcpu); 580f14791a8SRory Sexton } 581f14791a8SRory Sexton } else if (diff < (pol->pkt.traffic_policy.avg_max_packet_thresh)) { 582f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 583f14791a8SRory Sexton if (pol->core_share[count].status != 1) 584f14791a8SRory Sexton power_manager_scale_core_min( 585f14791a8SRory Sexton pol->core_share[count].pcpu); 586f14791a8SRory Sexton } 587f14791a8SRory Sexton } 588f14791a8SRory Sexton } 589f14791a8SRory Sexton 590f14791a8SRory Sexton static void 591f14791a8SRory Sexton apply_time_profile(struct policy *pol) 592f14791a8SRory Sexton { 593f14791a8SRory Sexton 594f14791a8SRory Sexton int count, x; 595f14791a8SRory Sexton struct timeval tv; 596f14791a8SRory Sexton struct tm *ptm; 597f14791a8SRory Sexton char time_string[40]; 598f14791a8SRory Sexton 599f14791a8SRory Sexton /* Obtain the time of day, and convert it to a tm struct. */ 600f14791a8SRory Sexton gettimeofday(&tv, NULL); 601f14791a8SRory Sexton ptm = localtime(&tv.tv_sec); 602f14791a8SRory Sexton /* Format the date and time, down to a single second. */ 603f14791a8SRory Sexton strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", ptm); 604f14791a8SRory Sexton 605f14791a8SRory Sexton for (x = 0; x < HOURS; x++) { 606f14791a8SRory Sexton 607f14791a8SRory Sexton if (ptm->tm_hour == pol->pkt.timer_policy.busy_hours[x]) { 608f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 609f14791a8SRory Sexton if (pol->core_share[count].status != 1) { 610f14791a8SRory Sexton power_manager_scale_core_max( 611f14791a8SRory Sexton pol->core_share[count].pcpu); 612f14791a8SRory Sexton } 613f14791a8SRory Sexton } 614f14791a8SRory Sexton break; 615f14791a8SRory Sexton } else if (ptm->tm_hour == 616f14791a8SRory Sexton pol->pkt.timer_policy.quiet_hours[x]) { 617f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 618f14791a8SRory Sexton if (pol->core_share[count].status != 1) { 619f14791a8SRory Sexton power_manager_scale_core_min( 620f14791a8SRory Sexton pol->core_share[count].pcpu); 621f14791a8SRory Sexton } 622f14791a8SRory Sexton } 623f14791a8SRory Sexton break; 624f14791a8SRory Sexton } else if (ptm->tm_hour == 625f14791a8SRory Sexton pol->pkt.timer_policy.hours_to_use_traffic_profile[x]) { 626f14791a8SRory Sexton apply_traffic_profile(pol); 627f14791a8SRory Sexton break; 628f14791a8SRory Sexton } 629f14791a8SRory Sexton } 630f14791a8SRory Sexton } 631f14791a8SRory Sexton 632f14791a8SRory Sexton static void 633f14791a8SRory Sexton apply_workload_profile(struct policy *pol) 634f14791a8SRory Sexton { 635f14791a8SRory Sexton 636f14791a8SRory Sexton int count; 637f14791a8SRory Sexton 638f14791a8SRory Sexton if (pol->pkt.workload == HIGH) { 639f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 640f14791a8SRory Sexton if (pol->core_share[count].status != 1) 641f14791a8SRory Sexton power_manager_scale_core_max( 642f14791a8SRory Sexton pol->core_share[count].pcpu); 643f14791a8SRory Sexton } 644f14791a8SRory Sexton } else if (pol->pkt.workload == MEDIUM) { 645f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 646f14791a8SRory Sexton if (pol->core_share[count].status != 1) 647f14791a8SRory Sexton power_manager_scale_core_med( 648f14791a8SRory Sexton pol->core_share[count].pcpu); 649f14791a8SRory Sexton } 650f14791a8SRory Sexton } else if (pol->pkt.workload == LOW) { 651f14791a8SRory Sexton for (count = 0; count < pol->pkt.num_vcpu; count++) { 652f14791a8SRory Sexton if (pol->core_share[count].status != 1) 653f14791a8SRory Sexton power_manager_scale_core_min( 654f14791a8SRory Sexton pol->core_share[count].pcpu); 655f14791a8SRory Sexton } 656f14791a8SRory Sexton } 657f14791a8SRory Sexton } 658f14791a8SRory Sexton 659f14791a8SRory Sexton static void 660f14791a8SRory Sexton apply_policy(struct policy *pol) 661f14791a8SRory Sexton { 662f14791a8SRory Sexton 663f14791a8SRory Sexton struct channel_packet *pkt = &pol->pkt; 664f14791a8SRory Sexton 665f14791a8SRory Sexton /*Check policy to use*/ 666f14791a8SRory Sexton if (pkt->policy_to_use == TRAFFIC) 667f14791a8SRory Sexton apply_traffic_profile(pol); 668f14791a8SRory Sexton else if (pkt->policy_to_use == TIME) 669f14791a8SRory Sexton apply_time_profile(pol); 670f14791a8SRory Sexton else if (pkt->policy_to_use == WORKLOAD) 671f14791a8SRory Sexton apply_workload_profile(pol); 672f14791a8SRory Sexton } 673f14791a8SRory Sexton 674e8ae9b66SAlan Carew static int 675e8ae9b66SAlan Carew process_request(struct channel_packet *pkt, struct channel_info *chan_info) 676e8ae9b66SAlan Carew { 677d7b713d0SLukasz Krakowiak int ret; 678d7b713d0SLukasz Krakowiak 679e8ae9b66SAlan Carew if (chan_info == NULL) 680e8ae9b66SAlan Carew return -1; 681e8ae9b66SAlan Carew 682e8ae9b66SAlan Carew if (rte_atomic32_cmpset(&(chan_info->status), CHANNEL_MGR_CHANNEL_CONNECTED, 683e8ae9b66SAlan Carew CHANNEL_MGR_CHANNEL_PROCESSING) == 0) 684e8ae9b66SAlan Carew return -1; 685e8ae9b66SAlan Carew 686e8ae9b66SAlan Carew if (pkt->command == CPU_POWER) { 6875776b7a3SDavid Hunt unsigned int core_num; 688e8ae9b66SAlan Carew 689d38e6a6aSDavid Hunt if (pkt->core_type == CORE_TYPE_VIRTUAL) 6905776b7a3SDavid Hunt core_num = get_pcpu(chan_info, pkt->resource_id); 691d38e6a6aSDavid Hunt else 692d38e6a6aSDavid Hunt core_num = pkt->resource_id; 693e8ae9b66SAlan Carew 694d7b713d0SLukasz Krakowiak RTE_LOG(DEBUG, CHANNEL_MONITOR, "Processing requested cmd for cpu:%d\n", 695d7b713d0SLukasz Krakowiak core_num); 696d7b713d0SLukasz Krakowiak 697e8ae9b66SAlan Carew switch (pkt->unit) { 698e8ae9b66SAlan Carew case(CPU_POWER_SCALE_MIN): 699e8ae9b66SAlan Carew power_manager_scale_core_min(core_num); 700e8ae9b66SAlan Carew break; 701e8ae9b66SAlan Carew case(CPU_POWER_SCALE_MAX): 702e8ae9b66SAlan Carew power_manager_scale_core_max(core_num); 703e8ae9b66SAlan Carew break; 704e8ae9b66SAlan Carew case(CPU_POWER_SCALE_DOWN): 705e8ae9b66SAlan Carew power_manager_scale_core_down(core_num); 706e8ae9b66SAlan Carew break; 707e8ae9b66SAlan Carew case(CPU_POWER_SCALE_UP): 708e8ae9b66SAlan Carew power_manager_scale_core_up(core_num); 709e8ae9b66SAlan Carew break; 710567997b9SDavid Hunt case(CPU_POWER_ENABLE_TURBO): 711567997b9SDavid Hunt power_manager_enable_turbo_core(core_num); 712567997b9SDavid Hunt break; 713567997b9SDavid Hunt case(CPU_POWER_DISABLE_TURBO): 714567997b9SDavid Hunt power_manager_disable_turbo_core(core_num); 715567997b9SDavid Hunt break; 716e8ae9b66SAlan Carew default: 717e8ae9b66SAlan Carew break; 718e8ae9b66SAlan Carew } 719e8ae9b66SAlan Carew } 720f14791a8SRory Sexton 721f14791a8SRory Sexton if (pkt->command == PKT_POLICY) { 722ce4a2766SDavid Hunt RTE_LOG(INFO, CHANNEL_MONITOR, "Processing policy request %s\n", 723ce4a2766SDavid Hunt pkt->vm_name); 724f14791a8SRory Sexton update_policy(pkt); 725f14791a8SRory Sexton policy_is_set = 1; 726f14791a8SRory Sexton } 727f14791a8SRory Sexton 7283618326fSDavid Hunt if (pkt->command == PKT_POLICY_REMOVE) { 729d7b713d0SLukasz Krakowiak ret = remove_policy(pkt); 730d7b713d0SLukasz Krakowiak if (ret == 0) 7313618326fSDavid Hunt RTE_LOG(INFO, CHANNEL_MONITOR, 732d7b713d0SLukasz Krakowiak "Removed policy %s\n", pkt->vm_name); 733d7b713d0SLukasz Krakowiak else 734d7b713d0SLukasz Krakowiak RTE_LOG(INFO, CHANNEL_MONITOR, 735d7b713d0SLukasz Krakowiak "Policy %s does not exist\n", pkt->vm_name); 7363618326fSDavid Hunt } 7373618326fSDavid Hunt 7383618326fSDavid Hunt /* 7393618326fSDavid Hunt * Return is not checked as channel status may have been set to DISABLED 740e8ae9b66SAlan Carew * from management thread 741e8ae9b66SAlan Carew */ 742e8ae9b66SAlan Carew rte_atomic32_cmpset(&(chan_info->status), CHANNEL_MGR_CHANNEL_PROCESSING, 743e8ae9b66SAlan Carew CHANNEL_MGR_CHANNEL_CONNECTED); 744e8ae9b66SAlan Carew return 0; 745e8ae9b66SAlan Carew 746e8ae9b66SAlan Carew } 747e8ae9b66SAlan Carew 748e8ae9b66SAlan Carew int 749e8ae9b66SAlan Carew add_channel_to_monitor(struct channel_info **chan_info) 750e8ae9b66SAlan Carew { 751e8ae9b66SAlan Carew struct channel_info *info = *chan_info; 752e8ae9b66SAlan Carew struct epoll_event event; 753e8ae9b66SAlan Carew 754e8ae9b66SAlan Carew event.events = EPOLLIN; 755e8ae9b66SAlan Carew event.data.ptr = info; 756e8ae9b66SAlan Carew if (epoll_ctl(global_event_fd, EPOLL_CTL_ADD, info->fd, &event) < 0) { 757e8ae9b66SAlan Carew RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to add channel '%s' " 758e8ae9b66SAlan Carew "to epoll\n", info->channel_path); 759e8ae9b66SAlan Carew return -1; 760e8ae9b66SAlan Carew } 7613618326fSDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, "Added channel '%s' " 7623618326fSDavid Hunt "to monitor\n", info->channel_path); 763e8ae9b66SAlan Carew return 0; 764e8ae9b66SAlan Carew } 765e8ae9b66SAlan Carew 766e8ae9b66SAlan Carew int 767e8ae9b66SAlan Carew remove_channel_from_monitor(struct channel_info *chan_info) 768e8ae9b66SAlan Carew { 7693618326fSDavid Hunt if (epoll_ctl(global_event_fd, EPOLL_CTL_DEL, 7703618326fSDavid Hunt chan_info->fd, NULL) < 0) { 771e8ae9b66SAlan Carew RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to remove channel '%s' " 772e8ae9b66SAlan Carew "from epoll\n", chan_info->channel_path); 773e8ae9b66SAlan Carew return -1; 774e8ae9b66SAlan Carew } 775e8ae9b66SAlan Carew return 0; 776e8ae9b66SAlan Carew } 777e8ae9b66SAlan Carew 778e8ae9b66SAlan Carew int 779e8ae9b66SAlan Carew channel_monitor_init(void) 780e8ae9b66SAlan Carew { 781e8ae9b66SAlan Carew global_event_fd = epoll_create1(0); 782e8ae9b66SAlan Carew if (global_event_fd == 0) { 7833618326fSDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 7843618326fSDavid Hunt "Error creating epoll context with error %s\n", 7853618326fSDavid Hunt strerror(errno)); 786e8ae9b66SAlan Carew return -1; 787e8ae9b66SAlan Carew } 7883618326fSDavid Hunt global_events_list = rte_malloc("epoll_events", 7893618326fSDavid Hunt sizeof(*global_events_list) 790fdf20fa7SSergio Gonzalez Monroy * MAX_EVENTS, RTE_CACHE_LINE_SIZE); 791e8ae9b66SAlan Carew if (global_events_list == NULL) { 792e8ae9b66SAlan Carew RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to rte_malloc for " 793e8ae9b66SAlan Carew "epoll events\n"); 794e8ae9b66SAlan Carew return -1; 795e8ae9b66SAlan Carew } 796e8ae9b66SAlan Carew return 0; 797e8ae9b66SAlan Carew } 798e8ae9b66SAlan Carew 799a63504a9SDavid Hunt static void 800a63504a9SDavid Hunt read_binary_packet(struct channel_info *chan_info) 801a63504a9SDavid Hunt { 802a63504a9SDavid Hunt struct channel_packet pkt; 803a63504a9SDavid Hunt void *buffer = &pkt; 804a63504a9SDavid Hunt int buffer_len = sizeof(pkt); 805a63504a9SDavid Hunt int n_bytes, err = 0; 806a63504a9SDavid Hunt 807a63504a9SDavid Hunt while (buffer_len > 0) { 808a63504a9SDavid Hunt n_bytes = read(chan_info->fd, 809a63504a9SDavid Hunt buffer, buffer_len); 810a63504a9SDavid Hunt if (n_bytes == buffer_len) 811a63504a9SDavid Hunt break; 8121b897991SLukasz Krakowiak if (n_bytes < 0) { 813a63504a9SDavid Hunt err = errno; 814a63504a9SDavid Hunt RTE_LOG(DEBUG, CHANNEL_MONITOR, 815a63504a9SDavid Hunt "Received error on " 816a63504a9SDavid Hunt "channel '%s' read: %s\n", 817a63504a9SDavid Hunt chan_info->channel_path, 818a63504a9SDavid Hunt strerror(err)); 819a63504a9SDavid Hunt remove_channel(&chan_info); 820a63504a9SDavid Hunt break; 821a63504a9SDavid Hunt } 822a63504a9SDavid Hunt buffer = (char *)buffer + n_bytes; 823a63504a9SDavid Hunt buffer_len -= n_bytes; 824a63504a9SDavid Hunt } 825a63504a9SDavid Hunt if (!err) 826a63504a9SDavid Hunt process_request(&pkt, chan_info); 827a63504a9SDavid Hunt } 828a63504a9SDavid Hunt 829a63504a9SDavid Hunt #ifdef USE_JANSSON 830a63504a9SDavid Hunt static void 831a63504a9SDavid Hunt read_json_packet(struct channel_info *chan_info) 832a63504a9SDavid Hunt { 833a63504a9SDavid Hunt struct channel_packet pkt; 834a63504a9SDavid Hunt int n_bytes, ret; 835a63504a9SDavid Hunt json_t *root; 836a63504a9SDavid Hunt json_error_t error; 837*221e7026SMarcin Hajkowski const char *resource_name; 838*221e7026SMarcin Hajkowski 839a63504a9SDavid Hunt 840a63504a9SDavid Hunt /* read opening brace to closing brace */ 841a63504a9SDavid Hunt do { 842a63504a9SDavid Hunt int idx = 0; 843a63504a9SDavid Hunt int indent = 0; 844a63504a9SDavid Hunt do { 845a63504a9SDavid Hunt n_bytes = read(chan_info->fd, &json_data[idx], 1); 846a63504a9SDavid Hunt if (n_bytes == 0) 847a63504a9SDavid Hunt break; 848a63504a9SDavid Hunt if (json_data[idx] == '{') 849a63504a9SDavid Hunt indent++; 850a63504a9SDavid Hunt if (json_data[idx] == '}') 851a63504a9SDavid Hunt indent--; 852a63504a9SDavid Hunt if ((indent > 0) || (idx > 0)) 853a63504a9SDavid Hunt idx++; 8544c2caea0SReshma Pattan if (indent <= 0) 855a63504a9SDavid Hunt json_data[idx] = 0; 856a63504a9SDavid Hunt if (idx >= MAX_JSON_STRING_LEN-1) 857a63504a9SDavid Hunt break; 858a63504a9SDavid Hunt } while (indent > 0); 859a63504a9SDavid Hunt 8608f8f876bSDavid Hunt json_data[idx] = '\0'; 861a63504a9SDavid Hunt 862a63504a9SDavid Hunt if (strlen(json_data) == 0) 863a63504a9SDavid Hunt continue; 864a63504a9SDavid Hunt 865a63504a9SDavid Hunt printf("got [%s]\n", json_data); 866a63504a9SDavid Hunt 867a63504a9SDavid Hunt root = json_loads(json_data, 0, &error); 868a63504a9SDavid Hunt 869a63504a9SDavid Hunt if (root) { 870*221e7026SMarcin Hajkowski resource_name = get_resource_name_from_chn_path( 871*221e7026SMarcin Hajkowski chan_info->channel_path); 872a63504a9SDavid Hunt /* 873a63504a9SDavid Hunt * Because our data is now in the json 874a63504a9SDavid Hunt * object, we can overwrite the pkt 875a63504a9SDavid Hunt * with a channel_packet struct, using 876a63504a9SDavid Hunt * parse_json_to_pkt() 877a63504a9SDavid Hunt */ 878*221e7026SMarcin Hajkowski ret = parse_json_to_pkt(root, &pkt, resource_name); 879a63504a9SDavid Hunt json_decref(root); 880a63504a9SDavid Hunt if (ret) { 881a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 882a63504a9SDavid Hunt "Error validating JSON profile data\n"); 883a63504a9SDavid Hunt break; 884a63504a9SDavid Hunt } 885a63504a9SDavid Hunt process_request(&pkt, chan_info); 886a63504a9SDavid Hunt } else { 887a63504a9SDavid Hunt RTE_LOG(ERR, CHANNEL_MONITOR, 888a63504a9SDavid Hunt "JSON error on line %d: %s\n", 889a63504a9SDavid Hunt error.line, error.text); 890a63504a9SDavid Hunt } 891a63504a9SDavid Hunt } while (n_bytes > 0); 892a63504a9SDavid Hunt } 893a63504a9SDavid Hunt #endif 894a63504a9SDavid Hunt 895e8ae9b66SAlan Carew void 896e8ae9b66SAlan Carew run_channel_monitor(void) 897e8ae9b66SAlan Carew { 898e8ae9b66SAlan Carew while (run_loop) { 899e8ae9b66SAlan Carew int n_events, i; 900e8ae9b66SAlan Carew 901e8ae9b66SAlan Carew n_events = epoll_wait(global_event_fd, global_events_list, 902e8ae9b66SAlan Carew MAX_EVENTS, 1); 903e8ae9b66SAlan Carew if (!run_loop) 904e8ae9b66SAlan Carew break; 905e8ae9b66SAlan Carew for (i = 0; i < n_events; i++) { 906e8ae9b66SAlan Carew struct channel_info *chan_info = (struct channel_info *) 907e8ae9b66SAlan Carew global_events_list[i].data.ptr; 908e8ae9b66SAlan Carew if ((global_events_list[i].events & EPOLLERR) || 909e8ae9b66SAlan Carew (global_events_list[i].events & EPOLLHUP)) { 910ce4a2766SDavid Hunt RTE_LOG(INFO, CHANNEL_MONITOR, 911ce4a2766SDavid Hunt "Remote closed connection for " 912f14791a8SRory Sexton "channel '%s'\n", 913f14791a8SRory Sexton chan_info->channel_path); 914e8ae9b66SAlan Carew remove_channel(&chan_info); 915e8ae9b66SAlan Carew continue; 916e8ae9b66SAlan Carew } 917e8ae9b66SAlan Carew if (global_events_list[i].events & EPOLLIN) { 918e8ae9b66SAlan Carew 919a63504a9SDavid Hunt switch (chan_info->type) { 920a63504a9SDavid Hunt case CHANNEL_TYPE_BINARY: 921a63504a9SDavid Hunt read_binary_packet(chan_info); 922e8ae9b66SAlan Carew break; 923a63504a9SDavid Hunt #ifdef USE_JANSSON 924a63504a9SDavid Hunt case CHANNEL_TYPE_JSON: 925a63504a9SDavid Hunt read_json_packet(chan_info); 926a63504a9SDavid Hunt break; 927a63504a9SDavid Hunt #endif 928a63504a9SDavid Hunt default: 929e8ae9b66SAlan Carew break; 930e8ae9b66SAlan Carew } 931e8ae9b66SAlan Carew } 932e8ae9b66SAlan Carew } 933e4f66da3SDavid Hunt rte_delay_us(time_period_ms*1000); 934f14791a8SRory Sexton if (policy_is_set) { 935*221e7026SMarcin Hajkowski unsigned int j; 9367abd801fSDavid Hunt 937*221e7026SMarcin Hajkowski for (j = 0; j < RTE_DIM(policies); j++) { 938f14791a8SRory Sexton if (policies[j].enabled == 1) 939f14791a8SRory Sexton apply_policy(&policies[j]); 940f14791a8SRory Sexton } 941f14791a8SRory Sexton } 942e8ae9b66SAlan Carew } 943e8ae9b66SAlan Carew } 944