前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >深入浅出思科VPP24.02系列:日志模块vlib_log_init逻辑介绍

深入浅出思科VPP24.02系列:日志模块vlib_log_init逻辑介绍

作者头像
通信行业搬砖工
发布2024-10-21 10:14:31
发布2024-10-21 10:14:31
15900
代码可运行
举报
文章被收录于专栏:网络虚拟化网络虚拟化
运行总次数:0
代码可运行

01=上期内容回顾

本期我们将继续深入浅出思科vpp24.02系列专题,介绍VPP的日志log功能初始化的函数的业务逻辑介绍。

02=vlib_log_init函数介绍

在往期的内容中,我们介绍了思科VPP软件对日志功能的初始化的函数vlib_log_init()的业务逻辑介绍,其在vlib_main()中备调用的。

log模块初始化逻辑如下所示

代码语言:javascript
代码运行次数:0
复制
clib_error_t *vlib_log_init (vlib_main_t *vm)
{
  vlib_log_main_t *lm = &log_main;
  vlib_log_class_registration_t *r = lm->registrations;

  gettimeofday (&lm->time_zero_timeval, 0);
  lm->time_zero = vlib_time_now (vm);

  vec_validate (lm->entries, lm->size);

  while (r)
    {
      r->class = vlib_log_register_class (r->class_name, r->subclass_name);
      if (r->default_level)
  vlib_log_get_subclass_data (r->class)->level = r->default_level;
      if (r->default_syslog_level)
  vlib_log_get_subclass_data (r->class)->syslog_level =
    r->default_syslog_level;
      r = r->next;
    }

  r = lm->registrations;
  while (r)
    {
      vlib_log_debug (r->class, "initialized");
      r = r->next;
    }
  return 0;
}

函数声明:clib_error_t *vlib_log_init (vlib_main_t *vm);

返回值:此处应该返回clib_error_t 类型的更佳。

03=函数工程意义分析

1、日志系统的主要结构体:这里lm是指向日志系统主要结构的指针,它引用了全局变量log_main。这个结构包含了日志系统的各种状态和配置。。

代码语言:javascript
代码运行次数:0
复制
  vlib_log_main_t *lm = &log_main;
  vlib_log_class_registration_t *r = lm->registrations;

结构体介绍:vlib_log_main_t用于管理和配置日志记录的行为:

代码语言:javascript
代码运行次数:0
复制
typedef struct
{
  vlib_log_entry_t *entries;
  vlib_log_class_data_t *classes;
  int size, next, count;

  int default_rate_limit;
  int default_log_level;
  int default_syslog_log_level;
  int unthrottle_time;
  u32 max_class_name_length;

  /* time zero */
  struct timeval time_zero_timeval;
  f64 time_zero;

  /* config */
  vlib_log_class_config_t *configs;
  uword *config_index_by_name;
  int add_to_elog;

  /* registrations */
  vlib_log_class_registration_t *registrations;
} vlib_log_main_t

结构体参数解释:

  1. vlib_log_entry_t *entries;这是一个指向日志条目数组的指针,每个条目记录了一个具体的日志事件。
  2. vlib_log_class_data_t *classes;指向日志类别数据数组的指针,日志类别用于区分不同类型的日志消息。
  3. int size, next, count;size 表示日志条目数组的大小。next 指向下一个将要写入的日志条目的索引。count 表示当前已记录的日志条目数量。
  4. 日志配置参数
    • int default_rate_limit; 默认速率限制,用于控制日志输出的频率。
    • int default_log_level; 默认日志级别,决定哪些级别的日志消息应该被记录。
    • int default_syslog_log_level; 默认的系统日志级别,控制哪些级别的日志应该被发送到系统日志。
    • int unthrottle_time; 解限时间,用于在达到速率限制后,指定多少时间后可以再次记录日志。
  5. u32 max_class_name_length;日志类别名称的最大长度。
  6. 时间相关
    • struct timeval time_zero_timeval; 记录了“时间零点”的timeval结构体,用于时间戳的计算。
    • f64 time_zero; “时间零点”的浮点数表示,通常用于更精确的时间计算。
  7. 配置信息
    • vlib_log_class_config_t *configs; 指向日志类别配置数组的指针。
    • uword *config_index_by_name; 通过日志类别名称查找配置的索引数组。
    • int add_to_elog; 一个标志,指示是否将日志消息添加到错误日志中。
  8. 注册信息:vlib_log_class_registration_t *registrations; 指向日志类别注册信息的指针,用于跟踪哪些日志类别已经被注册。

