P4->NetFPGA 工作流程概述


P4->NetFPGA 工作流程概述

前言

Workflow Overview的翻译

结构

本页面介绍了P4-> NetFPGA工作流程的以下几个方面:

SimpleSumeSwitch Architecture

SimpleSumeSwitch是目前为NetFPGA SUME定义的P4架构。 体系结构描述可以在/opt/Xilinx/SDNet/<version_number>/data/p4include/sume_switch.p4中找到,或者您已经安装了Xilinx SDNet的地方。 该体系结构由单个解析器,单个匹配操作管道和单个解析器组成。 如下所示:

SimpleSumeSwitch_arch

  • sume_metadata: 对应于SUME reference_switch设计中的tuser总线,定义如下:
struct sume_metadata_t {
    bit<16> dma_q_size; // measured in 32-byte words
    bit<16> nf3_q_size; // measured in 32-byte words
    bit<16> nf2_q_size; // measured in 32-byte words
    bit<16> nf1_q_size; // measured in 32-byte words
    bit<16> nf0_q_size; // measured in 32-byte words
    bit<8> send_dig_to_cpu; // send digest_data to CPU
    bit<8> drop;
    port_t dst_port; // one-hot encoded: {DMA, NF3, DMA, NF2, DMA, NF1, DMA, NF0}
    port_t src_port; // one-hot encoded: {DMA, NF3, DMA, NF2, DMA, NF1, DMA, NF0}
    bit<16> pkt_len; // (bytes) unsigned int
}

其中:

  • pkt_len - 数据包的大小(不包括FCS的以太网前缀),单位为字节。
  • src_port - 数据包到达的端口。 例如,如果数据包到达端口nf1,则该字段将被设置为0b00000100。
  • dst_port - 应由用户的P4程序设置,以指示哪个或哪些端口(如果有的话)数据包应该被发送出去。 例如,要从端口nf0和nf2发送数据包,该字段应设置为0b00010001。
  • drop - 如果该字段的最低有效位被设置为1,则该分组将被丢弃。
  • send_dig_to_cpu - 如果该字段的最低有效位设置为1,则摘要数据将通过DMA发送到CPU。
  • _q_size - 每个输出队列的大小,以32字节的单词来衡量(向上舍入)。 这是P4程序开始处理数据包时输出队列的大小。
  • digest_data: 这个总线的格式是由P4程序员定义的。 唯一的限制是它必须被定义为80位宽。 例如,要实现一个L2学习开关,可以将digest_data总线配置如下:
struct digest_data_t {
    bit<8> src_port;
    bit<48> eth_src_addr;
    bit<24> unused;
}
  • user_metadata: 这个总线的格式也由P4程序员定义。 它可以用来将解析器的任何附加信息传递给M / A流水线,并从M / A流水线传递给解析器。
  • in/out control: 这些信号用于添加/删除表和读/写控制寄存器的条目。

Xilinx P4-SDNet工具链创建一个HDL模块,然后将其封装在一个小封装中,并插入到NetFPGA SUME参考交换机架构中,如下图所示。

switch_diagram

Xilinx P4-SDNet

赛灵思P4-SDNet编译器是P4-> NetFPGA工作流程的核心。 它将面向SimpleSumeSwitch体系结构的P4程序编译成一个具有标准AXI-Stream数据包接口和AXI-Lite控制接口的HDL模块。 SDNet输出设计为100G速率,因此能够轻松处理SUME参考开关设计中的总计40G速率。 有关赛灵思SDNet工具的更多信息,请参见此处

Workflow Steps

1)修改$ SUME_FOLDER / tools / settings.sh以确保将P4_PROJECT_NAME环境变量设置为您想要处理的项目的名称。 运行$ source settings.sh

2)编写P4程序和commands.txt - commands.txt文件允许你添加条目到你在P4程序中定义的表中。

3)写 gen_testdata.py

4)运行P4-SDNet编译器生成最终的HDL和初始仿真框架:

$ cd $P4_PROJECT_DIR && make

5)运行SDNet模拟:

$ cd $P4_PROJECT_DIR/nf_sume_sdnet_ip/SimpleSumeSwitch

$ ./vivado_sim.bash

注意:如果您想启动Vivado GUI并查看HDL波形(这是一个非常有用的调试工具),您也可以运行vivado_sim_waveform.bash。

如果这个模拟通过很好! 如果没有,你将需要修改你的P4程序或你的gen_testdata.py脚本。

6)生成可在NetFPGA SUME模拟中使用的脚本来配置表条目。

$ cd $P4_PROJECT_DIR

$ make config_writes

