1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 6 #include <stdint.h> 7 #include <string.h> 8 #include <stdio.h> 9 #include <termios.h> 10 11 #include <cmdline_rdline.h> 12 #include <cmdline_parse.h> 13 #include <cmdline_parse_string.h> 14 #include <cmdline_parse_num.h> 15 #include <cmdline_socket.h> 16 #include <cmdline.h> 17 #include <rte_log.h> 18 #include <rte_lcore.h> 19 #include <rte_ethdev.h> 20 21 #include <rte_power.h> 22 #include <guest_channel.h> 23 24 #include "vm_power_cli_guest.h" 25 26 27 #define CHANNEL_PATH "/dev/virtio-ports/virtio.serial.port.poweragent" 28 29 30 #define RTE_LOGTYPE_GUEST_CHANNEL RTE_LOGTYPE_USER1 31 32 struct cmd_quit_result { 33 cmdline_fixed_string_t quit; 34 }; 35 36 union PFID { 37 struct ether_addr addr; 38 uint64_t pfid; 39 }; 40 41 static struct channel_packet policy; 42 43 struct channel_packet * 44 get_policy(void) 45 { 46 return &policy; 47 } 48 49 int 50 set_policy_mac(int port, int idx) 51 { 52 struct channel_packet *policy; 53 union PFID pfid; 54 55 /* Use port MAC address as the vfid */ 56 rte_eth_macaddr_get(port, &pfid.addr); 57 58 printf("Port %u MAC: %02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 ":" 59 "%02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 "\n", 60 port, 61 pfid.addr.addr_bytes[0], pfid.addr.addr_bytes[1], 62 pfid.addr.addr_bytes[2], pfid.addr.addr_bytes[3], 63 pfid.addr.addr_bytes[4], pfid.addr.addr_bytes[5]); 64 policy = get_policy(); 65 policy->vfid[idx] = pfid.pfid; 66 return 0; 67 } 68 69 void 70 set_policy_defaults(struct channel_packet *pkt) 71 { 72 set_policy_mac(0, 0); 73 pkt->nb_mac_to_monitor = 1; 74 75 pkt->t_boost_status.tbEnabled = false; 76 77 pkt->vcpu_to_control[0] = 0; 78 pkt->vcpu_to_control[1] = 1; 79 pkt->num_vcpu = 2; 80 /* Dummy Population. */ 81 pkt->traffic_policy.min_packet_thresh = 96000; 82 pkt->traffic_policy.avg_max_packet_thresh = 1800000; 83 pkt->traffic_policy.max_max_packet_thresh = 2000000; 84 85 pkt->timer_policy.busy_hours[0] = 3; 86 pkt->timer_policy.busy_hours[1] = 4; 87 pkt->timer_policy.busy_hours[2] = 5; 88 pkt->timer_policy.quiet_hours[0] = 11; 89 pkt->timer_policy.quiet_hours[1] = 12; 90 pkt->timer_policy.quiet_hours[2] = 13; 91 92 pkt->timer_policy.hours_to_use_traffic_profile[0] = 8; 93 pkt->timer_policy.hours_to_use_traffic_profile[1] = 10; 94 95 pkt->core_type = CORE_TYPE_VIRTUAL; 96 pkt->workload = LOW; 97 pkt->policy_to_use = TIME; 98 pkt->command = PKT_POLICY; 99 strcpy(pkt->vm_name, "ubuntu2"); 100 } 101 102 static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result, 103 __attribute__((unused)) struct cmdline *cl, 104 __attribute__((unused)) void *data) 105 { 106 unsigned lcore_id; 107 108 RTE_LCORE_FOREACH(lcore_id) { 109 rte_power_exit(lcore_id); 110 } 111 cmdline_quit(cl); 112 } 113 114 cmdline_parse_token_string_t cmd_quit_quit = 115 TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit"); 116 117 cmdline_parse_inst_t cmd_quit = { 118 .f = cmd_quit_parsed, /* function to call */ 119 .data = NULL, /* 2nd arg of func */ 120 .help_str = "close the application", 121 .tokens = { /* token list, NULL terminated */ 122 (void *)&cmd_quit_quit, 123 NULL, 124 }, 125 }; 126 127 /* *** VM operations *** */ 128 129 struct cmd_set_cpu_freq_result { 130 cmdline_fixed_string_t set_cpu_freq; 131 uint8_t lcore_id; 132 cmdline_fixed_string_t cmd; 133 }; 134 135 static void 136 cmd_set_cpu_freq_parsed(void *parsed_result, struct cmdline *cl, 137 __attribute__((unused)) void *data) 138 { 139 int ret = -1; 140 struct cmd_set_cpu_freq_result *res = parsed_result; 141 142 if (!strcmp(res->cmd , "up")) 143 ret = rte_power_freq_up(res->lcore_id); 144 else if (!strcmp(res->cmd , "down")) 145 ret = rte_power_freq_down(res->lcore_id); 146 else if (!strcmp(res->cmd , "min")) 147 ret = rte_power_freq_min(res->lcore_id); 148 else if (!strcmp(res->cmd , "max")) 149 ret = rte_power_freq_max(res->lcore_id); 150 else if (!strcmp(res->cmd, "enable_turbo")) 151 ret = rte_power_freq_enable_turbo(res->lcore_id); 152 else if (!strcmp(res->cmd, "disable_turbo")) 153 ret = rte_power_freq_disable_turbo(res->lcore_id); 154 if (ret != 1) 155 cmdline_printf(cl, "Error sending message: %s\n", strerror(ret)); 156 } 157 158 cmdline_parse_token_string_t cmd_set_cpu_freq = 159 TOKEN_STRING_INITIALIZER(struct cmd_set_cpu_freq_result, 160 set_cpu_freq, "set_cpu_freq"); 161 cmdline_parse_token_string_t cmd_set_cpu_freq_core_num = 162 TOKEN_NUM_INITIALIZER(struct cmd_set_cpu_freq_result, 163 lcore_id, UINT8); 164 cmdline_parse_token_string_t cmd_set_cpu_freq_cmd_cmd = 165 TOKEN_STRING_INITIALIZER(struct cmd_set_cpu_freq_result, 166 cmd, "up#down#min#max#enable_turbo#disable_turbo"); 167 168 cmdline_parse_inst_t cmd_set_cpu_freq_set = { 169 .f = cmd_set_cpu_freq_parsed, 170 .data = NULL, 171 .help_str = "set_cpu_freq <core_num> " 172 "<up|down|min|max|enable_turbo|disable_turbo>, " 173 "adjust the frequency for the specified core.", 174 .tokens = { 175 (void *)&cmd_set_cpu_freq, 176 (void *)&cmd_set_cpu_freq_core_num, 177 (void *)&cmd_set_cpu_freq_cmd_cmd, 178 NULL, 179 }, 180 }; 181 182 struct cmd_send_policy_result { 183 cmdline_fixed_string_t send_policy; 184 cmdline_fixed_string_t cmd; 185 }; 186 187 static inline int 188 send_policy(struct channel_packet *pkt) 189 { 190 int ret; 191 192 ret = rte_power_guest_channel_send_msg(pkt, 1); 193 if (ret == 0) 194 return 1; 195 RTE_LOG(DEBUG, POWER, "Error sending message: %s\n", 196 ret > 0 ? strerror(ret) : "channel not connected"); 197 return -1; 198 } 199 200 static void 201 cmd_send_policy_parsed(void *parsed_result, struct cmdline *cl, 202 __attribute__((unused)) void *data) 203 { 204 int ret = -1; 205 struct cmd_send_policy_result *res = parsed_result; 206 207 if (!strcmp(res->cmd, "now")) { 208 printf("Sending Policy down now!\n"); 209 ret = send_policy(&policy); 210 } 211 if (ret != 1) 212 cmdline_printf(cl, "Error sending message: %s\n", 213 strerror(ret)); 214 } 215 216 cmdline_parse_token_string_t cmd_send_policy = 217 TOKEN_STRING_INITIALIZER(struct cmd_send_policy_result, 218 send_policy, "send_policy"); 219 cmdline_parse_token_string_t cmd_send_policy_cmd_cmd = 220 TOKEN_STRING_INITIALIZER(struct cmd_send_policy_result, 221 cmd, "now"); 222 223 cmdline_parse_inst_t cmd_send_policy_set = { 224 .f = cmd_send_policy_parsed, 225 .data = NULL, 226 .help_str = "send_policy now", 227 .tokens = { 228 (void *)&cmd_send_policy, 229 (void *)&cmd_send_policy_cmd_cmd, 230 NULL, 231 }, 232 }; 233 234 cmdline_parse_ctx_t main_ctx[] = { 235 (cmdline_parse_inst_t *)&cmd_quit, 236 (cmdline_parse_inst_t *)&cmd_send_policy_set, 237 (cmdline_parse_inst_t *)&cmd_set_cpu_freq_set, 238 NULL, 239 }; 240 241 void 242 run_cli(__attribute__((unused)) void *arg) 243 { 244 struct cmdline *cl; 245 246 cl = cmdline_stdin_new(main_ctx, "vmpower(guest)> "); 247 if (cl == NULL) 248 return; 249 250 cmdline_interact(cl); 251 cmdline_stdin_exit(cl); 252 } 253