searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享

SONIC容器组件通信机制介绍

2023-09-20 07:36:34
79
0
  1. 内部通信模型

SONiC使用了发布订阅机制与redis的键空间通知机制(当客户端修改数据时,redis服务器会通知其他相关订阅者(client)的数据变化)。

SONiC 中使用到的数据库如下:

  • 0号数据库:APPL_DB,存储所有应用程序生成的状态——路由、下一跳、邻居等。这是应用程序与其他SONiC子系统交互的入口点;
  • 1号数据库:ASIC_DB,存放底层 ASIC 的状态信息和配置表项,格式对底层芯片友好,芯片重启可以从ASIC_DB快速恢复;
  • 2号数据库:CONTERS_DB,存放每个端口计数器和统计信息,这些信息可以被cli使用或者反馈给telemetry;
  • 3号数据库:LOGLEVEL_DB,存放日志配置等级信息;
  • 4号数据库:CONFIG_DB,存储SONiC应用程序创建的配置状态——端口配置、接口、VLAN等,有的APP/模块可能没有配置,可以没有对应表,有的配置直接调用linux的命令进行配置,有的配置还需要下发到芯片,这时需要往APPL_DB里写;
  • 5号数据库:FLEX_COUNTER_DB,存放灵活计数器配置;
  • 6号数据库:STATE_DB,存储系统中配置实体的“关键”操作状态。此状态用于解决不同SONiC子系统之间的依赖关系。例如,LAG端口channel(由teamd子模块定义)可能指系统中可能存在或不存在的物理端口。另一个例子是VLAN的定义(通过vlanmgrd组件),它可能引用系统中存在未知的端口成员。本质上,该数据库存储了解决跨模块依赖关系所需的所有状态。

在SONiC中,CONFIG_DB和STATE_DB之间的数据监听通过 key-space 机制实现。key-space 机制的消费者通过 sonic-swss-common/common 中的 SubscriberStateTable 类实现。

对CONFIG_DB的修改一般用于对系统进行配置操作,如使用命令行来配置系统功能,SONiC在sonic-py-swsssdk组件中封装了对CONFIG_DB的操作,根据传递data是否为空执行hmset或delete操作。

这里以监听CONFIG_DB配置VLAN为例说明。

VlanMgr 组件在初始化时监听CFG_VLAN_TABLE_NAME和CFG_VLAN_MEMBER_TABLE_NAME两个 key-space 事件,当通过config命令(sonic cli)添加 vlan 100的操作时,redis服务器的 CONFIG_DB 会为“VLAN|Vlan100”的KEY产生 key-space事件消息, VlanMgr 组件收到后,调用 VlanMgr::doTask(Consumer &consumer) 处理。

收到消息后,这里的Consumer即是通过orch类封装过的 SubscriberStateTable 。

通过消息队列来传递信息,内容可以灵活定义。在 SONiC 中,该通信模型主要用于 SWSS容器中的 orchagent 与 syncd 容器中的之间的事件通知。

以FDB事件为例,SYNCD收到来自底层驱动的FDB事件,调用对数据库的hset或del操作更新ASIC_DB中的FDB表项,同时作为Notification生产者发送名为“fdb_event”的通知消息。 Notification的消费者流程在fdborch中实现,通知消息触发FdbOrch::doTask(NotificationConsumer&consumer)来进行后续处理,更新orchagent中的FDB信息。

sonic-swss-common 中 ProducerStateTable 与 ConsumerStateTable 实现

该机制通过一个set集合传递key,通过publish命令通知有新的key产生。消费者通过key组合成一个hash表的key,用于获取真实的消息,set不保证顺序,在publish通知KEY修改事件前允许对key-value进行多次操作,操作过程不保证执行顺序。这样做的好处是不必在每次设置key-value时都触发事件通知,可以提升处理效率,但对orchagent处理流程有一定要求。