7)在包装模块中包装SDNet输出并作为SUME库核心进行安装:

$ cd $P4_PROJECT_DIR

$ make uninstall_sdnet && make install_sdnet

8)设置SUME模拟。 $ NF_DESIGN_DIR / test / sim_switch_default目录包含负责运行SUME模拟的run.py脚本,请检查一下。 您将看到它读取由步骤3中的gen_testdata.py脚本生成的测试数据包,并将数据包应用于SUME接口。 我们所需要做的就是将步骤6中生成的config_writes.py脚本复制到这个目录中。

$ cd $NF_DESIGN_DIR/test/sim_switch_default && make

9)运行SUME模拟:

$ cd $SUME_FOLDER

$ ./tools/scripts/nf_test.py sim --major switch --minor default

注意:您也可以使用--gui选项运行上述命令来启动Vivado GUI并查看HDL波形。 再次,一个非常有用的调试工具。

10)编译比特流:

$ cd $NF_DESIGN_DIR && make

11)检查以确保设计符合时间要求。 看到这个this FAQ,看看如何做到这一点。

12)编程FPGA。 将比特流文件config_writes.sh脚本复制到$ NF_DESIGN_DIR / bitfiles目录中。

$ cd $NF_DESIGN_DIR/bitfiles

$ cp ../hw/project/simple_sume_switch.runs/impl_1/top.bit ./ && mv top.bit ${P4_PROJECT_NAME}.bit

$ cp $P4_PROJECT_DIR/testdata/config_writes.sh ./

$ sudo bash

# bash program_switch.sh

注意:确保配置写入全部成功。 如果这是自上次断电以来首次对FPGA进行编程,则可能需要重新启动。

13)在真实硬件上测试设计! 转到$ P4_PROJECT_DIR / sw / CLI目录并运行P4_SWITCH_CLI.py脚本。 这启动了一个交互式命令行界面,您可以使用该界面与您的交换机进行交互(例如,读取/写入寄存器,添加/删除表条目等)。 输入help以查看可用命令的列表。

Writing P4 Programs

该库目前支持Xilinx P4 _ 16前端编译器请参阅此处以获取有关P4_16语言当前标准的链接。 有关开源P4语言联盟的更多信息,请访问P4.org

赛灵思P4-SDNet指定了一些可用于P4程序的附加注释:

  • @Xilinx_MaxPacketRegion() - for parser/deparser; 声明解析器/解析器需要支持的最大数据包大小(以位为单位)。
  • @Xilinx_MaxLatency() - 对于extern; 外部函数需要完成的最大时钟周期数。
  • @Xilinx_ControlWidth() - 为extern; 地址空间的大小分配给一个extern函数。
  • @Xilinx_ExternallyConnected() - 表格; 将表的请求和响应元组拉到设计的顶层

有关使用和编写extern函数的更多信息,请参见“P4-> NetFPGA Extern库”一节。

Table Types:在P4程序中可以使用3种表格类型:

  • exact - 完全匹配指定的标题或元数据字段,然后执行所需的操作。 可以指定多个键匹配。
  • ternary - 完全匹配指定键的一些所需子集。
  • lpm - 匹配与指定key共享最长前缀匹配的表中的条目。 只能指定一个键。

Commands.txt: 这是$ P4_PROJECT_DIR / src /目录中的文件,其中包含用于填充表条目的命令。 以下是用于填充每种类型的表中的表项的命令的格式:

Table Type Command
exact table_cam_add_entry <table_name> <action_name> <keys (space separated)> => <action_data (space separated)>
ternary table_tcam_add_entry <table_name> <entry_address> <action_name> <key1/mask1 ... keyN/maskN> => <action_data (space separated)>
lpm table_lpm_add_entry <table_name> <action_name> <key>/<prefix_length> => <action_data (space separated)>

上面列出的命令是commands.txt文件中唯一支持的命令。

注意:使用lpm表时,SDNet编译器将生成一个bash脚本(即create_ip_forward.bash),在启动SDNet仿真之前必须运行它。

Testing P4 Programs

通过在$ P4_PROJECT_DIR / testdata目录中写入一个gen_testdata.py脚本来测试你的P4程序。 gen_testdata.py脚本大量使用python scapy模块。 Scapy是一个非常方便和易于使用的数据包操作库。 它允许你定义任意数据包,甚至定义你自己的头类型(例如switch_calc_headers.py)。 gen_testdata.py脚本必须生成:

  • src.pcap - 数据包通过P4交换机
  • dst.pcap - 数据包在P4交换机的输出处预期
  • Tuples_in.txt - 与src.pcap中的每个数据包关联的metadata
  • Tuples_expect.txt - 与dst.pcap中的每个数据包关联的metadata

