acrn-hypervisor/misc/services/life_mngr/command.c
Xiangyang Wu ecf99c45a3 Misc: life_mngr: support user VM reboot
Add user VM reboot command and related command handler in
lifecycle manager to support user VM reboot.

Libvirt will send user VM reboot command to lifecycle manager
of service VM through socket, this command is forwarded to the
specified user VM, user VM will execute reboot command to start
reboot itself.

v1-->v2:
	Update some interfaces name to make it reable:
        (1) enable_uart_channel_dev_resend -->
	start_uart_channel_dev_resend
	(2) enable_all_uart_channel_dev_resend -->
	start_all_uart_channel_dev_resend
	(3) disable_uart_channel_dev_resend -->
	stop_uart_channel_dev_resend
	(4) get_reboot_flag --> get_user_vm_reboot_flag

Tracked-On: #5921

Signed-off-by: Xiangyang Wu <xiangyang.wu@intel.com>
Acked-by: Wang, Yu1 <yu1.wang@intel.com>
2022-03-03 14:40:04 +08:00

104 lines
2.8 KiB
C

/*
* Copyright (C)2021 Intel Corporation
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include "command.h"
#include "log.h"
#define GEN_CMD_OBJ(cmd_name, cmd_id) \
{.name = cmd_name, .id = cmd_id, .cmd_handler_mtx = PTHREAD_MUTEX_INITIALIZER}
#define CMD_OBJS \
GEN_CMD_OBJ(SYNC_CMD, SYNC_ID), \
GEN_CMD_OBJ(ACK_SYNC, ACKED_SYNC_ID), \
GEN_CMD_OBJ(REQ_SYS_SHUTDOWN, REQ_SYS_SHUTDOWN_ID), \
GEN_CMD_OBJ(ACK_REQ_SYS_SHUTDOWN, ACKED_REQ_SYS_SHUTDOWN_ID), \
GEN_CMD_OBJ(POWEROFF_CMD, POWEROFF_CMD_ID), \
GEN_CMD_OBJ(ACK_POWEROFF, ACKED_POWEROFF_ID), \
GEN_CMD_OBJ(ACK_TIMEOUT, ACK_TIMEOUT_ID), \
GEN_CMD_OBJ(REQ_USER_VM_SHUTDOWN, REQ_USER_VM_SHUTDOWN_ID), \
GEN_CMD_OBJ(USER_VM_SHUTDOWN, USER_VM_SHUTDOWN_ID),\
GEN_CMD_OBJ(ACK_USER_VM_SHUTDOWN, ACK_USER_VM_SHUTDOWN_ID),\
GEN_CMD_OBJ(REQ_USER_VM_REBOOT, REQ_USER_VM_REBOOT_ID), \
GEN_CMD_OBJ(USER_VM_REBOOT, USER_VM_REBOOT_ID),\
GEN_CMD_OBJ(ACK_USER_VM_REBOOT, ACK_USER_VM_REBOOT_ID),\
struct command dm_command_list[CMD_END] = {CMD_OBJS};
int dispatch_command_handlers(void *arg, int fd)
{
struct command *cmd = (struct command *)arg;
struct command_handlers *handler;
unsigned int count = 0U;
int ret = 0;
if (cmd == NULL) {
LOG_PRINTF("Invalid command, fd=%d\n", fd);
return -EINVAL;
}
LOG_PRINTF("Handle command (%s) in command monitor\n", cmd->name);
LIST_FOREACH(handler, &cmd->cmd_handlers_head, list) {
if (handler->fn) {
ret = handler->fn(handler->arg, fd);
count++;
}
}
LOG_PRINTF("Command handler ret=%d\n", ret);
if (!count)
LOG_PRINTF("No handler for command:%s\r\n", cmd->name);
return 0;
}
struct command *find_command(const char *name)
{
for (int i = 0; (i < CMD_END) && (name != NULL); i++) {
if (strcmp(dm_command_list[i].name, name) == 0)
return &dm_command_list[i];
}
return NULL;
}
int register_command_handler(cmd_handler *fn, void *arg, const char *cmd_name)
{
struct command *cmd;
struct command_handlers *handler;
if ((!fn) || (!arg) || (!cmd_name)) {
LOG_PRINTF("%s:Failed to register command_handler\n", __func__);
return -EINVAL;
}
cmd = find_command(cmd_name);
if (cmd == NULL) {
LOG_PRINTF("%s:invalid command name (%s)\r\n", __func__, cmd_name);
return -EINVAL;
}
handler = calloc(1, sizeof(*handler));
if (!handler) {
LOG_WRITE("Failed to allocate command handler\r\n");
return -ENOMEM;
}
handler->fn = fn;
handler->arg = arg;
pthread_mutex_lock(&cmd->cmd_handler_mtx);
LIST_INSERT_HEAD(&cmd->cmd_handlers_head, handler, list);
pthread_mutex_unlock(&cmd->cmd_handler_mtx);
return 0;
}