Orchagent调度处理采用epoll事件通知模型,事件触发即会产生调度;在调度处理中,可能出现因资源依赖等因素导致任务处理无法完成,此时可以选择将任务保留在m_toSync中等待下一次调度处理。在大规模控制表项和较复杂逻辑关系的场景下,这种调度机制可能出现因资源限制、依赖条件不满足等因素导致的频繁或无效调度,Asterfusion通过优化处理顺序、改进批量操作以及在STATE_DB中设置状态标志等改进方式,提高了组件运行效率并增强了可靠性。

使用redis publish 通知KEY修改事件,利用Key-Value-Operate机制来传递信息。该通信模型通过有序链表(list)来传递key-value-operate三元消息,一次操作在LIST中压入三个值(通知订阅者进行消息处理,循环处理消息,一次必须从链表中拿出三个key),分别为key,value,operate。其中的 value 是把一个 hash表进行json编码后形成了一个单一的字符串,所以订阅者得到消息后需要进行解码还原,最后一个是操作类型。

SYNCD 通过这种方式List队列获得 key-value-operation, 然后解码,写入到ASIC_STATE,同时调用底层SAI接口。

在SONiC中,该模型用于围绕ASIC_DBFLEX_COUNTER_DB的消息传递。与模型3相比,该模型保证了操作的严格执行顺序,在 syncd 执行 SAI API 调用时保证了对底层ASIC的操作时序。

  1. 与内核的通信方式

网络接口事件和路由等需要SONiC应用程序与Linux内核通信,主要通过两种方式:

  • 调用Linux工具命令, 如调用ip命令配置网络接口IP地址和设置VRF,又如调用bridge命令配置VLAN。用封装的swss::exec方法最终通过popen执行拼装好的command指令。
  • 对netlink消息操作则是通过以libnl库为基础封装的NetLink类来完成,同时SWSS也定义了一套NetDispatcher机制来实现netlink消息监听和分发处理。
  1. 端口状态交互
  • 建立连接,声明角色:初始化期间,portsyncd与redis引擎中的主数据库建立通信通道。Portsyncd声明它打算充当APPL_DB和STATE_DB的发布者,以及CONFIG_DB的订户。同样,portsyncd还订阅负责承载端口/链路状态信息的系统netlink通道。
  • 解析配置:Portsyncd首先解析与系统中使用的硬件配置文件/sku关联的端口配置文件(ini)(有关更多详细信息,请参阅配置部分)。与端口相关的信息,如通道、接口名称、接口别名、速度等,通过该通道传输到APPL_DB。
  • 转换到ASIC_DBOrchagent听到所有这些新状态,但将推迟对其进行操作,直到portsyncd通知它已完全完成对ini信息的解析。一旦发生这种情况,orchagent将继续初始化硬件/内核中相应的端口接口。Orchagent调用sairedis API,通过常用的ASIC_DB接口将此请求传递给syncd
  • 创建端口:Syncd通过ASIC_DB接收此新请求,并准备调用满足Orchagent请求所需的SAI API。Syncd使用SAI API+ASIC SDK创建与正在初始化的物理端口相关联的内核主机接口。
  • 更新状态:上一步生成netlink消息,被portsyncd接收,并与先前从ini(步骤1)解析的所有端口进行对比,若都完成,则声明“初始化”过程已完成。portsyncd 将写入一个条目到 STATE_DB 中,表示端口初始化完成。
  • 依赖使用:从现在起,以前订阅STATE_DB content的应用程序将收到一个通知,允许这些应用程序开始使用它们所依赖的端口。换句话说,如果在STATE_DB中找不到特定端口的有效条目,则任何应用程序都无法使用它。
  1. 端口状态变化
  • 当端口状态发生变化时,驱动通过syncd注册的函数通知syncd
  • syncd调用通知函数发送事件给 ASIC_DB
  • Orchagent 通过notification 线程监听ASIC_DB事件,执行端口状态变化函数:1)产生APPL_DB更新消息,通知上层应用;2)调用sairedis API以提醒syncd需要更新与所选端口的主机接口关联的内核状态,orchagent再次通过常用的ASIC_DB接口将此请求传递给syncd
  • Syncd使用SAI API+ASIC SDK将受影响主机接口状态(关闭)更新;
  • portsyncd接收到与上一步相关的netlink消息,由于所有SONiC组件现在都完全知道端口关闭事件,因此该消息将被悄悄丢弃。
  1. 路由状态交互