上面列出的文件用于初始SDNet模拟。 文件$ P4_PROJECT_DIR / testdata / sss_sdnet_tuples.py可以用于为针对SimpleSumeSwitch体系结构的项目创建Tuples_in.txtTuples_expect.txt文件。 对于每个数据包,更新sume_tuple_indig_tuple_insume_tuple_expectdig_tuple_expect,随后调用write_tuples()Tuples _ *.txt文件添加一行。

建议gen_testdata.py脚本也会生成:

  • nf0_applied.pcap ... nf3_applied.pcap
  • nf0_expected.pcap ... nf3_expected.pcap

这些是可以在SUME模拟中使用的文件。 该脚本还应该为每个应用数据包设置时间字段,以便可以按正确的顺序应用SUME模拟。

$ {NF_DESIGN_DIR} /test/sim_switch_default/run.py脚本运行一个SUME模拟。 它可以使用由gen_tesdata.py脚本生成的数据包追踪,或者可以创建新数据包并使用它们。 有关编写run.py脚本的更多详细信息,请参阅此处

Debugging P4 Programs

如果你做了足够的P4开发,你可能需要在某个时候进行调试。 本节旨在为您提供一些调试技巧。

SDNet产生你的P4程序的两个实现:一个HDL实现和一个C ++模型。 为了将C ++模型的输出与HDL实现的输出进行比较,请执行以下操作:

$ cd $P4_PROJECT_DIR && make_cpp_test

$ cd nf_sume_sdnet_ip/SimpleSumeSwitch/

$ ./vivado_sim.bash

这对于测试SDNet编译器的功能非常有用,因为C ++模型的输出应该始终与HDL实现的输出相匹配。 所以如果运行上面的模拟失败这可能表明SDNet编译器的问题,但它也可能表明另一个问题。 例如,也许你正在试图添加更多的条目比你的表可以容纳? 要解决这个问题,你需要在你的P4程序中增加你的表的大小。 或者,也许你正在使用的任何外部函数的C ++模型是不正确的实现?

SDNet C ++模型有用的另一个原因是因为它产生了经过处理的数据包的PCAP文件Packet_expect.pcap。 要生成C ++模型输出PCAP文件,请执行以下操作:

$ cd $P4_PROJECT_DIR && make

$ cd nf_sume_sdnet_ip/SimpleSumeSwitch/SimpleSumeSwitch.TB/

$ ./compile

$ ./SimpleSumeSwitch

生成的PCAP文件被称为Packet_expect.pcap,可以与gen_testdata.py脚本生成的dst.pcap文件进行比较。 运行C ++模型产生非常详细的输出,描述如何处理数据包。 例如,您可以看到整个设计中元数据字段的修改方式,以及您定义的表中是否存在命中或未命中。

一旦确定Packet_expect.pcap文件与dst.pcap文件相匹配,您可以运行SDNet模拟,将HDL实现输出与dst.pcap中的数据包以及Tuple_expect.txt中的预期元数据进行比较:

$ cd $P4_PROJECT_DIR && make

$ cd nf_sume_sdnet_ip/SimpleSumeSwitch/

$ ./vivado_sim.bash

如果运行此模拟会导致元数据错误(即期望元组与实际元组之间不匹配),则可以轻松地检查哪些字段不匹配:

$ ./vivado_sim.bash
...
expected < tuple_out_sume_metadata > = < 00000000000000000000000100040041 >
actual   < tuple_out_sume_metadata > = < 00000000000000000000000100040040 >
...

$ $P4_PROJECT_DIR/testdata/sss_sdnet_tuples.py --parse 00000000000000000000000100040041 sume
Parsed Tuple:
-----------------------
dma_q_size  =  0
nf3_q_size  =  0
nf2_q_size  =  0
nf1_q_size  =  0
nf0_q_size  =  0
send_dig_to_cpu  =  0
drop  =  1
dst_port  = 00000000
src_port  = 00000100
pkt_len  =  65

如果SDNet模拟通过但SUME模拟失败,该怎么办?

如果你遇到这个问题,我会建议检查几件事情:

1)确保你已经运行:

  • $ cd $P4_PROJECT_DIR && make config_writes
  • $ cd $NF_DESIGN_DIR/test/sim_major_minor && make
  • $ cd $P4_PROJECT_DIR && make install_sdnet

2)请注意,数据包的接收顺序很重要。 如果您的nf _ * _ expected.pcap文件中的数据包包含的数据包顺序与实际收到的数据包不同,则会导致模拟失败。

