net: add macro to extract MAC address bytes
[dpdk.git] / examples / vm_power_manager / guest_cli / vm_power_cli_guest.c
index 2d9e768..94bfbba 100644 (file)
@@ -19,7 +19,6 @@
 #include <rte_ethdev.h>
 
 #include <rte_power.h>
-#include <guest_channel.h>
 
 #include "vm_power_cli_guest.h"
 
 #define CHANNEL_PATH "/dev/virtio-ports/virtio.serial.port.poweragent"
 
 
-#define RTE_LOGTYPE_GUEST_CHANNEL RTE_LOGTYPE_USER1
+#define RTE_LOGTYPE_GUEST_CLI RTE_LOGTYPE_USER1
 
 struct cmd_quit_result {
        cmdline_fixed_string_t quit;
 };
 
 union PFID {
-       struct ether_addr addr;
+       struct rte_ether_addr addr;
        uint64_t pfid;
 };
 
-static struct channel_packet policy;
+static struct rte_power_channel_packet policy;
 
-struct channel_packet *
+struct rte_power_channel_packet *
 get_policy(void)
 {
        return &policy;
@@ -49,28 +48,36 @@ get_policy(void)
 int
 set_policy_mac(int port, int idx)
 {
-       struct channel_packet *policy;
+       struct rte_power_channel_packet *policy;
        union PFID pfid;
+       int ret;
 
        /* Use port MAC address as the vfid */
-       rte_eth_macaddr_get(port, &pfid.addr);
+       ret = rte_eth_macaddr_get(port, &pfid.addr);
+       if (ret != 0) {
+               printf("Failed to get device (port %u) MAC address: %s\n",
+                               port, rte_strerror(-ret));
+               return ret;
+       }
 
        printf("Port %u MAC: %02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 ":"
                        "%02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 "\n",
-                       port,
-                       pfid.addr.addr_bytes[0], pfid.addr.addr_bytes[1],
-                       pfid.addr.addr_bytes[2], pfid.addr.addr_bytes[3],
-                       pfid.addr.addr_bytes[4], pfid.addr.addr_bytes[5]);
+                       port, RTE_ETHER_ADDR_BYTES(&pfid.addr));
        policy = get_policy();
        policy->vfid[idx] = pfid.pfid;
        return 0;
 }
 
-void
-set_policy_defaults(struct channel_packet *pkt)
+int
+set_policy_defaults(struct rte_power_channel_packet *pkt)
 {
-       set_policy_mac(0, 0);
-       pkt->nb_mac_to_monitor = 1;
+       int ret;
+
+       ret = set_policy_mac(0, 0);
+       if (ret != 0)
+               pkt->nb_mac_to_monitor = 0;
+       else
+               pkt->nb_mac_to_monitor = 1;
 
        pkt->t_boost_status.tbEnabled = false;
 
@@ -92,16 +99,18 @@ set_policy_defaults(struct channel_packet *pkt)
        pkt->timer_policy.hours_to_use_traffic_profile[0] = 8;
        pkt->timer_policy.hours_to_use_traffic_profile[1] = 10;
 
-       pkt->core_type = CORE_TYPE_VIRTUAL;
-       pkt->workload = LOW;
-       pkt->policy_to_use = TIME;
-       pkt->command = PKT_POLICY;
-       strcpy(pkt->vm_name, "ubuntu2");
+       pkt->core_type = RTE_POWER_CORE_TYPE_VIRTUAL;
+       pkt->workload = RTE_POWER_WL_LOW;
+       pkt->policy_to_use = RTE_POWER_POLICY_TIME;
+       pkt->command = RTE_POWER_PKT_POLICY;
+       strlcpy(pkt->vm_name, "ubuntu2", sizeof(pkt->vm_name));
+
+       return 0;
 }
 
