命令行配置UPGW LOG等级

目前UPGW的LOG等级可以在程序启动时通过dpdk的命令参数–log-level来配置,如下:

./build/app/nes-daemon -n 4 --log-level="NES":8 --lcores='(0,4,5)@2,1@3,2@4,3@5' --huge-dir /dev/hugepages --socket-mem 2048

这样不太方便,想要修改LOG级别还要重启程序,所以增加自己的命令行来配置LOG级别,该命令行的框架如下。

cmd_nes_log

main_ctx、cmd_nes_loglevel_set_func、nes_set_loglevel属于nes_cli模块,负责进行命令的下发;nes_loglevel_set_client属于nes_api模块,负责进行命令数据的传递;nes_loglevel_set_server属于nes_ctrl模块,通过function_id(这里是eNesloglevelset),接收下发的数据,解析后调用相关接口进行日志等级配置。

nes_cli模块

typedef struct cmd_nes_loglevel_set_result {
    cmdline_fixed_string_t nes_loglevel_set;
    uint8_t loglevel;
} cmd_nes_loglevel_set_result;

cmdline_parse_token_string_t cmd_nes_loglevel_set =
    TOKEN_STRING_INITIALIZER(struct cmd_nes_loglevel_set_result, nes_loglevel_set, "nes-loglevel-set");

cmdline_parse_token_num_t cmd_nes_loglevel =
    TOKEN_NUM_INITIALIZER(struct cmd_nes_loglevel_set_result, loglevel, UINT8);

static void
nes_set_loglevel(void *parsed_result,
    __attribute__((unused)) struct cmdline *nes_cmdline, __attribute__((unused)) void *data) {
    struct cmd_nes_loglevel_set_result *res = parsed_result;

    if (NES_SUCCESS != nes_loglevel_set_client(&remote_NEV, res->loglevel))
        cmdline_printf(nes_cmdline, "Nes loglevel set fail!\n");
    else
        cmdline_printf(nes_cmdline, "Nes loglevel set success!\n");
}

cmdline_parse_inst_t cmd_nes_loglevel_set_func = {
    .f = nes_set_loglevel,
    .data = NULL,
    .help_str = "Nes loglevel set",
    .tokens =
    {
        (void *) &cmd_nes_loglevel_set,
        (void *) &cmd_nes_loglevel,
        NULL,
    },
};

如上,该命令行有两个参数组成,第一个参数是命令提示符nes-loglevel-set,第二个参数为一个uint8_t类型的数字loglevel,表示日志等级,可配置级别如下,值越大等级越高,输出的内容越多。

#define RTE_LOG_EMERG    1U  /**< System is unusable.               */
#define RTE_LOG_ALERT    2U  /**< Action must be taken immediately. */
#define RTE_LOG_CRIT     3U  /**< Critical conditions.              */
#define RTE_LOG_ERR      4U  /**< Error conditions.                 */
#define RTE_LOG_WARNING  5U  /**< Warning conditions.               */
#define RTE_LOG_NOTICE   6U  /**< Normal but significant condition. */
#define RTE_LOG_INFO     7U  /**< Informational.                    */
#define RTE_LOG_DEBUG    8U  /**< Debug-level messages.             */

nes_api模块

api_msg = malloc(sizeof(nes_api_msg_t) + data_len);
VERIFY_PTR_OR_RET(api_msg, NES_FAIL);
api_msg->message_type = eRequest;
api_msg->function_id = eNesloglevelset;
*api_msg->data = loglevel;

api_msg->data_size = data_len;

if (NES_SUCCESS != nes_send_api_msg(self, api_msg, &api_response)) {
    free(api_msg);
    return NES_FAIL;
}

将命令行配置的loglevel数据赋予api_msg,同时给api_msg赋予相应的function_id,最后将此msg消息传递下去,让后续模块处理。

nes_ctrl模块

case eNesloglevelset:
    if (NULL == (*response = nes_loglevel_set_server(api_msg)))
        NES_LOG(ERR, "NES loglevel set fail");
    break;
loglevel = *api_msg->data;

if (NES_SUCCESS != rte_log_set_level(logtype_nes, loglevel)) {
    response->message_type = eError;
    response->data_size = 0;
    return response;
}

通过解析到的function_id(eNesloglevelset)去调用nes_loglevel_set_server函数,该函数解析出loglevel后,直接调用dpdk模块的接口去配置对应模块的log等级。

验证说明

程序启动后,默认日志等级为7(RTE_LOG_INFO),RTE_LOG_DEBUG等级的日志不会输出,使用命令“nes-loglevel-set 8”配置后,RTE_LOG_DEBUG等级的日志可以输出,验证OK。