连接SONiC与P4交换芯片的SDE
SONiC作为近几年来在云网络领域最重要的开源网络操作系统,获得了业界足够多的关注,基于P4语言的数据平面可编程技术与架构,也是开放网络生态正在讨论的热点话题之一。随着开源、开放网络的进一步发展,SONiC与P4可编程的全方位融合逐渐出现在产业发展的思考范畴之内,并且逐渐开始了一些初步的尝试。
什么是P4 SDE
自2013年创建以来,网络编程语言P4凭借其优异的抽象能力以及灵活性,将网络的可编程性下压到了数据平面,让数据包的解析和转发流程也能通过编程控制,为实现SDN的终极目标提供了有力支撑。
随着芯片巨头Intel出手收购Barefoot,Tofino系列芯片以及P4生态将获得持续的支持与长久的发展。
Barefoot社区提供的SDE(Software Development Environment)可以用P4语言对数据面进行编程,然后编译好的数据面程序就可以运行在Barefoot Tofino芯片上或是SDE中的模拟芯片上。
Barefoot SDE包括了一系列用于开发P4的组件,包括:
- 核心组件
- Reference Code
- 测试框架
- 一系列代码教程示例
其中核心组件包括了:P4语言开发环境(编译器和模拟芯片环境),系统库以及相关驱动;Reference Code包括了:P4源码以及一组层次分明向上提供的API。
SONiC中的SDE
SONiC使用了Redis中机制来完成系统内各个模块间信息的传递。
在这里我们只需要知道在SONiC中syncd容器是与ASIC通信的唯一通道,控制面的业务进程想将数据下发ASIC时,最终处理流程都是将数据按照SAI标准接口格式写入Redis中的ASIC_DB,syncd容器中的同名主进程syncd订阅ASIC_DB中的相关表项并处理这些下发的数据,调用ASIC SDK对SAI API的实现,并通过ASIC driver下发到ASIC。
其中SDE就包括了ASIC SDK以及运行在Tofino ASIC上的tofino.bin(由P4源码编译生成的二进制程序)。
Barefoot SDE在SONiC中表现为deb包的形式,在编译生成SONiC镜像时,由Barefoot SDE编译生成的deb包将会安装在syncd容器中,安装目录如下:
/opt/bfn/install
|– bin
|– include
|– lib
`– share
其中ASIC SDK会以动态链接库的形式放在lib目录下面,被syncd主进程链接;由P4源码编译生成的tofino.bin放在share/switch目录下,运行时通过PCIE通道下发到ASIC中运行。
下面我们以SONiC下发二层MAC表为例来演示SONiC中的P4工作流程。
从SONiC上用命令行配置MAC表到P4转发芯片中的转发流表生效,这一整个流程可以分成下面三个部分进行说明。
- 第一步:SONiC通过命令行下发一条静态的MAC表,对应数据经过SONiC的业务进程处理,最终将会写入Redis中的ASIC_DB,即1号DB,DB中MAC表的组织形式如下:其中对接口参数的定义与SAI接口定义(如下所示)一致:包括一条fdb_entry以及对应count数量的key-value键值对,由上可知,我们下发了三对键值对,分别为BRIDGE_PORT_ID、TYPE和PACKET_ACTION
- 第二步:syncd容器中的同名主进程syncd订阅ASIC_DB中的相关表项并调用ASIC SDK对SAI API的实现(如下所示)来处理ASIC_DB中的数据。这一步的处理包括两个部分:参数转换和数据存储。首先做参数转换,将标准SAI接口定义的参数转换成Barefoot SDE中的接口层使用的参数格式,然后将其放入内存结构中进行存储,如下图:于是我们得到最终存储的数据结构如下:数据存储完成之后就会调用P4源码对应的语义接口层(与P4源码中table的语法结构一一对应),即SDE中的API层进入第三步。
- 第三步:在SDE中的API层对应P4源码的语义结构接口中,将上一步写入内存DB结构里的数据读取出来,将其转义为P4源码定义的table的语法结构,通过ASIC driver下发到ASIC。API层对应P4源码table的语义结构接口如下:
class dmac : {
…
public:
dmac(const switch_object_id_t parent, switch_status_t &status){
…
//读取上一步存储在内存中的数据
status |= switch_store::v_get(
parent, SWITCH_MAC_ENTRY_ATTR_VLAN_HANDLE, vlan_handle);
status |= find_auto_oid(vlan_handle, SWITCH_OBJECT_TYPE_BD, bd_handle);
status |= switch_store::v_get(
parent, SWITCH_MAC_ENTRY_ATTR_MAC_ADDRESS, match_mac);
status |= switch_store::v_get(
parent, SWITCH_MAC_ENTRY_ATTR_PORT_LAG_HANDLE, handle);
//转义为P4源码定义的table的语法结构
//生成流表的match_key
status |= match_key.set_exact(smi_id::F_DMAC_IG_MD_BD, compute_bd(bd_handle));
status |= match_key.set_exact(smi_id::F_DMAC_DST_ADDR, match_mac);
//生成流表的action
action_entry.init_action_data(smi_id::A_DMAC_HIT);
action_entry.set_arg(smi_id::P_DMAC_HIT_PORT_LAG_INDEX,
compute_port_lag_index(handle));
}
switch_status_t create_update() {
//将生成好的流表match_key和action通过ASIC driver下发到ASIC
}
};
在本文示例中用到的P4源码定义的table的语法结构如下:
小结
我们通过SONiC命令行下发一条静态的MAC表的数据最终在ASIC中表现出的流表形式为:
在ASIC进行流量转发时,如果数据包命中这条流表,即BD为03E7(对应VLAN ID为2),dst_mac为00:11:11:11:11:11,该数据包将从06口(对应port为60)出去。
通过本文的描述,希望帮助您对SDE作为SONiC与P4可编程芯片连接的中间组件,进行转发流表下发的数据流动过程有更深的了解。