mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-21 05:02:24 +00:00
misc: life_mngr: add command module
In the command module, the following functions are implemented: - register_command_handler Provide one interface to register command handler, other module can use this interface to register multiple handler for one command. - find_command Provide one interface to find a command instance by name; - dispatch_command_handlers Provide one interface to dispatch the command and invoke registered handler. v1-->v2: Add comments in head file. v2-->v3: Update interface name since "dm" prefix is useless. Update some log message. v3-->v4: Support guest shutdown. v4-->v5: Refine command name and add parameter check for interface. v5-->v6: Remove allow s5 command. Tracked-On: #6652 Signed-off-by: Xiangyang Wu <xiangyang.wu@intel.com> Reviewed-by: fei1.li@intel.com
This commit is contained in:
parent
62b19fe50d
commit
db182ead67
100
misc/services/life_mngr/command.c
Normal file
100
misc/services/life_mngr/command.c
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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),\
|
||||
|
||||
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;
|
||||
}
|
87
misc/services/life_mngr/command.h
Normal file
87
misc/services/life_mngr/command.h
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C)2021 Intel Corporation
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef _CMD_H_
|
||||
#define _CMD_H_
|
||||
#include <pthread.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
|
||||
#define SYNC_CMD "sync"
|
||||
#define ACK_SYNC "ack_sync"
|
||||
#define REQ_SYS_SHUTDOWN "req_sys_shutdown"
|
||||
#define ACK_REQ_SYS_SHUTDOWN "ack_req_sys_shutdown"
|
||||
#define POWEROFF_CMD "poweroff_cmd"
|
||||
#define ACK_POWEROFF "ack_poweroff"
|
||||
#define ACK_TIMEOUT "ack_timeout"
|
||||
#define REQ_USER_VM_SHUTDOWN "req_user_vm_shutdown"
|
||||
#define USER_VM_SHUTDOWN "user_vm_shutdown"
|
||||
|
||||
#define ACK_REQ_USER_VM_SHUTDOWN "ack_req_user_vm_shutdown"
|
||||
#define ACK_USER_VM_SHUTDOWN "ack_user_vm_shutdown"
|
||||
#define FAIL_CONNECT "fail_connect"
|
||||
#define USER_VM_DISCONNECT "user_vm_disconnect"
|
||||
#define S5_REJECTED "system shutdown request is rejected"
|
||||
|
||||
#define SYNC_LEN (sizeof(SYNC_CMD))
|
||||
|
||||
#define POWEROFF "poweroff"
|
||||
|
||||
#define CMD_NAME_MAX 32U
|
||||
|
||||
enum command_id {
|
||||
SYNC_ID = 0x0,
|
||||
ACKED_SYNC_ID,
|
||||
REQ_SYS_SHUTDOWN_ID,
|
||||
ACKED_REQ_SYS_SHUTDOWN_ID,
|
||||
POWEROFF_CMD_ID,
|
||||
ACKED_POWEROFF_ID,
|
||||
ACK_TIMEOUT_ID,
|
||||
REQ_USER_VM_SHUTDOWN_ID,
|
||||
USER_VM_SHUTDOWN_ID,
|
||||
ACK_USER_VM_SHUTDOWN_ID,
|
||||
CMD_END,
|
||||
};
|
||||
|
||||
typedef int (cmd_handler)(void *arg, int fd);
|
||||
struct command_handlers {
|
||||
void *arg;
|
||||
cmd_handler *fn;
|
||||
|
||||
LIST_ENTRY(command_handlers) list;
|
||||
};
|
||||
|
||||
struct command {
|
||||
const char name[CMD_NAME_MAX]; /**< command name */
|
||||
enum command_id id; /**< command id */
|
||||
|
||||
/* command handler list */
|
||||
LIST_HEAD(cmd_handlers_list, command_handlers) cmd_handlers_head;
|
||||
pthread_mutex_t cmd_handler_mtx; /**< mutex to protect command handler list */
|
||||
};
|
||||
/**
|
||||
* @brief register command handler, other module can use this interface to
|
||||
* register multiple handler for one command.
|
||||
*
|
||||
* @param fn the command handler which will be registered
|
||||
* @param arg the parameter which will be passed into hanlder
|
||||
* @param cmd_name the command name
|
||||
*/
|
||||
int register_command_handler(cmd_handler *fn, void *arg, const char *cmd_name);
|
||||
/**
|
||||
* @brief find a command instance by name
|
||||
*
|
||||
* @param name the command name
|
||||
* @return command instance
|
||||
*/
|
||||
struct command *find_command(const char *name);
|
||||
/**
|
||||
* @brief dispatch the command and invoke registered handler.
|
||||
*
|
||||
* @param arg command instance
|
||||
* @param fd the file descriptor of the device
|
||||
* @return the flag indicates the state of command handler execution
|
||||
*/
|
||||
int dispatch_command_handlers(void *arg, int fd);
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user