2、时间戳操作

代码语言:javascript
代码运行次数:0
复制
  gettimeofday (&lm->time_zero_timeval, 0);
  lm->time_zero = vlib_time_now (vm);

gettimeofday 是linux系统函数,它的目的是获取当前时间戳,并将其存储在lm->time_zero_timeval中。

lm->time_zero = vlib_time_now(vm);使用VPP时间函数获取时间戳,将其存放在lm->time_zero 之中。

3、验证日志条目数量的大小,确保其大小够用,该部分会采用vpp的vec机制,如果空间大小不够,会自动拓展来确保空间足够。

代码语言:javascript
代码运行次数:0
复制
vec_validate (lm->entries, lm->size);

4、注册日志类别和日志的level等级

代码语言:javascript
代码运行次数:0
复制
while (r)
{
  r->class = vlib_log_register_class (r->class_name, r->subclass_name);
  if (r->default_level)
    vlib_log_get_subclass_data (r->class)->level = r->default_level;
  if (r->default_syslog_level)
    vlib_log_get_subclass_data (r->class)->syslog_level = r->default_syslog_level;
  r = r->next;
}

技术点补充:syslog的日志等级介绍,其level分为如下所示的等级,一般默认使用log_info等级。

代码语言:javascript
代码运行次数:0
复制
LOG_EMERG      system is unusable
LOG_ALERT      action must be taken immediately
LOG_CRIT       critical conditions
LOG_ERR        error conditions
LOG_WARNING    warning conditions
LOG_NOTICE     normal, but significant, condition
LOG_INFO       informational message
LOG_DEBUG      debug-level message

5、输出初始化标志

代码语言:javascript
代码运行次数:0
复制
r = lm->registrations;
while (r)
{
  vlib_log_debug (r->class, "initialized");
  r = r->next;
}

6、返回值:源代码中为return 0 建议修改为返回clib_error_t 里面的参数

04=log模块的使用方法介绍

1、首先在vpp启动配置文件中配置文件生成的路径,配置文件的详细参数可以参考如下文所述。

Ubuntu系统运行VPP24.02系列:startup.conf配置文件解读

代码语言:javascript
代码运行次数:0
复制
unix {
  nodaemon
  log /var/log/vpp/vpp.log
  full-coredump
  cli-listen /run/vpp/cli.sock
  gid vpp
  startup-config /etc/vpp/start.txt
}

在unix的配置参数下,配置的是log文件生成的路径,如果不存在OS下创建该路径即可,也可以按照需求设置指定的日志路径下。

2、配置log模块的默认level参数,也是在startup.conf文件中配置,这里的level 等级可以按照需求自行配置syslog的告警等级。

代码语言:javascript
代码运行次数:0
复制
logging {
  default-log-level info
  default-syslog-log-level info
}

3、查询配置信息,将lm里面存储的log 配置信息输出,该输出工作在管理线程main线程上。

