DM: add command module for command monitor

The command module provides interfaces to find a command
intance, register handler for specified command, dispatch
command and invoke related handler.
find_command: find a command instance by name.
register_command_handler: register the handler for one
command instance.
dispatch_command_handlers: dispatch the command and invoke
registered handler.

v1-->v2:
	Only support single handler for one command instance.
v2-->v3:
	Remove command id.
	Add error check to avoid regiter handler to command
	instance which has handler.
	Update the second parameter type of register_command_handler
	to avoid unnecessary type conversion.

Tracked-On: #5921

Signed-off-by: Xiangyang Wu <xiangyang.wu@intel.com>
Acked-by: Wang, Yu1 <yu1.wang@intel.com>
This commit is contained in:
Xiangyang Wu 2022-01-20 08:12:04 +08:00 committed by acrnsi-robot
parent 26fdfc6a30
commit a31bd7bb0d
2 changed files with 149 additions and 0 deletions

View File

@ -0,0 +1,88 @@
/*
* Copyright (C) 2022 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 "vmmapi.h"
#include "log.h"
#define GEN_CMD_OBJ(cmd_name) \
{.name = cmd_name,}
#define CMD_OBJS \
GEN_CMD_OBJ(DESTROY), \
GEN_CMD_OBJ(BLKRESCAN), \
struct command dm_command_list[CMDS_NUM] = {CMD_OBJS};
int dispatch_command_handlers(void *arg)
{
struct command *cmd = (struct command *)arg;
int ret = 0;
pr_info("Handle command %s in command monitor.\n", cmd->name);
if (cmd->cmd_handler.fn) {
ret = cmd->cmd_handler.fn(cmd->cmd_handler.arg, &cmd->para);
pr_info("Command handler ret=%d.\n", ret);
} else {
pr_info("No handler for command: %s.\r\n", cmd->name);
}
return 0;
}
struct command *find_command(const char *name)
{
for (int i = 0; (i < CMDS_NUM) && (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, struct handler_args *arg, const char *cmd_name)
{
struct command *cmd;
struct handler_args *handler_arg;
if ((!fn) || (!arg) || (!cmd_name)) {
pr_err("%s : Failed to register command_handler.\n", __func__);
return -EINVAL;
}
cmd = find_command(cmd_name);
if (cmd == NULL) {
pr_err("%s : invalid command name %s.\r\n", __func__, cmd_name);
return -EINVAL;
}
if (cmd->cmd_handler.fn != NULL) {
pr_err("Failed to register command handler since the handler have already been registered.\n");
return -EINVAL;
}
cmd->cmd_handler.fn = fn;
handler_arg = calloc(1, sizeof(*handler_arg));
if (!handler_arg) {
pr_err("Failed to allocate command handler argument.\r\n");
return -ENOMEM;
}
cmd->cmd_handler.arg = handler_arg;
cmd->cmd_handler.arg->channel_arg = arg->channel_arg;
cmd->cmd_handler.arg->ctx_arg = arg->ctx_arg;
return 0;
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (C) 2022 Intel Corporation
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _COMMAND_H_
#define _COMMAND_H_
#include <pthread.h>
#include <sys/queue.h>
#define DESTROY "destroy"
#define BLKRESCAN "blkrescan"
#define CMDS_NUM 2U
#define CMD_NAME_MAX 32U
#define CMD_ARG_MAX 320U
typedef int (cmd_handler)(void *arg, void *command_para);
struct handler_args {
void *channel_arg;
void *ctx_arg;
};
struct command_handler {
struct handler_args *arg;
cmd_handler *fn;
};
struct command_parameters {
int fd;
char option[CMD_ARG_MAX];
};
struct command {
const char name[CMD_NAME_MAX]; /**< command name */
struct command_parameters para;
/* command handler */
struct command_handler cmd_handler;
};
/**
* @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, struct handler_args *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
* @return the flag indicates the state of command handler execution
*/
int dispatch_command_handlers(void *arg);
#endif