-static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result,
-                               __attribute__((unused)) struct cmdline *cl,
-                           __attribute__((unused)) void *data)
+static void cmd_quit_parsed(__rte_unused void *parsed_result,
+               __rte_unused struct cmdline *cl,
+               __rte_unused void *data)
 {
        unsigned lcore_id;
 
@@ -126,6 +135,270 @@ cmdline_parse_inst_t cmd_quit = {
 
 /* *** VM operations *** */
 
+struct cmd_freq_list_result {
+       cmdline_fixed_string_t query_freq;
+       cmdline_fixed_string_t cpu_num;
+};
+
+static int
+query_data(struct rte_power_channel_packet *pkt, unsigned int lcore_id)
+{
+       int ret;
+       ret = rte_power_guest_channel_send_msg(pkt, lcore_id);
+       if (ret < 0) {
+               RTE_LOG(ERR, GUEST_CLI, "Error sending message.\n");
+               return -1;
+       }
+       return 0;
+}
+
+static int
+receive_freq_list(struct rte_power_channel_packet_freq_list *pkt_freq_list,
+               unsigned int lcore_id)
+{
+       int ret;
+
+       ret = rte_power_guest_channel_receive_msg(pkt_freq_list,
+                       sizeof(*pkt_freq_list),
+                       lcore_id);
+       if (ret < 0) {
+               RTE_LOG(ERR, GUEST_CLI, "Error receiving message.\n");
+               return -1;
+       }
+       if (pkt_freq_list->command != RTE_POWER_FREQ_LIST) {
+               RTE_LOG(ERR, GUEST_CLI, "Unexpected message received.\n");
+               return -1;
+       }
+       return 0;
+}
+
+static void
+cmd_query_freq_list_parsed(void *parsed_result,
+               __rte_unused struct cmdline *cl,
+               __rte_unused void *data)
+{
+       struct cmd_freq_list_result *res = parsed_result;
+       unsigned int lcore_id;
+       struct rte_power_channel_packet_freq_list pkt_freq_list;
+       struct rte_power_channel_packet pkt;
+       bool query_list = false;
+       int ret;
+       char *ep;
+
+       memset(&pkt, 0, sizeof(pkt));
+       memset(&pkt_freq_list, 0, sizeof(pkt_freq_list));
+
+       if (!strcmp(res->cpu_num, "all")) {
+
+               /* Get first enabled lcore. */
+               lcore_id = rte_get_next_lcore(-1,
+                               0,
+                               0);
+               if (lcore_id == RTE_MAX_LCORE) {
+                       cmdline_printf(cl, "Enabled core not found.\n");
+                       return;
+               }
+
+               pkt.command = RTE_POWER_QUERY_FREQ_LIST;
+               strlcpy(pkt.vm_name, policy.vm_name, sizeof(pkt.vm_name));
+               query_list = true;
+       } else {
+               errno = 0;
+               lcore_id = (unsigned int)strtol(res->cpu_num, &ep, 10);
+               if (errno != 0 || lcore_id >= RTE_POWER_MAX_VCPU_PER_VM ||
+                       ep == res->cpu_num) {
+                       cmdline_printf(cl, "Invalid parameter provided.\n");
+                       return;
+               }
+               pkt.command = RTE_POWER_QUERY_FREQ;
+               strlcpy(pkt.vm_name, policy.vm_name, sizeof(pkt.vm_name));
+               pkt.resource_id = lcore_id;
+       }
+
+       ret = query_data(&pkt, lcore_id);
+       if (ret < 0) {
+               cmdline_printf(cl, "Error during sending frequency list query.\n");
+               return;
+       }
+
+       ret = receive_freq_list(&pkt_freq_list, lcore_id);
+       if (ret < 0) {
+               cmdline_printf(cl, "Error during frequency list reception.\n");
+               return;
+       }
+       if (query_list) {
+               unsigned int i;
+               for (i = 0; i < pkt_freq_list.num_vcpu; ++i)
+                       cmdline_printf(cl, "Frequency of [%d] vcore is %d.\n",
+                                       i,
+                                       pkt_freq_list.freq_list[i]);
+       } else {
+               cmdline_printf(cl, "Frequency of [%d] vcore is %d.\n",
+                               lcore_id,
+                               pkt_freq_list.freq_list[lcore_id]);
+       }
+}
+
+cmdline_parse_token_string_t cmd_query_freq_token =
+       TOKEN_STRING_INITIALIZER(struct cmd_freq_list_result, query_freq, "query_cpu_freq");
+cmdline_parse_token_string_t cmd_query_freq_cpu_num_token =
+       TOKEN_STRING_INITIALIZER(struct cmd_freq_list_result, cpu_num, NULL);
+
+cmdline_parse_inst_t cmd_query_freq_list = {
+       .f = cmd_query_freq_list_parsed,  /* function to call */
+       .data = NULL,      /* 2nd arg of func */
+       .help_str = "query_cpu_freq <core_num>|all, request"
+                               " information regarding virtual core frequencies."
+                               " The keyword 'all' will query list of all vcores for the VM",
+       .tokens = {        /* token list, NULL terminated */
+               (void *)&cmd_query_freq_token,
+               (void *)&cmd_query_freq_cpu_num_token,
+               NULL,
+       },
+};
+
+struct cmd_query_caps_result {
+       cmdline_fixed_string_t query_caps;
+       cmdline_fixed_string_t cpu_num;
+};
+
+static int
+receive_capabilities(struct rte_power_channel_packet_caps_list *pkt_caps_list,
+               unsigned int lcore_id)
+{
+       int ret;
+
+       ret = rte_power_guest_channel_receive_msg(pkt_caps_list,
+               sizeof(*pkt_caps_list),
+               lcore_id);
+       if (ret < 0) {
+               RTE_LOG(ERR, GUEST_CLI, "Error receiving message.\n");
+               return -1;
+       }
+       if (pkt_caps_list->command != RTE_POWER_CAPS_LIST) {
+               RTE_LOG(ERR, GUEST_CLI, "Unexpected message received.\n");
+               return -1;
+       }
+       return 0;
+}
+
+static void
+cmd_query_caps_list_parsed(void *parsed_result,
+               __rte_unused struct cmdline *cl,
+               __rte_unused void *data)
+{
+       struct cmd_query_caps_result *res = parsed_result;
+       unsigned int lcore_id;
+       struct rte_power_channel_packet_caps_list pkt_caps_list;
+       struct rte_power_channel_packet pkt;
+       bool query_list = false;
+       int ret;
+       char *ep;
+
+       memset(&pkt, 0, sizeof(pkt));
+       memset(&pkt_caps_list, 0, sizeof(pkt_caps_list));
+
+       if (!strcmp(res->cpu_num, "all")) {
+
+               /* Get first enabled lcore. */
+               lcore_id = rte_get_next_lcore(-1,
+                               0,
+                               0);
+               if (lcore_id == RTE_MAX_LCORE) {
+                       cmdline_printf(cl, "Enabled core not found.\n");
+                       return;
+               }
+
+               pkt.command = RTE_POWER_QUERY_CAPS_LIST;
+               strlcpy(pkt.vm_name, policy.vm_name, sizeof(pkt.vm_name));
+               query_list = true;
+       } else {
+               errno = 0;
+               lcore_id = (unsigned int)strtol(res->cpu_num, &ep, 10);
+               if (errno != 0 || lcore_id >= RTE_POWER_MAX_VCPU_PER_VM ||
+                       ep == res->cpu_num) {
+                       cmdline_printf(cl, "Invalid parameter provided.\n");
+                       return;
+               }
+               pkt.command = RTE_POWER_QUERY_CAPS;
+               strlcpy(pkt.vm_name, policy.vm_name, sizeof(pkt.vm_name));
+               pkt.resource_id = lcore_id;
+       }
+
+       ret = query_data(&pkt, lcore_id);
+       if (ret < 0) {
+               cmdline_printf(cl, "Error during sending capabilities query.\n");
+               return;
+       }
+
+       ret = receive_capabilities(&pkt_caps_list, lcore_id);
+       if (ret < 0) {
+               cmdline_printf(cl, "Error during capabilities reception.\n");
+               return;
+       }
+       if (query_list) {
+               unsigned int i;
+               for (i = 0; i < pkt_caps_list.num_vcpu; ++i)
+                       cmdline_printf(cl, "Capabilities of [%d] vcore are:"
+                                       " turbo possibility: %" PRId64 ", "
+                                       "is priority core: %" PRId64 ".\n",
+                                       i,
+                                       pkt_caps_list.turbo[i],
+                                       pkt_caps_list.priority[i]);
+       } else {
+               cmdline_printf(cl, "Capabilities of [%d] vcore are:"
+                               " turbo possibility: %" PRId64 ", "
+                               "is priority core: %" PRId64 ".\n",
+                               lcore_id,
+                               pkt_caps_list.turbo[lcore_id],
+                               pkt_caps_list.priority[lcore_id]);
+       }
+}
+
+cmdline_parse_token_string_t cmd_query_caps_token =
+       TOKEN_STRING_INITIALIZER(struct cmd_query_caps_result, query_caps, "query_cpu_caps");
+cmdline_parse_token_string_t cmd_query_caps_cpu_num_token =
+       TOKEN_STRING_INITIALIZER(struct cmd_query_caps_result, cpu_num, NULL);
+
+cmdline_parse_inst_t cmd_query_caps_list = {
+       .f = cmd_query_caps_list_parsed,  /* function to call */
+       .data = NULL,      /* 2nd arg of func */
+       .help_str = "query_cpu_caps <core_num>|all, request"
+                               " information regarding virtual core capabilities."
+                               " The keyword 'all' will query list of all vcores for the VM",
+       .tokens = {        /* token list, NULL terminated */
+               (void *)&cmd_query_caps_token,
+               (void *)&cmd_query_caps_cpu_num_token,
+               NULL,
+       },
+};
+
+static int
+check_response_cmd(unsigned int lcore_id, int *result)
+{
+       struct rte_power_channel_packet pkt;
+       int ret;
+
+       ret = rte_power_guest_channel_receive_msg(&pkt, sizeof pkt, lcore_id);
+       if (ret < 0)
+               return -1;
+
+       switch (pkt.command) {
+       case(RTE_POWER_CMD_ACK):
+               *result = 1;
+               break;
+       case(RTE_POWER_CMD_NACK):
+               *result = 0;
+               break;
+       default:
+               RTE_LOG(ERR, GUEST_CLI,
+                               "Received invalid response from host, expecting ACK/NACK.\n");
+               return -1;
+       }
+
+       return 0;
+}
+
 struct cmd_set_cpu_freq_result {
        cmdline_fixed_string_t set_cpu_freq;
        uint8_t lcore_id;
@@ -134,33 +407,44 @@ struct cmd_set_cpu_freq_result {
 
 static void
 cmd_set_cpu_freq_parsed(void *parsed_result, struct cmdline *cl,
-                      __attribute__((unused)) void *data)
+              __rte_unused void *data)
 {
        int ret = -1;
        struct cmd_set_cpu_freq_result *res = parsed_result;
 
-       if (!strcmp(res->cmd , "up"))
+       if (!strcmp(res->cmd, "up"))
                ret = rte_power_freq_up(res->lcore_id);
-       else if (!strcmp(res->cmd , "down"))
+       else if (!strcmp(res->cmd, "down"))
                ret = rte_power_freq_down(res->lcore_id);
-       else if (!strcmp(res->cmd , "min"))
+       else if (!strcmp(res->cmd, "min"))
                ret = rte_power_freq_min(res->lcore_id);
-       else if (!strcmp(res->cmd , "max"))
+       else if (!strcmp(res->cmd, "max"))
                ret = rte_power_freq_max(res->lcore_id);
        else if (!strcmp(res->cmd, "enable_turbo"))
                ret = rte_power_freq_enable_turbo(res->lcore_id);
        else if (!strcmp(res->cmd, "disable_turbo"))
                ret = rte_power_freq_disable_turbo(res->lcore_id);
-       if (ret != 1)
+
+       if (ret != 1) {
                cmdline_printf(cl, "Error sending message: %s\n", strerror(ret));
+               return;
+       }
+       int result;
+       ret = check_response_cmd(res->lcore_id, &result);
+       if (ret < 0) {
+               RTE_LOG(ERR, GUEST_CLI, "No confirmation for sent message received\n");
+       } else {
+               cmdline_printf(cl, "%s received for message sent to host.\n",
+                               result == 1 ? "ACK" : "NACK");
+       }
 }
 
 cmdline_parse_token_string_t cmd_set_cpu_freq =
        TOKEN_STRING_INITIALIZER(struct cmd_set_cpu_freq_result,
                        set_cpu_freq, "set_cpu_freq");
-cmdline_parse_token_string_t cmd_set_cpu_freq_core_num =
+cmdline_parse_token_num_t cmd_set_cpu_freq_core_num =
        TOKEN_NUM_INITIALIZER(struct cmd_set_cpu_freq_result,
-                       lcore_id, UINT8);
+                       lcore_id, RTE_UINT8);
 cmdline_parse_token_string_t cmd_set_cpu_freq_cmd_cmd =
        TOKEN_STRING_INITIALIZER(struct cmd_set_cpu_freq_result,
                        cmd, "up#down#min#max#enable_turbo#disable_turbo");
@@ -185,28 +469,38 @@ struct cmd_send_policy_result {
 };
 
 static inline int
-send_policy(struct channel_packet *pkt)
+send_policy(struct rte_power_channel_packet *pkt, struct cmdline *cl)
 {
        int ret;
 
        ret = rte_power_guest_channel_send_msg(pkt, 1);
-       if (ret == 0)
-               return 1;
-       RTE_LOG(DEBUG, POWER, "Error sending message: %s\n",
-                       ret > 0 ? strerror(ret) : "channel not connected");
-       return -1;
+       if (ret < 0) {
+               RTE_LOG(ERR, GUEST_CLI, "Error sending message: %s\n",
+                               ret > 0 ? strerror(ret) : "channel not connected");
+               return -1;
+       }
+
+       int result;
+       ret = check_response_cmd(1, &result);
+       if (ret < 0) {
+               RTE_LOG(ERR, GUEST_CLI, "No confirmation for sent policy received\n");
+       } else {
+               cmdline_printf(cl, "%s for sent policy received.\n",
+                               result == 1 ? "ACK" : "NACK");
+       }
+       return 1;
 }
 
 static void
 cmd_send_policy_parsed(void *parsed_result, struct cmdline *cl,
-                      __attribute__((unused)) void *data)
+               __rte_unused void *data)
 {
        int ret = -1;
        struct cmd_send_policy_result *res = parsed_result;
 
        if (!strcmp(res->cmd, "now")) {
                printf("Sending Policy down now!\n");
-               ret = send_policy(&policy);
+               ret = send_policy(&policy, cl);
        }
        if (ret != 1)
                cmdline_printf(cl, "Error sending message: %s\n",
@@ -235,11 +529,13 @@ cmdline_parse_ctx_t main_ctx[] = {
                (cmdline_parse_inst_t *)&cmd_quit,
                (cmdline_parse_inst_t *)&cmd_send_policy_set,
                (cmdline_parse_inst_t *)&cmd_set_cpu_freq_set,
+               (cmdline_parse_inst_t *)&cmd_query_freq_list,
+               (cmdline_parse_inst_t *)&cmd_query_caps_list,
                NULL,
 };
 
 void
-run_cli(__attribute__((unused)) void *arg)
+run_cli(__rte_unused void *arg)
 {
        struct cmdline *cl;