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