代码语言:javascript
代码运行次数:0
复制
static clib_error_t *show_log_config (vlib_main_t * vm,
     unformat_input_t * input, vlib_cli_command_t * cmd)
{
  clib_error_t *error = 0;
  vlib_log_main_t *lm = &log_main;
  vlib_log_class_data_t *c;
  vlib_log_subclass_data_t *sc;

  vlib_cli_output (vm, "%-20s %u entries", "Buffer Size:", lm->size);
  vlib_cli_output (vm, "Defaults:\n");
  vlib_cli_output (vm, "%-20s %U", "  Log Level:",
       format_vlib_log_level, lm->default_log_level);
  vlib_cli_output (vm, "%-20s %U", "  Syslog Log Level:",
       format_vlib_log_level, lm->default_syslog_log_level);
  vlib_cli_output (vm, "%-20s %u msgs/sec", "  Rate Limit:",
       lm->default_rate_limit);
  vlib_cli_output (vm, "\n");
  vlib_cli_output (vm, "%-22s %-14s %-14s %s",
       "Class/Subclass", "Level", "Syslog Level", "Rate Limit");

  u8 *defstr = format (0, "default");
  vec_foreach (c, lm->classes)
  {
    vlib_cli_output (vm, "%v", c->name);
    vec_foreach (sc, c->subclasses)
    {
      vlib_cli_output (vm, "  %-20v %-14U %-14U %d",
           sc->name ? sc->name : defstr,
           format_vlib_log_level, sc->level,
           format_vlib_log_level, sc->syslog_level,
           sc->rate_limit);
    }
  }
  vec_free (defstr);

  return error;
}

VLIB_CLI_COMMAND (cli_show_log_config, static) = {
  .path = "show logging configuration",
  .short_help = "show logging configuration",
  .function = show_log_config,
};

4、查询生成的log日志方法,通过show logging命令输出

代码语言:javascript
代码运行次数:0
复制
static clib_error_t *show_log (vlib_main_t * vm,
    unformat_input_t * input, vlib_cli_command_t * cmd)
{
  clib_error_t *error = 0;
  vlib_log_main_t *lm = &log_main;
  vlib_log_entry_t *e;
  int i = last_log_entry ();
  int count = lm->count;
  f64 time_offset;

  time_offset = (f64) lm->time_zero_timeval.tv_sec
    + (((f64) lm->time_zero_timeval.tv_usec) * 1e-6) - lm->time_zero;

  while (count--)
    {
      e = vec_elt_at_index (lm->entries, i);
      vlib_cli_output (vm, "%U %-10U %-14U %v", format_time_float, NULL,
           e->timestamp + time_offset, format_vlib_log_level,
           e->level, format_vlib_log_class, e->class, e->string);
      i = (i + 1) % lm->size;
    }

  return error;
}

VLIB_CLI_COMMAND (cli_show_log, static) = {
  .path = "show logging",
  .short_help = "show logging",
  .function = show_log,
};

5、清除操作,通过clear logging命令进行清理

代码语言:javascript
代码运行次数:0
复制
static clib_error_t *clear_log (vlib_main_t * vm,
     unformat_input_t * input, vlib_cli_command_t * cmd)
{
  clib_error_t *error = 0;
  vlib_log_main_t *lm = &log_main;
  vlib_log_entry_t *e;
  int i = last_log_entry ();
  int count = lm->count;

  while (count--)
    {
      e = vec_elt_at_index (lm->entries, i);
      vec_free (e->string);
      i = (i + 1) % lm->size;
    }

  lm->count = 0;
  lm->next = 0;
  vlib_log_info (log_log.class, "log cleared");
  return error;
}

VLIB_CLI_COMMAND (cli_clear_log, static) = {
  .path = "clear logging",
  .short_help = "clear logging",
  .function = clear_log,
};

05=本次内容总结

本次内容主要是介绍了VPP中日志模块log的初始化操作、使用方法、查询方法、清理方法的介绍,其思维导图可以总结为:

总的来说,在vpp的vlib_log_init()这个函数中,日志系统被初始化,包括设置时间戳参数、创建/验证日志条目数组的大小、注册日志类别以及设置默认的日志级别和syslog级别等的功能。在使用章节中,我们介绍log功能在vpp上的使用方法,有需要的小伙伴们可以根据项目需要自己修改相关的逻辑和配置。好了,本次介绍就到此为止。小伙伴们,你们学会了吗?

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-10-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 通信行业搬砖工 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档