1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include <unistd.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <stdint.h> 9 #include <signal.h> 10 #include <errno.h> 11 #include <string.h> 12 #include <fcntl.h> 13 #include <sys/types.h> 14 #include <sys/epoll.h> 15 #include <sys/queue.h> 16 #include <sys/time.h> 17 #include <sys/socket.h> 18 #include <sys/select.h> 19 #ifdef USE_JANSSON 20 #include <jansson.h> 21 #else 22 #pragma message "Jansson dev libs unavailable, not including JSON parsing" 23 #endif 24 #include <rte_string_fns.h> 25 #include <rte_log.h> 26 #include <rte_memory.h> 27 #include <rte_malloc.h> 28 #include <rte_atomic.h> 29 #include <rte_cycles.h> 30 #include <rte_ethdev.h> 31 #ifdef RTE_NET_I40E 32 #include <rte_pmd_i40e.h> 33 #endif 34 #include <rte_power.h> 35 36 #include <libvirt/libvirt.h> 37 #include "channel_monitor.h" 38 #include "channel_manager.h" 39 #include "power_manager.h" 40 #include "oob_monitor.h" 41 42 #define RTE_LOGTYPE_CHANNEL_MONITOR RTE_LOGTYPE_USER1 43 44 #define MAX_EVENTS 256 45 46 uint64_t vsi_pkt_count_prev[384]; 47 uint64_t rdtsc_prev[384]; 48 #define MAX_JSON_STRING_LEN 1024 49 char json_data[MAX_JSON_STRING_LEN]; 50 51 double time_period_ms = 1; 52 static volatile unsigned run_loop = 1; 53 static int global_event_fd; 54 static unsigned int policy_is_set; 55 static struct epoll_event *global_events_list; 56 static struct policy policies[RTE_MAX_LCORE]; 57 58 #ifdef USE_JANSSON 59 60 union PFID { 61 struct rte_ether_addr addr; 62 uint64_t pfid; 63 }; 64 65 static int 66 str_to_ether_addr(const char *a, struct rte_ether_addr *ether_addr) 67 { 68 int i; 69 char *end; 70 unsigned long o[RTE_ETHER_ADDR_LEN]; 71 72 i = 0; 73 do { 74 errno = 0; 75 o[i] = strtoul(a, &end, 16); 76 if (errno != 0 || end == a || (end[0] != ':' && end[0] != 0)) 77 return -1; 78 a = end + 1; 79 } while (++i != RTE_DIM(o) / sizeof(o[0]) && end[0] != 0); 80 81 /* Junk at the end of line */ 82 if (end[0] != 0) 83 return -1; 84 85 /* Support the format XX:XX:XX:XX:XX:XX */ 86 if (i == RTE_ETHER_ADDR_LEN) { 87 while (i-- != 0) { 88 if (o[i] > UINT8_MAX) 89 return -1; 90 ether_addr->addr_bytes[i] = (uint8_t)o[i]; 91 } 92 /* Support the format XXXX:XXXX:XXXX */ 93 } else if (i == RTE_ETHER_ADDR_LEN / 2) { 94 while (i-- != 0) { 95 if (o[i] > UINT16_MAX) 96 return -1; 97 ether_addr->addr_bytes[i * 2] = 98 (uint8_t)(o[i] >> 8); 99 ether_addr->addr_bytes[i * 2 + 1] = 100 (uint8_t)(o[i] & 0xff); 101 } 102 /* unknown format */ 103 } else 104 return -1; 105 106 return 0; 107 } 108 109 static int 110 set_policy_mac(struct rte_power_channel_packet *pkt, int idx, char *mac) 111 { 112 union PFID pfid; 113 int ret; 114 115 /* Use port MAC address as the vfid */ 116 ret = str_to_ether_addr(mac, &pfid.addr); 117 118 if (ret != 0) { 119 RTE_LOG(ERR, CHANNEL_MONITOR, 120 "Invalid mac address received in JSON\n"); 121 pkt->vfid[idx] = 0; 122 return -1; 123 } 124 125 printf("Received MAC Address: %02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 ":" 126 "%02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 "\n", 127 RTE_ETHER_ADDR_BYTES(&pfid.addr)); 128 129 pkt->vfid[idx] = pfid.pfid; 130 return 0; 131 } 132 133 static char* 134 get_resource_name_from_chn_path(const char *channel_path) 135 { 136 char *substr = NULL; 137 138 substr = strstr(channel_path, CHANNEL_MGR_FIFO_PATTERN_NAME); 139 140 return substr; 141 } 142 143 static int 144 get_resource_id_from_vmname(const char *vm_name) 145 { 146 int result = -1; 147 int off = 0; 148 149 if (vm_name == NULL) 150 return -1; 151 152 while (vm_name[off] != '\0') { 153 if (isdigit(vm_name[off])) 154 break; 155 off++; 156 } 157 result = atoi(&vm_name[off]); 158 if ((result == 0) && (vm_name[off] != '0')) 159 return -1; 160 161 return result; 162 } 163 164 static int 165 parse_json_to_pkt(json_t *element, struct rte_power_channel_packet *pkt, 166 const char *vm_name) 167 { 168 const char *key; 169 json_t *value; 170 int ret; 171 int resource_id; 172 173 memset(pkt, 0, sizeof(*pkt)); 174 175 pkt->nb_mac_to_monitor = 0; 176 pkt->t_boost_status.tbEnabled = false; 177 pkt->workload = RTE_POWER_WL_LOW; 178 pkt->policy_to_use = RTE_POWER_POLICY_TIME; 179 pkt->command = RTE_POWER_PKT_POLICY; 180 pkt->core_type = RTE_POWER_CORE_TYPE_PHYSICAL; 181 182 if (vm_name == NULL) { 183 RTE_LOG(ERR, CHANNEL_MONITOR, 184 "vm_name is NULL, request rejected !\n"); 185 return -1; 186 } 187 188 json_object_foreach(element, key, value) { 189 if (!strcmp(key, "policy")) { 190 /* Recurse in to get the contents of profile */ 191 ret = parse_json_to_pkt(value, pkt, vm_name); 192 if (ret) 193 return ret; 194 } else if (!strcmp(key, "instruction")) { 195 /* Recurse in to get the contents of instruction */ 196 ret = parse_json_to_pkt(value, pkt, vm_name); 197 if (ret) 198 return ret; 199 } else if (!strcmp(key, "command")) { 200 char command[32]; 201 strlcpy(command, json_string_value(value), 32); 202 if (!strcmp(command, "power")) { 203 pkt->command = RTE_POWER_CPU_POWER; 204 } else if (!strcmp(command, "create")) { 205 pkt->command = RTE_POWER_PKT_POLICY; 206 } else if (!strcmp(command, "destroy")) { 207 pkt->command = RTE_POWER_PKT_POLICY_REMOVE; 208 } else { 209 RTE_LOG(ERR, CHANNEL_MONITOR, 210 "Invalid command received in JSON\n"); 211 return -1; 212 } 213 } else if (!strcmp(key, "policy_type")) { 214 char command[32]; 215 strlcpy(command, json_string_value(value), 32); 216 if (!strcmp(command, "TIME")) { 217 pkt->policy_to_use = 218 RTE_POWER_POLICY_TIME; 219 } else if (!strcmp(command, "TRAFFIC")) { 220 pkt->policy_to_use = 221 RTE_POWER_POLICY_TRAFFIC; 222 } else if (!strcmp(command, "WORKLOAD")) { 223 pkt->policy_to_use = 224 RTE_POWER_POLICY_WORKLOAD; 225 } else if (!strcmp(command, "BRANCH_RATIO")) { 226 pkt->policy_to_use = 227 RTE_POWER_POLICY_BRANCH_RATIO; 228 } else { 229 RTE_LOG(ERR, CHANNEL_MONITOR, 230 "Wrong policy_type received in JSON\n"); 231 return -1; 232 } 233 } else if (!strcmp(key, "workload")) { 234 char command[32]; 235 strlcpy(command, json_string_value(value), 32); 236 if (!strcmp(command, "HIGH")) { 237 pkt->workload = RTE_POWER_WL_HIGH; 238 } else if (!strcmp(command, "MEDIUM")) { 239 pkt->workload = RTE_POWER_WL_MEDIUM; 240 } else if (!strcmp(command, "LOW")) { 241 pkt->workload = RTE_POWER_WL_LOW; 242 } else { 243 RTE_LOG(ERR, CHANNEL_MONITOR, 244 "Wrong workload received in JSON\n"); 245 return -1; 246 } 247 } else if (!strcmp(key, "busy_hours")) { 248 unsigned int i; 249 size_t size = json_array_size(value); 250 251 for (i = 0; i < size; i++) { 252 int hour = (int)json_integer_value( 253 json_array_get(value, i)); 254 pkt->timer_policy.busy_hours[i] = hour; 255 } 256 } else if (!strcmp(key, "quiet_hours")) { 257 unsigned int i; 258 size_t size = json_array_size(value); 259 260 for (i = 0; i < size; i++) { 261 int hour = (int)json_integer_value( 262 json_array_get(value, i)); 263 pkt->timer_policy.quiet_hours[i] = hour; 264 } 265 } else if (!strcmp(key, "mac_list")) { 266 unsigned int i; 267 size_t size = json_array_size(value); 268 269 for (i = 0; i < size; i++) { 270 char mac[32]; 271 strlcpy(mac, 272 json_string_value(json_array_get(value, i)), 273 32); 274 set_policy_mac(pkt, i, mac); 275 } 276 pkt->nb_mac_to_monitor = size; 277 } else if (!strcmp(key, "avg_packet_thresh")) { 278 pkt->traffic_policy.avg_max_packet_thresh = 279 (uint32_t)json_integer_value(value); 280 } else if (!strcmp(key, "max_packet_thresh")) { 281 pkt->traffic_policy.max_max_packet_thresh = 282 (uint32_t)json_integer_value(value); 283 } else if (!strcmp(key, "unit")) { 284 char unit[32]; 285 strlcpy(unit, json_string_value(value), 32); 286 if (!strcmp(unit, "SCALE_UP")) { 287 pkt->unit = RTE_POWER_SCALE_UP; 288 } else if (!strcmp(unit, "SCALE_DOWN")) { 289 pkt->unit = RTE_POWER_SCALE_DOWN; 290 } else if (!strcmp(unit, "SCALE_MAX")) { 291 pkt->unit = RTE_POWER_SCALE_MAX; 292 } else if (!strcmp(unit, "SCALE_MIN")) { 293 pkt->unit = RTE_POWER_SCALE_MIN; 294 } else if (!strcmp(unit, "ENABLE_TURBO")) { 295 pkt->unit = RTE_POWER_ENABLE_TURBO; 296 } else if (!strcmp(unit, "DISABLE_TURBO")) { 297 pkt->unit = RTE_POWER_DISABLE_TURBO; 298 } else { 299 RTE_LOG(ERR, CHANNEL_MONITOR, 300 "Invalid command received in JSON\n"); 301 return -1; 302 } 303 } else { 304 RTE_LOG(ERR, CHANNEL_MONITOR, 305 "Unknown key received in JSON string: %s\n", 306 key); 307 } 308 309 resource_id = get_resource_id_from_vmname(vm_name); 310 if (resource_id < 0) { 311 RTE_LOG(ERR, CHANNEL_MONITOR, 312 "Could not get resource_id from vm_name:%s\n", 313 vm_name); 314 return -1; 315 } 316 strlcpy(pkt->vm_name, vm_name, RTE_POWER_VM_MAX_NAME_SZ); 317 pkt->resource_id = resource_id; 318 } 319 return 0; 320 } 321 #endif 322 323 void channel_monitor_exit(void) 324 { 325 run_loop = 0; 326 rte_free(global_events_list); 327 } 328 329 static void 330 core_share(int pNo, int z, int x, int t) 331 { 332 if (policies[pNo].core_share[z].pcpu == lvm_info[x].pcpus[t]) { 333 if (strcmp(policies[pNo].pkt.vm_name, 334 lvm_info[x].vm_name) != 0) { 335 policies[pNo].core_share[z].status = 1; 336 power_manager_scale_core_max( 337 policies[pNo].core_share[z].pcpu); 338 } 339 } 340 } 341 342 static void 343 core_share_status(int pNo) 344 { 345 346 int noVms = 0, noVcpus = 0, z, x, t; 347 348 get_all_vm(&noVms, &noVcpus); 349 350 /* Reset Core Share Status. */ 351 for (z = 0; z < noVcpus; z++) 352 policies[pNo].core_share[z].status = 0; 353 354 /* Foreach vcpu in a policy. */ 355 for (z = 0; z < policies[pNo].pkt.num_vcpu; z++) { 356 /* Foreach VM on the platform. */ 357 for (x = 0; x < noVms; x++) { 358 /* Foreach vcpu of VMs on platform. */ 359 for (t = 0; t < lvm_info[x].num_cpus; t++) 360 core_share(pNo, z, x, t); 361 } 362 } 363 } 364 365 366 static int 367 pcpu_monitor(struct policy *pol, struct core_info *ci, int pcpu, int count) 368 { 369 int ret = 0; 370 371 if (pol->pkt.policy_to_use == RTE_POWER_POLICY_BRANCH_RATIO) { 372 ci->cd[pcpu].oob_enabled = 1; 373 ret = add_core_to_monitor(pcpu); 374 if (ret == 0) 375 RTE_LOG(INFO, CHANNEL_MONITOR, 376 "Monitoring pcpu %d OOB for %s\n", 377 pcpu, pol->pkt.vm_name); 378 else 379 RTE_LOG(ERR, CHANNEL_MONITOR, 380 "Error monitoring pcpu %d OOB for %s\n", 381 pcpu, pol->pkt.vm_name); 382 383 } else { 384 pol->core_share[count].pcpu = pcpu; 385 RTE_LOG(INFO, CHANNEL_MONITOR, 386 "Monitoring pcpu %d for %s\n", 387 pcpu, pol->pkt.vm_name); 388 } 389 return ret; 390 } 391 392 static void 393 get_pcpu_to_control(struct policy *pol) 394 { 395 396 /* Convert vcpu to pcpu. */ 397 struct vm_info info; 398 int pcpu, count; 399 struct core_info *ci; 400 401 ci = get_core_info(); 402 403 RTE_LOG(DEBUG, CHANNEL_MONITOR, 404 "Looking for pcpu for %s\n", pol->pkt.vm_name); 405 406 /* 407 * So now that we're handling virtual and physical cores, we need to 408 * differenciate between them when adding them to the branch monitor. 409 * Virtual cores need to be converted to physical cores. 410 */ 411 if (pol->pkt.core_type == RTE_POWER_CORE_TYPE_VIRTUAL) { 412 /* 413 * If the cores in the policy are virtual, we need to map them 414 * to physical core. We look up the vm info and use that for 415 * the mapping. 416 */ 417 get_info_vm(pol->pkt.vm_name, &info); 418 for (count = 0; count < pol->pkt.num_vcpu; count++) { 419 pcpu = info.pcpu_map[pol->pkt.vcpu_to_control[count]]; 420 pcpu_monitor(pol, ci, pcpu, count); 421 } 422 } else { 423 /* 424 * If the cores in the policy are physical, we just use 425 * those core id's directly. 426 */ 427 for (count = 0; count < pol->pkt.num_vcpu; count++) { 428 pcpu = pol->pkt.vcpu_to_control[count]; 429 pcpu_monitor(pol, ci, pcpu, count); 430 } 431 } 432 } 433 434 static int 435 get_pfid(struct policy *pol) 436 { 437 438 int i, x, ret = 0; 439 440 for (i = 0; i < pol->pkt.nb_mac_to_monitor; i++) { 441 442 RTE_ETH_FOREACH_DEV(x) { 443 #ifdef RTE_NET_I40E 444 ret = rte_pmd_i40e_query_vfid_by_mac(x, 445 (struct rte_ether_addr *)&(pol->pkt.vfid[i])); 446 #else 447 ret = -ENOTSUP; 448 #endif 449 if (ret != -EINVAL) { 450 pol->port[i] = x; 451 break; 452 } 453 } 454 if (ret == -EINVAL || ret == -ENOTSUP || ret == ENODEV) { 455 RTE_LOG(INFO, CHANNEL_MONITOR, 456 "Error with Policy. MAC not found on " 457 "attached ports "); 458 pol->enabled = 0; 459 return ret; 460 } 461 pol->pfid[i] = ret; 462 } 463 return 1; 464 } 465 466 static int 467 update_policy(struct rte_power_channel_packet *pkt) 468 { 469 470 unsigned int updated = 0; 471 unsigned int i; 472 473 474 RTE_LOG(INFO, CHANNEL_MONITOR, 475 "Applying policy for %s\n", pkt->vm_name); 476 477 for (i = 0; i < RTE_DIM(policies); i++) { 478 if (strcmp(policies[i].pkt.vm_name, pkt->vm_name) == 0) { 479 /* Copy the contents of *pkt into the policy.pkt */ 480 policies[i].pkt = *pkt; 481 get_pcpu_to_control(&policies[i]); 482 /* Check Eth dev only for Traffic policy */ 483 if (policies[i].pkt.policy_to_use == 484 RTE_POWER_POLICY_TRAFFIC) { 485 if (get_pfid(&policies[i]) < 0) { 486 updated = 1; 487 break; 488 } 489 } 490 core_share_status(i); 491 policies[i].enabled = 1; 492 updated = 1; 493 } 494 } 495 if (!updated) { 496 for (i = 0; i < RTE_DIM(policies); i++) { 497 if (policies[i].enabled == 0) { 498 policies[i].pkt = *pkt; 499 get_pcpu_to_control(&policies[i]); 500 /* Check Eth dev only for Traffic policy */ 501 if (policies[i].pkt.policy_to_use == 502 RTE_POWER_POLICY_TRAFFIC) { 503 if (get_pfid(&policies[i]) < 0) { 504 updated = 1; 505 break; 506 } 507 } 508 core_share_status(i); 509 policies[i].enabled = 1; 510 break; 511 } 512 } 513 } 514 return 0; 515 } 516 517 static int 518 remove_policy(struct rte_power_channel_packet *pkt __rte_unused) 519 { 520 unsigned int i; 521 522 /* 523 * Disabling the policy is simply a case of setting 524 * enabled to 0 525 */ 526 for (i = 0; i < RTE_DIM(policies); i++) { 527 if (strcmp(policies[i].pkt.vm_name, pkt->vm_name) == 0) { 528 policies[i].enabled = 0; 529 return 0; 530 } 531 } 532 return -1; 533 } 534 535 static uint64_t 536 get_pkt_diff(struct policy *pol) 537 { 538 539 uint64_t vsi_pkt_count, 540 vsi_pkt_total = 0, 541 vsi_pkt_count_prev_total = 0; 542 double rdtsc_curr, rdtsc_diff, diff; 543 int x; 544 #ifdef RTE_NET_I40E 545 struct rte_eth_stats vf_stats; 546 #endif 547 548 for (x = 0; x < pol->pkt.nb_mac_to_monitor; x++) { 549 550 #ifdef RTE_NET_I40E 551 /*Read vsi stats*/ 552 if (rte_pmd_i40e_get_vf_stats(x, pol->pfid[x], &vf_stats) == 0) 553 vsi_pkt_count = vf_stats.ipackets; 554 else 555 vsi_pkt_count = -1; 556 #else 557 vsi_pkt_count = -1; 558 #endif 559 560 vsi_pkt_total += vsi_pkt_count; 561 562 vsi_pkt_count_prev_total += vsi_pkt_count_prev[pol->pfid[x]]; 563 vsi_pkt_count_prev[pol->pfid[x]] = vsi_pkt_count; 564 } 565 566 rdtsc_curr = rte_rdtsc_precise(); 567 rdtsc_diff = rdtsc_curr - rdtsc_prev[pol->pfid[x-1]]; 568 rdtsc_prev[pol->pfid[x-1]] = rdtsc_curr; 569 570 diff = (vsi_pkt_total - vsi_pkt_count_prev_total) * 571 ((double)rte_get_tsc_hz() / rdtsc_diff); 572 573 return diff; 574 } 575 576 static void 577 apply_traffic_profile(struct policy *pol) 578 { 579 580 int count; 581 uint64_t diff = 0; 582 583 diff = get_pkt_diff(pol); 584 585 if (diff >= (pol->pkt.traffic_policy.max_max_packet_thresh)) { 586 for (count = 0; count < pol->pkt.num_vcpu; count++) { 587 if (pol->core_share[count].status != 1) 588 power_manager_scale_core_max( 589 pol->core_share[count].pcpu); 590 } 591 } else if (diff >= (pol->pkt.traffic_policy.avg_max_packet_thresh)) { 592 for (count = 0; count < pol->pkt.num_vcpu; count++) { 593 if (pol->core_share[count].status != 1) 594 power_manager_scale_core_med( 595 pol->core_share[count].pcpu); 596 } 597 } else if (diff < (pol->pkt.traffic_policy.avg_max_packet_thresh)) { 598 for (count = 0; count < pol->pkt.num_vcpu; count++) { 599 if (pol->core_share[count].status != 1) 600 power_manager_scale_core_min( 601 pol->core_share[count].pcpu); 602 } 603 } 604 } 605 606 static void 607 apply_time_profile(struct policy *pol) 608 { 609 610 int count, x; 611 struct timeval tv; 612 struct tm *ptm; 613 char time_string[40]; 614 615 /* Obtain the time of day, and convert it to a tm struct. */ 616 gettimeofday(&tv, NULL); 617 ptm = localtime(&tv.tv_sec); 618 /* Format the date and time, down to a single second. */ 619 strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", ptm); 620 621 for (x = 0; x < RTE_POWER_HOURS_PER_DAY; x++) { 622 623 if (ptm->tm_hour == pol->pkt.timer_policy.busy_hours[x]) { 624 for (count = 0; count < pol->pkt.num_vcpu; count++) { 625 if (pol->core_share[count].status != 1) { 626 power_manager_scale_core_max( 627 pol->core_share[count].pcpu); 628 } 629 } 630 break; 631 } else if (ptm->tm_hour == 632 pol->pkt.timer_policy.quiet_hours[x]) { 633 for (count = 0; count < pol->pkt.num_vcpu; count++) { 634 if (pol->core_share[count].status != 1) { 635 power_manager_scale_core_min( 636 pol->core_share[count].pcpu); 637 } 638 } 639 break; 640 } else if (ptm->tm_hour == 641 pol->pkt.timer_policy.hours_to_use_traffic_profile[x]) { 642 apply_traffic_profile(pol); 643 break; 644 } 645 } 646 } 647 648 static void 649 apply_workload_profile(struct policy *pol) 650 { 651 652 int count; 653 654 if (pol->pkt.workload == RTE_POWER_WL_HIGH) { 655 for (count = 0; count < pol->pkt.num_vcpu; count++) { 656 if (pol->core_share[count].status != 1) 657 power_manager_scale_core_max( 658 pol->core_share[count].pcpu); 659 } 660 } else if (pol->pkt.workload == RTE_POWER_WL_MEDIUM) { 661 for (count = 0; count < pol->pkt.num_vcpu; count++) { 662 if (pol->core_share[count].status != 1) 663 power_manager_scale_core_med( 664 pol->core_share[count].pcpu); 665 } 666 } else if (pol->pkt.workload == RTE_POWER_WL_LOW) { 667 for (count = 0; count < pol->pkt.num_vcpu; count++) { 668 if (pol->core_share[count].status != 1) 669 power_manager_scale_core_min( 670 pol->core_share[count].pcpu); 671 } 672 } 673 } 674 675 static void 676 apply_policy(struct policy *pol) 677 { 678 679 struct rte_power_channel_packet *pkt = &pol->pkt; 680 681 /*Check policy to use*/ 682 if (pkt->policy_to_use == RTE_POWER_POLICY_TRAFFIC) 683 apply_traffic_profile(pol); 684 else if (pkt->policy_to_use == RTE_POWER_POLICY_TIME) 685 apply_time_profile(pol); 686 else if (pkt->policy_to_use == RTE_POWER_POLICY_WORKLOAD) 687 apply_workload_profile(pol); 688 } 689 690 static int 691 write_binary_packet(void *buffer, 692 size_t buffer_len, 693 struct channel_info *chan_info) 694 { 695 int ret; 696 697 if (buffer_len == 0 || buffer == NULL) 698 return -1; 699 700 if (chan_info->fd < 0) { 701 RTE_LOG(ERR, CHANNEL_MONITOR, "Channel is not connected\n"); 702 return -1; 703 } 704 705 while (buffer_len > 0) { 706 ret = write(chan_info->fd, buffer, buffer_len); 707 if (ret == -1) { 708 if (errno == EINTR) 709 continue; 710 RTE_LOG(ERR, CHANNEL_MONITOR, "Write function failed due to %s.\n", 711 strerror(errno)); 712 return -1; 713 } 714 buffer = (char *)buffer + ret; 715 buffer_len -= ret; 716 } 717 return 0; 718 } 719 720 static int 721 send_freq(struct rte_power_channel_packet *pkt, 722 struct channel_info *chan_info, 723 bool freq_list) 724 { 725 unsigned int vcore_id = pkt->resource_id; 726 struct rte_power_channel_packet_freq_list channel_pkt_freq_list; 727 struct vm_info info; 728 729 if (get_info_vm(pkt->vm_name, &info) != 0) 730 return -1; 731 732 if (!freq_list && vcore_id >= RTE_POWER_MAX_VCPU_PER_VM) 733 return -1; 734 735 if (!info.allow_query) 736 return -1; 737 738 channel_pkt_freq_list.command = RTE_POWER_FREQ_LIST; 739 channel_pkt_freq_list.num_vcpu = info.num_vcpus; 740 741 if (freq_list) { 742 unsigned int i; 743 for (i = 0; i < info.num_vcpus; i++) 744 channel_pkt_freq_list.freq_list[i] = 745 power_manager_get_current_frequency(info.pcpu_map[i]); 746 } else { 747 channel_pkt_freq_list.freq_list[vcore_id] = 748 power_manager_get_current_frequency(info.pcpu_map[vcore_id]); 749 } 750 751 return write_binary_packet(&channel_pkt_freq_list, 752 sizeof(channel_pkt_freq_list), 753 chan_info); 754 } 755 756 static int 757 send_capabilities(struct rte_power_channel_packet *pkt, 758 struct channel_info *chan_info, 759 bool list_requested) 760 { 761 unsigned int vcore_id = pkt->resource_id; 762 struct rte_power_channel_packet_caps_list channel_pkt_caps_list; 763 struct vm_info info; 764 struct rte_power_core_capabilities caps; 765 int ret; 766 767 if (get_info_vm(pkt->vm_name, &info) != 0) 768 return -1; 769 770 if (!list_requested && vcore_id >= RTE_POWER_MAX_VCPU_PER_VM) 771 return -1; 772 773 if (!info.allow_query) 774 return -1; 775 776 channel_pkt_caps_list.command = RTE_POWER_CAPS_LIST; 777 channel_pkt_caps_list.num_vcpu = info.num_vcpus; 778 779 if (list_requested) { 780 unsigned int i; 781 for (i = 0; i < info.num_vcpus; i++) { 782 ret = rte_power_get_capabilities(info.pcpu_map[i], 783 &caps); 784 if (ret == 0) { 785 channel_pkt_caps_list.turbo[i] = 786 caps.turbo; 787 channel_pkt_caps_list.priority[i] = 788 caps.priority; 789 } else 790 return -1; 791 792 } 793 } else { 794 ret = rte_power_get_capabilities(info.pcpu_map[vcore_id], 795 &caps); 796 if (ret == 0) { 797 channel_pkt_caps_list.turbo[vcore_id] = 798 caps.turbo; 799 channel_pkt_caps_list.priority[vcore_id] = 800 caps.priority; 801 } else 802 return -1; 803 } 804 805 return write_binary_packet(&channel_pkt_caps_list, 806 sizeof(channel_pkt_caps_list), 807 chan_info); 808 } 809 810 static int 811 send_ack_for_received_cmd(struct rte_power_channel_packet *pkt, 812 struct channel_info *chan_info, 813 uint32_t command) 814 { 815 pkt->command = command; 816 return write_binary_packet(pkt, 817 sizeof(*pkt), 818 chan_info); 819 } 820 821 static int 822 process_request(struct rte_power_channel_packet *pkt, 823 struct channel_info *chan_info) 824 { 825 int ret; 826 827 if (chan_info == NULL) 828 return -1; 829 830 if (rte_atomic32_cmpset(&(chan_info->status), CHANNEL_MGR_CHANNEL_CONNECTED, 831 CHANNEL_MGR_CHANNEL_PROCESSING) == 0) 832 return -1; 833 834 if (pkt->command == RTE_POWER_CPU_POWER) { 835 unsigned int core_num; 836 837 if (pkt->core_type == RTE_POWER_CORE_TYPE_VIRTUAL) 838 core_num = get_pcpu(chan_info, pkt->resource_id); 839 else 840 core_num = pkt->resource_id; 841 842 RTE_LOG(DEBUG, CHANNEL_MONITOR, "Processing requested cmd for cpu:%d\n", 843 core_num); 844 845 int scale_res; 846 bool valid_unit = true; 847 848 switch (pkt->unit) { 849 case(RTE_POWER_SCALE_MIN): 850 scale_res = power_manager_scale_core_min(core_num); 851 break; 852 case(RTE_POWER_SCALE_MAX): 853 scale_res = power_manager_scale_core_max(core_num); 854 break; 855 case(RTE_POWER_SCALE_DOWN): 856 scale_res = power_manager_scale_core_down(core_num); 857 break; 858 case(RTE_POWER_SCALE_UP): 859 scale_res = power_manager_scale_core_up(core_num); 860 break; 861 case(RTE_POWER_ENABLE_TURBO): 862 scale_res = power_manager_enable_turbo_core(core_num); 863 break; 864 case(RTE_POWER_DISABLE_TURBO): 865 scale_res = power_manager_disable_turbo_core(core_num); 866 break; 867 default: 868 valid_unit = false; 869 break; 870 } 871 872 if (valid_unit) { 873 ret = send_ack_for_received_cmd(pkt, 874 chan_info, 875 scale_res >= 0 ? 876 RTE_POWER_CMD_ACK : 877 RTE_POWER_CMD_NACK); 878 if (ret < 0) 879 RTE_LOG(ERR, CHANNEL_MONITOR, "Error during sending ack command.\n"); 880 } else 881 RTE_LOG(ERR, CHANNEL_MONITOR, "Unexpected unit type.\n"); 882 883 } 884 885 if (pkt->command == RTE_POWER_PKT_POLICY) { 886 RTE_LOG(INFO, CHANNEL_MONITOR, "Processing policy request %s\n", 887 pkt->vm_name); 888 int ret = send_ack_for_received_cmd(pkt, 889 chan_info, 890 RTE_POWER_CMD_ACK); 891 if (ret < 0) 892 RTE_LOG(ERR, CHANNEL_MONITOR, "Error during sending ack command.\n"); 893 update_policy(pkt); 894 policy_is_set = 1; 895 } 896 897 if (pkt->command == RTE_POWER_PKT_POLICY_REMOVE) { 898 ret = remove_policy(pkt); 899 if (ret == 0) 900 RTE_LOG(INFO, CHANNEL_MONITOR, 901 "Removed policy %s\n", pkt->vm_name); 902 else 903 RTE_LOG(INFO, CHANNEL_MONITOR, 904 "Policy %s does not exist\n", pkt->vm_name); 905 } 906 907 if (pkt->command == RTE_POWER_QUERY_FREQ_LIST || 908 pkt->command == RTE_POWER_QUERY_FREQ) { 909 910 RTE_LOG(INFO, CHANNEL_MONITOR, 911 "Frequency for %s requested.\n", pkt->vm_name); 912 int ret = send_freq(pkt, 913 chan_info, 914 pkt->command == RTE_POWER_QUERY_FREQ_LIST); 915 if (ret < 0) 916 RTE_LOG(ERR, CHANNEL_MONITOR, "Error during frequency sending.\n"); 917 } 918 919 if (pkt->command == RTE_POWER_QUERY_CAPS_LIST || 920 pkt->command == RTE_POWER_QUERY_CAPS) { 921 922 RTE_LOG(INFO, CHANNEL_MONITOR, 923 "Capabilities for %s requested.\n", pkt->vm_name); 924 int ret = send_capabilities(pkt, 925 chan_info, 926 pkt->command == RTE_POWER_QUERY_CAPS_LIST); 927 if (ret < 0) 928 RTE_LOG(ERR, CHANNEL_MONITOR, "Error during sending capabilities.\n"); 929 } 930 931 /* 932 * Return is not checked as channel status may have been set to DISABLED 933 * from management thread 934 */ 935 rte_atomic32_cmpset(&(chan_info->status), CHANNEL_MGR_CHANNEL_PROCESSING, 936 CHANNEL_MGR_CHANNEL_CONNECTED); 937 return 0; 938 939 } 940 941 int 942 add_channel_to_monitor(struct channel_info **chan_info) 943 { 944 struct channel_info *info = *chan_info; 945 struct epoll_event event; 946 947 event.events = EPOLLIN; 948 event.data.ptr = info; 949 if (epoll_ctl(global_event_fd, EPOLL_CTL_ADD, info->fd, &event) < 0) { 950 RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to add channel '%s' " 951 "to epoll\n", info->channel_path); 952 return -1; 953 } 954 RTE_LOG(ERR, CHANNEL_MONITOR, "Added channel '%s' " 955 "to monitor\n", info->channel_path); 956 return 0; 957 } 958 959 int 960 remove_channel_from_monitor(struct channel_info *chan_info) 961 { 962 if (epoll_ctl(global_event_fd, EPOLL_CTL_DEL, 963 chan_info->fd, NULL) < 0) { 964 RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to remove channel '%s' " 965 "from epoll\n", chan_info->channel_path); 966 return -1; 967 } 968 return 0; 969 } 970 971 int 972 channel_monitor_init(void) 973 { 974 global_event_fd = epoll_create1(0); 975 if (global_event_fd == 0) { 976 RTE_LOG(ERR, CHANNEL_MONITOR, 977 "Error creating epoll context with error %s\n", 978 strerror(errno)); 979 return -1; 980 } 981 global_events_list = rte_malloc("epoll_events", 982 sizeof(*global_events_list) 983 * MAX_EVENTS, RTE_CACHE_LINE_SIZE); 984 if (global_events_list == NULL) { 985 RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to rte_malloc for " 986 "epoll events\n"); 987 return -1; 988 } 989 return 0; 990 } 991 992 static void 993 read_binary_packet(struct channel_info *chan_info) 994 { 995 struct rte_power_channel_packet pkt; 996 void *buffer = &pkt; 997 int buffer_len = sizeof(pkt); 998 int n_bytes, err = 0; 999 1000 while (buffer_len > 0) { 1001 n_bytes = read(chan_info->fd, 1002 buffer, buffer_len); 1003 if (n_bytes == buffer_len) 1004 break; 1005 if (n_bytes < 0) { 1006 err = errno; 1007 RTE_LOG(DEBUG, CHANNEL_MONITOR, 1008 "Received error on " 1009 "channel '%s' read: %s\n", 1010 chan_info->channel_path, 1011 strerror(err)); 1012 remove_channel(&chan_info); 1013 break; 1014 } 1015 buffer = (char *)buffer + n_bytes; 1016 buffer_len -= n_bytes; 1017 } 1018 if (!err) 1019 process_request(&pkt, chan_info); 1020 } 1021 1022 #ifdef USE_JANSSON 1023 static void 1024 read_json_packet(struct channel_info *chan_info) 1025 { 1026 struct rte_power_channel_packet pkt; 1027 int n_bytes, ret; 1028 json_t *root; 1029 json_error_t error; 1030 const char *resource_name; 1031 char *start, *end; 1032 uint32_t n; 1033 1034 1035 /* read opening brace to closing brace */ 1036 do { 1037 int idx = 0; 1038 int indent = 0; 1039 do { 1040 n_bytes = read(chan_info->fd, &json_data[idx], 1); 1041 if (n_bytes == 0) 1042 break; 1043 if (json_data[idx] == '{') 1044 indent++; 1045 if (json_data[idx] == '}') 1046 indent--; 1047 if ((indent > 0) || (idx > 0)) 1048 idx++; 1049 if (indent <= 0) 1050 json_data[idx] = 0; 1051 if (idx >= MAX_JSON_STRING_LEN-1) 1052 break; 1053 } while (indent > 0); 1054 1055 json_data[idx] = '\0'; 1056 1057 if (strlen(json_data) == 0) 1058 continue; 1059 1060 printf("got [%s]\n", json_data); 1061 1062 root = json_loads(json_data, 0, &error); 1063 1064 if (root) { 1065 resource_name = get_resource_name_from_chn_path( 1066 chan_info->channel_path); 1067 /* 1068 * Because our data is now in the json 1069 * object, we can overwrite the pkt 1070 * with a rte_power_channel_packet struct, using 1071 * parse_json_to_pkt() 1072 */ 1073 ret = parse_json_to_pkt(root, &pkt, resource_name); 1074 json_decref(root); 1075 if (ret) { 1076 RTE_LOG(ERR, CHANNEL_MONITOR, 1077 "Error validating JSON profile data\n"); 1078 break; 1079 } 1080 start = strstr(pkt.vm_name, 1081 CHANNEL_MGR_FIFO_PATTERN_NAME); 1082 if (start != NULL) { 1083 /* move past pattern to start of fifo id */ 1084 start += strlen(CHANNEL_MGR_FIFO_PATTERN_NAME); 1085 1086 end = start; 1087 n = (uint32_t)strtoul(start, &end, 10); 1088 1089 if (end[0] == '\0') { 1090 /* Add core id to core list */ 1091 pkt.num_vcpu = 1; 1092 pkt.vcpu_to_control[0] = n; 1093 process_request(&pkt, chan_info); 1094 } else { 1095 RTE_LOG(ERR, CHANNEL_MONITOR, 1096 "Cannot extract core id from fifo name\n"); 1097 } 1098 } else { 1099 process_request(&pkt, chan_info); 1100 } 1101 } else { 1102 RTE_LOG(ERR, CHANNEL_MONITOR, 1103 "JSON error on line %d: %s\n", 1104 error.line, error.text); 1105 } 1106 } while (n_bytes > 0); 1107 } 1108 #endif 1109 1110 void 1111 run_channel_monitor(void) 1112 { 1113 while (run_loop) { 1114 int n_events, i; 1115 1116 n_events = epoll_wait(global_event_fd, global_events_list, 1117 MAX_EVENTS, 1); 1118 if (!run_loop) 1119 break; 1120 for (i = 0; i < n_events; i++) { 1121 struct channel_info *chan_info = (struct channel_info *) 1122 global_events_list[i].data.ptr; 1123 if ((global_events_list[i].events & EPOLLERR) || 1124 (global_events_list[i].events & EPOLLHUP)) { 1125 RTE_LOG(INFO, CHANNEL_MONITOR, 1126 "Remote closed connection for " 1127 "channel '%s'\n", 1128 chan_info->channel_path); 1129 remove_channel(&chan_info); 1130 continue; 1131 } 1132 if (global_events_list[i].events & EPOLLIN) { 1133 1134 switch (chan_info->type) { 1135 case CHANNEL_TYPE_BINARY: 1136 read_binary_packet(chan_info); 1137 break; 1138 #ifdef USE_JANSSON 1139 case CHANNEL_TYPE_JSON: 1140 read_json_packet(chan_info); 1141 break; 1142 #endif 1143 default: 1144 break; 1145 } 1146 } 1147 } 1148 rte_delay_us(time_period_ms*1000); 1149 if (policy_is_set) { 1150 unsigned int j; 1151 1152 for (j = 0; j < RTE_DIM(policies); j++) { 1153 if (policies[j].enabled == 1) 1154 apply_policy(&policies[j]); 1155 } 1156 } 1157 } 1158 } 1159