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