在本节中,我们将迭代SONiC中发生的一系列步骤,以处理从eBGP对等方接收到的新路由。我们将假设此会话已经建立,并且我们正在学习一种新的路由,该路由使用直接连接的对等方作为其下一跳。

 

 

(0)在BGP容器初始化期间,zebra通过常规TCP套接字连接到fpmsyncd。在稳定/非瞬态条件下,zebra、linux内核、APPL_DB和ASIC_DB中保存的路由表应完全一致/等效。 (1) 一个新的TCP包到达内核空间中bgp的套接字。内核的网络堆栈最终将相关的有效负载交付给bgpd进程。 (2) Bgpd解析新数据包,处理bgp更新,并通知zebra此新前缀及其关联协议下一跳的存在。 (3) zebra确定此前缀的可行性/可达性(例如,现有转发nh)后,zebra生成路由netlink消息,将此新状态注入内核。 (4) Zebra利用FPM接口将此netlink路由消息传递给fpmsyncd。 (5) Fpmsyncd处理netlink消息并将此状态推送到APPL_DB。 (6) 作为APPL_DB消费者,它将接收先前推送到APPL_DB的信息内容。 (7) 在处理接收到的信息后,orchagentd将调用sairedis API将路由信息注入ASIC_DB。 (8) 当与ASIC_DB消费者同步时,它将接收orchagentd生成的新状态。 (9) Syncd将处理该信息并调用SAI API将该状态注入相应的asic驱动程序。 (10) 新的路线最终被推到了硬件上。

  1. LLDP状态交互

 

  • (0)lldpmgrd进程启动时订阅STATE_DB数据中物理口的状态,周期性获取接口最新状态。基于这些信息,lldpd(及其网络对等方)将随时了解系统端口状态的更改以及影响其操作的任何配置更改
  • (1)内核收到lldp报文后会分发给lldp进程去处理
  • (2)lldp解析LLDP报文获取最新状态,lldp_syncd周期性执行lldpctl cli获取该最新状态
  • (3)lldp_syncd把最新的状态写入APPL_DB数据库中的LLDP_ENTRY_TABLE表
  • (4)其他监听这张表的app就能获取lldp的最新状态了
  1. syncd 组件

syncd 通过注册回调函数与driver通信,syncd和sai共享命名空间。syncd 启动线程监听共享队列,处理driver的通知。

syncd 进程是介于orchagent与driver之间的进程。syncd从asic-db中读取的数据经转换后调用驱动提供的sai接口下发到硬件,同时需要将驱动的应答进行一定的处理,还需要处理驱动的事件通知(比如端口up/down,mac老化等信息)。

  1. orchagent 写操作

createremoveset写操作:异步写。orchagent会在 sairedis 层构建一个虚拟的sai层:sairedis。orchagent执行sai接口只是对asic-db进行操作,生成或者删除虚拟对象(vid)。默认所有操作都是成功的,直接返回,不等待syncd的应答。syncd从asic-db中读出请。如果4步骤返回成功,则整个请求运行结束,否则,syncd将会发送shutdown通知给orchagent。orchagent会退出

  1. orchagent 读操作

get 读操作:同步读。orchagent执行1后会使用select阻塞等待syncd的应答,如果syncd在60分钟内没有应答,那么orchagent会产生segment退出。get操作执行顺序为1->2->3->4->5->6。

      整体而言:SONIC分为用户态、内核态、硬件三部分,用户态采用docker的方式分为各个组件,组件之间的通信中间件为redis数据库,这样避免了各个容器之间相互交互的繁琐流程。另外用户态和内核态之间采用netlink消息进行通信,端口状态的变化,路由状态的变化等等都会通知到内核,这样保证端口状态、路由状态在用户面及控制面保持一致。

0条评论
0 / 1000
石****露
3文章数
0粉丝数
石****露
3 文章 | 0 粉丝