3)运行SUME模拟更长时间 - 如果您看到所有预期的数据包尚未到达,则可能是问题所在。

4)确保所有配置写入在应用测试数据包之前已经完成。

5)要检查SUME模拟的实际和预期数据包,请检查$ NF_DESIGN_DIR / test / nf _ * _ expected.axi和​$ NF_DESIGN_DIR / test / nf _ * _ logged.axi

6)通过在$ NF_DESIGN_DIR / hw / tcl / simple_sume_switch_sim.tcland的底部添加--gui选项来运行SUME仿真,将信号添加到仿真波形。

P4->NetFPGA Extern Library

外部功能旨在让P4程序员在其P4程序中使用自定义逻辑。 对于NetFPGA平台,这些外部函数必须用HDL(或者可能是一些生成HDL的高级语言)来实现。 为了从P4开发者中抽象出HDL细节,P4-> NetFPGA工作流提供了一个可用于P4程序的外部函数库。 有状态的原子实验是受Domino原子的启发。 下表介绍了当前支持的外部函数:

Stateful Atomic Extern Functions

Name Description
RW 读写状态
RAW Read, add to, or overwrite state
PRAW Either perform RAW or don't perform RAW based on predicate
ifElseRAW Two RAWs, one each for when a predicate is true or false
Sub IfElseRAW with stateful subtraction capability

IMPORTANT:每个有状态原子(即寄存器)只能在P4代码中被访问一次。 多次调用extern函数会生成原子的多个实例,您可能会得到意想不到的结果。

注:Vivado将寄存器的大小限制为1百万个条目。 所以这些有状态原子的索引宽度必须小于20位。

Stateless Extern Functions

Name Description
IP Checksum Given an IP header, compute the IP checksum
LRC longitudinal redundancy check, simple hash function
timestamp generate timestamp (measure in clock cycles, granularity of 5ns)

Adding new extern functions:

为工作流添加新的外部函数是非常容易的。 实现extern函数,只需将条目添加到$ {SUME_SDNET} /bin/extern_data.py文件中即可。 每个条目是一个有两个键的Python字典:

  • “template_file” - 指定相对于$ {SUME_SDNET} / templates目录的extern函数模板的路径。
  • “replacements” - 一个python字典,指定要在模板文件中替换的模式,以及替换模式的模式。 支持的命令是:
Command Description
"module_name" The name of the module. This is determined by the P4-SDNet compiler and so must be replaced in the template file.
"extern_name" The full name of the extern function. This is also determined by the P4-SDNet compiler and so must be replaced in the template file.
"prefix_name" The name given to the extern function by the P4 programmer. For example, for an extern function called pktCnt_reg_raw the "prefix_name" would be called pktCnt.
"addr_width" The size (in bits) of the address space allocated to the extern function. Specified by the P4 programmer using the @Xilinx_ControlWidthannotation.
"input_width(field)" The width (in bits) of a particular input field.
"output_width(field)" The width (in bits) of a particular output field.

如果一个P4程序实例化一个控制宽度大于0的外部函数,P4-> NetFPGA工具将自动生成一个可以在外部模块中使用的<prefix_name> _cpu_regs模块。 它的目的是使用AXI-Lite接口轻松暴露控制寄存器。

强烈建议实现新的外部函数的用户将其贡献给P4-> NetFPGA项目,以便其他人也可以使用它们。

API / CLI

python和C API都是由工作流生成的,而且可以用来操作P4程序中实例化的寄存器和表。 C API由P4-SDNet直接生成,文件被复制到$ {P4_PROJECT_DIR} / sw / API目录中。 python API只是这些C API函数的一个包装,使开发人员可以很容易地编写python程序来控制它们的开关设计。 python API文件名为p4_tables_api.pyp4_regs_api.py,位于​$ {P4_PROJECT_DIR} / sw / CLI目录中。

这些工具生成一个交互式命令行环境,可用于查询有关生成的P4设计的编译时间信息,以及在物理交换机加载到FPGA时与交换机进行交互。 运行:$ ./P4_SWITCH_CLI.py进入环境,输入help查看命令列表及其文档。

Limitations

  • lpm和三元表只有轻微的测试。 为这些表类型开发项目和测试用例需要社区支持。

  • 从控制面访问的寄存器必须限制在32位宽。 因为这是SUME控制数据总线的宽度。

  • 所有的P4设计必须至少有一个表或外部功能与控制界面。 这是因为HDL包装模块目前假定SimpleSumeSwitch模块将具有AXI-Lite控制接口。

  • 有关更多问题,请参阅github issue页面。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM