FRR代码分析系列第二篇
FRRouting配置显示与保存
如果将FRR应用于项目中,那么它的配置文件是一个很好的配置处理方式。配置保存贯穿整个项目,与其他各模块耦合度较高,所以构建软件架构时,应该优先考虑好配置模块。
配置显示
- 命令show running-config显示当前设备配置信息。
vtysh定义该命令在vtysh.c中:show running-config [<zebra|ripd|ripngd|ospfd|ospf6d|ldpd|bgpd|isisd|pimd>]
-
命令直接调用接口vtysh_write_terminal():
接口vtysh_write_terminal()是命令write terminal
的处理函数,也就是说,show running-config
等价于write terminal
-
接口vtysh_write_terminal()调用vtysh_client_config()向各个daemon发送
write terminal
命令,并接收daemon返回的配置信息,解析,daemon配置信息接收完毕之后再调用接口生成vtysh进程自己的config配置信息,打印。这里需要注意:vtysh_client_config()调用
vtysh_client_run_all(head_client, line, 1, vtysh_config_parse_line, NULL);会对返回的数据进行解析和保存。
vtysh_client_config()处理完成之后调用vtysh_config_dump();遍历保存数据的数据结构,进行格式化输出,保证各进程配置的规范,不至于出现乱序。
至于这个结构的实现,没有仔细看,无非就是一些链表吧,目前不太关心。如果需要,可以看看vtysh_config_parse_line()这个接口。
(2020.12.08修改) -
daemon收到
write terminal
命令,这里需要注意的时,在daemon进程初始化调用frr_init()时,会注册一些默认的节点和命令,即command.c的cmd_init()接口,write terminal
命令也在这里注册,该命令区分terminal和file:- terminal:将调用vty_write_config()接口,首先输出frr信息,之后调用注册节点(接口:install_node()的第二个参数)的回调函数:node->func()。
- file:将调用file_write_config()接口写入自己进程的配置文件中。
配置保存
- 命令write file将配置写入文件。
vtysh命令定义在vtysh.c中:write [<memory|file>]
配置保存有两种模式:
- 配置文件统一保存在frr.conf文件中
- 各daemon进程独立保存到自己的配置文件中
在命令
write file
中使用:want_config_integrated()接口去判断使用哪种模式。在该接口中使用变量:vtysh_write_integrated来进行判断,该变量可以通过命令:service integrated-vtysh-config
和no service integrated-vtysh-config
进行配置。
模式一
查找VTYSH_WATCHFRR进程是否启动(实际是是否连接,这个和编译时是否使用watchfrr进程都有关系)
- 如果找到,则向watchfrr进程发送
do write integrated
命令,watchfrr进程拿到后,fork子进程,execl启动vtysh,使用参数 –w,根据参数新启动的vtysh将调用接口:vtysh_write_config_integrated()接口,进行配置保存完毕后,直接退出。 - 否则,直接调用vtysh_write_config_integrated()接口,进行配置保存。但是会有如下提示信息,警告配置可能会失败:
vtysh_write_config_integrated()接口首先对旧配置文件进行备份,之后向各个daemon进程发送do write terminal
命令,各daemon去执行。
模式二
vtysh直接给各daemon进程发送do write memory
命令,各daemon去执行。
需要注意的是,不管哪种模式,发送接收daemon进程消息时,都使用的sock通信,如果是写入到文件,那么vty->of中存放的是打开的文件描述符,vtysh拿到配置数据后,调用vty_out则,会向vty->of中写入数据。对于show,这个of是串口输出。