p4factory下 targets/basic_rout
p4factory/targets/basic_routing/p4src代码解读
headers.p4
header_type ethernet_t {
fields {
dstAddr : 48;
srcAddr : 48;
etherType : 16;
}
}
header_type ipv4_t {
fields {
version : 4;
ihl : 4;
diffserv : 8;
totalLen : 16;
identification : 16;
flags : 3;
fragOffset : 13;
ttl : 8;
protocol : 8;
hdrChecksum : 16;
srcAddr : 32;
dstAddr: 32;
}
}
定义了一个以太网包头,以及一个IPV4包头
parser.p4
parser start {
return parse_ethernet;
}
#define ETHERTYPE_IPV4 0x0800
header ethernet_t ethernet;
parser parse_ethernet {
extract(ethernet);
return select(latest.etherType) {
ETHERTYPE_IPV4 : parse_ipv4;
default: ingress;
}
}
header ipv4_t ipv4;
field_list ipv4_checksum_list { //提取包的field_list
ipv4.version;
ipv4.ihl;
ipv4.diffserv;
ipv4.totalLen;
ipv4.identification;
ipv4.flags;
ipv4.fragOffset;
ipv4.ttl;
ipv4.protocol;
ipv4.srcAddr;
ipv4.dstAddr;
}
field_list_calculation ipv4_checksum {
input {
ipv4_checksum_list;
}
algorithm : csum16;
output_width : 16;
} //通过实例计算出校验和
calculated_field ipv4.hdrChecksum {
verify ipv4_checksum;
update ipv4_checksum;
} //与该包的校验和想比较,看是否正确
parser parse_ipv4 {
extract(ipv4);
return ingress;
}
解释可以看这张图

报文进来后,直接到了parse_ethernet解析器,然后提取ethernet实例的etherType判断是否位0x800如果是在进入到parse_ipv4解析器否则,到达状态_condition_()
中间有个field_list_calculation ipv4_checksum 可以理解成是通过实例化的其他的field字段计算出checksum
calculated_field ipv4.hdrChecksum 计算出来的ipv4_checksum在于刚刚包的hdrChecksum作对比,判断是否一样,然后在更新他
basic_routing.p4
#include "headers.p4"
#include "parser.p4"
#define PORT_VLAN_TABLE_SIZE 32768
#define BD_TABLE_SIZE 65536
#define IPV4_LPM_TABLE_SIZE 16384
#define IPV4_HOST_TABLE_SIZE 131072
#define NEXTHOP_TABLE_SIZE 32768
#define REWRITE_MAC_TABLE_SIZE 32768
#define VRF_BIT_WIDTH 12
#define BD_BIT_WIDTH 16
#define IFINDEX_BIT_WIDTH 10
/* METADATA */
header_type ingress_metadata_t { //用户自定义元数据
fields {
vrf : VRF_BIT_WIDTH; /* VRF */
bd : BD_BIT_WIDTH; /* ingress BD */
nexthop_index : 16; /* final next hop index */
}
}
metadata ingress_metadata_t ingress_metadata;
action on_miss() {
}
action set_bd(bd) {
modify_field(ingress_metadata.bd, bd); //设置元数据的bd值
}
table port_mapping {
reads {
standard_metadata.ingress_port : exact;
}
actions {
set_bd;
}
size : PORT_VLAN_TABLE_SIZE;
}
action set_vrf(vrf) {
modify_field(ingress_metadata.vrf, vrf);
}
table bd {
reads {
ingress_metadata.bd : exact;
}
actions {
set_vrf;
}
size : BD_TABLE_SIZE;
}
action fib_hit_nexthop(nexthop_index) {
modify_field(ingress_metadata.nexthop_index, nexthop_index);
subtract_from_field(ipv4.ttl, 1); //让ipv4包ttl-1
}
table ipv4_fib {
reads {
ingress_metadata.vrf : exact;
ipv4.dstAddr : exact;
}
actions {
on_miss;
fib_hit_nexthop;
}
size : IPV4_HOST_TABLE_SIZE;
}
table ipv4_fib_lpm {
reads {
ingress_metadata.vrf : exact;
ipv4.dstAddr : lpm;
}
actions {
on_miss;
fib_hit_nexthop;
}
size : IPV4_LPM_TABLE_SIZE;
}
action set_egress_details(egress_spec) {
modify_field(standard_metadata.egress_spec, egress_spec);
}
table nexthop {
reads {
ingress_metadata.nexthop_index : exact;
}
actions {
on_miss;
set_egress_details;
}
size : NEXTHOP_TABLE_SIZE;
}
control ingress { //ingress流控制程序,规定了匹配过程
if (valid(ipv4)) {
/* derive ingress_metadata.bd */
apply(port_mapping);
/* derive ingress_metadata.vrf */
apply(bd);
/* fib lookup, set ingress_metadata.nexthop_index */
apply(ipv4_fib) {
on_miss {
apply(ipv4_fib_lpm);
}
}
/* derive standard_metadata.egress_spec from ingress_metadata.nexthop_index */
apply(nexthop);
}
}
action rewrite_src_dst_mac(smac, dmac) {
modify_field(ethernet.srcAddr, smac);
modify_field(ethernet.dstAddr, dmac);
}
table rewrite_mac {
reads {
ingress_metadata.nexthop_index : exact;
}
actions {
on_miss;
rewrite_src_dst_mac;
}
size : REWRITE_MAC_TABLE_SIZE;
}
control egress { //egress的流控制程序
/* set smac and dmac from ingress_metadata.nexthop_index */
apply(rewrite_mac);
}
这个也可以从图可得他想要实现的结果

上图两个团员可以看作是查表,线上文字代表执行相应的动作。下面解释一下这张图
首先一个有效ipv4实例进来后先进行端口的匹配,设置bd,然后接着匹配bd表,设置vrf,然后在匹配ipv4_fib这张表匹配到就到下一跳去处理,接下应该都比较好理解。
处理完ingress后在进入buffer区,然后在进行egress的处理,这里egress只有匹配一张表rewite_mac。
输出结果展示
Packet in on port 2 length 100; first bytes:
00010203 04050006 0708090a 08004500
new packet, len : 100, ingress : 2
rmt proc returns 0
ingress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
parsing parse_ipv4
payload length: 66
all checksums are correct //检验和正确,开始进入相应匹配
Applying table port_mapping
Lookup key for port_mapping: //端口匹配
standard_metadata_ingress_port: 0x00000002,
table hit
**********
entry at index 1:
key:
standard_metadata_ingress_port: 0x00000002 (0 0 0 2),//key值
action:
set_bd //动作
action data:
bd: 0x0000000a (0 0 0 10), //等下要赋值的数据
**********
action set_bd
action data:
bd: 0x0000000a (0 0 0 10), //执行完成
executing next table for action
Applying table bd
Lookup key for bd:
ingress_metadata_bd: 0x0000000a, //bd匹配
table hit
**********
entry at index 0:
key:
ingress_metadata_bd: 0x0000000a (0 0 0 10), //找到了表项
action:
set_vrf
action data:
vrf: 0x0000001e (0 0 0 30),
**********
action set_vrf
action data:
vrf: 0x0000001e (0 0 0 30),
executing next table for action
Applying table ipv4_fib //匹配路由表
Lookup key for ipv4_fib:
ingress_metadata_vrf: 0x0000001e, ipv4_dstAddr: 0x0a000002,
table miss, applying default action
action on_miss //没有匹配到,执行on_miss操作
executing next table for action
Applying table ipv4_fib_lpm //执行ipv4路由表的另一种lpm匹配、
//与上面ipv4_fib区别的的是 ipv4_fib是
//精确匹配,而ipv4_fib_lpm执行的是三 //重匹配
//“动作-匹配表的每个表项都有一个掩码,将 //掩码和字段值进行逻辑与运算,再执行匹 //配。”
Lookup key for ipv4_fib_lpm:
ingress_metadata_vrf: 0x0000001e, ipv4_dstAddr: 0x0a000002,
table hit
**********
entry at index 1:
key:
ingress_metadata_vrf: 0x0000001e (0 0 0 30), ipv4_dstAddr: 0x0a000000 (10 0 0 0),
prefix_length:
40
action:
fib_hit_nexthop
action data:
nexthop_index: 0x00000003 (0 0 0 3),
**********
action fib_hit_nexthop
action data:
nexthop_index: 0x00000003 (0 0 0 3), //设置下一跳索引
executing next table for action
Applying table nexthop
Lookup key for nexthop:
ingress_metadata_nexthop_index: 0x00000003,
table hit
**********
entry at index 2:
key:
ingress_metadata_nexthop_index: 0x00000003 (0 0 0 3),
action:
set_egress_details
action data:
egress_spec: 0x00000003 (0 0 0 3),
**********
action set_egress_details
action data:
egress_spec: 0x00000003 (0 0 0 3),
executing next table for action //设置下一跳egress出端口
total length for outgoing pkt: 100
deparsing ethernet //逆解析ethernet解析器刚刚解析的过程
deparsing ipv4 //逆解析刚刚ipv4解析器逆解析的港城
total length for outgoing meta: 26 //总的要进入egress元数据长度为26
copying metadata //赋值元数据
deparsing standard_metadata //逆解析固有元数据
deparsing ingress_metadata //你解析用户自定义元数据
queuing system: packet dequeued
egress port set to 3
instance type set to 0
egress_pipeline: packet dequeued
parsing start
parsing parse_ethernet
parsing parse_ipv4 //然后在向刚刚那样解析一次
payload length: 66
extracting metadata //提取元数据
extracting all metadata for 0x7f9ef0000930
Applying table rewrite_mac
Lookup key for rewrite_mac:
ingress_metadata_nexthop_index: 0x00000003,
table hit
**********
entry at index 2:
key:
ingress_metadata_nexthop_index: 0x00000003 (0 0 0 3),
action:
rewrite_src_dst_mac
action data:
smac: 0x010303030303, dmac: 0x000303030303,
**********
action rewrite_src_dst_mac
action data:
smac: 0x010303030303, dmac: 0x000303030303, //重写源目mac
executing next table for action
total lenth for outgoing pkt: 100
deparsing ethernet
deparsing ipv4 //在逆解析一次
outgoing thread: packet dequeued
outgoing thread: sending pkt: Size[100]: Port[3] //包从端口3送出去
p4factory下 targets/basic_rout的更多相关文章
- 实战 Prometheus 搭建监控系统
实战 Prometheus 搭建监控系统 Prometheus 是一款基于时序数据库的开源监控告警系统,说起 Prometheus 则不得不提 SoundCloud,这是一个在线音乐分享的平台,类似于 ...
- (四)学习了解OrchardCore笔记——将模块的名字添加到程序集的ModuleName
关于如何将模块名添加到程序集的ModuleName说简单吧也简单,说不简单吧也不简单. 简单的原因是代码只有几行,不简单的原因是这些都不是c#,都是MSbuild的代码.这可真难为我了,所以这个地方我 ...
- 初试 Prometheus + Grafana 监控系统搭建并监控 Mysql
转载自:https://cloud.tencent.com/developer/article/1433280 文章目录1.Prometheus & Grafana 介绍1.1.Prometh ...
- C++程序结构---1
C++ 基础教程Beta 版 原作:Juan Soulié 翻译:Jing Xu (aqua) 英文原版 本教程根据Juan Soulie的英文版C++教程翻译并改编. 本版为最新校对版,尚未定稿.如 ...
- Targets选项下Other linker flags的设置
-ObjC:加了这个参数后,链接器就会把静态库中所有的Objective-C类和分类都加载到最后的可执行文件中 -all_load:会让链接器把所有找到的目标文件都加载到可执行文件中,但是千万不要随便 ...
- centos7下安装iperf时出现 make: *** No targets specified and no makefile found. Stop.的解决方案
我们在Linux 安装包的时候,使用make 命令出现:"make:*** No targets specified and no makefile found.Stop."这样的 ...
- P4factory <Integration with Mininet>
在终端A进入simple_router目录,make bm之后,执行 ./run_demo.bash 成功和Mininet进行协作: *** Creating network *** Adding h ...
- P4factory 运行结果展示 basic_routing 以及 ./run_all_tests 的运行结果
p4factory子目录下的run_all_tests 安装好p4factory之后,打算跑一下样例来测试是否正确. 但是,跑了targets目录内的basic_routing,make又报错了,但之 ...
- P4factory ReadMe 剩余部分
Building and Running a Target Each P4 program (called a 'target') is set up in a directory under tar ...
随机推荐
- Go指南 - 笔记
Go指南 - 笔记 标签(空格分隔): Go Go指南 一.基础 1.包 每个Go程序都是由包构成的. 程序从main包开始运行. 包名与导入路径的最后一个元素一致 2.导入 分组导入:使用圆括号组合 ...
- 目标反射回波检测算法及其FPGA实现 之三:平方、积分电路及算法的顶层实现
目标反射回波检测算法及其FPGA实现之三: 平方.积分电路及算法的顶层实现 前段时间,接触了一个声呐目标反射回波检测的项目.声呐接收机要实现的核心功能是在含有大量噪声的反射回波中,识别出发射机发出的激 ...
- 【转】比较详细的Asp伪静态化方法及Asp静态化探讨
目前,各大搜索引擎如google.百度.雅虎已经对动态页面诸如asp,php有着不错的支持了,只要动态页面后面的参数不要太长,如控制在3个参数内,页面内容做点优化,各大搜索对该类页面收录甚至不比静态h ...
- 20155307刘浩《网络对抗》逆向及Bof基础
20155307刘浩<网络对抗>逆向及Bof基础 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件.该程序正常执行流程是:main调用foo函数,foo函数会回显任何用户输 ...
- 从OEL5中启动简单的dns服务
在OEL5中,有一个 dnsmasq,可以适合小型的实验性的dns设置. 如果可以看到类似如下的内容,说明dnsmasq已经设置好了. [root@dnssvr ~]# rpm -qa dnsmasq ...
- 【LNOI2014】LCA
题面 题解 考察\(dep[\mathrm{LCA}(i, x)]\)的性质,发现它是\(i\)和\(x\)的链交的长度. 那么对每个\(i\)所在的链打一个区间加标记,询问时算一下\(x\)所在的链 ...
- 初探JSP运行机制和与Servlet间的关系
自己看的书,手动画的图,如果有错误,请指正,谢谢.
- Tomcat 基础
一.Tomcat服务器端口的配置 Tomcat的所有配置都放在conf文件夹之中,里面的server.xml文件是配置的核心文件. 如果想修改Tomcat服务器的启动端口,则可以在server.xml ...
- chrome JS关闭当前页无效问题
如果没有父窗口,JS中 window.opener = null; window.open("", "_self"); window.close(); 对chr ...
- [C++]linux下实现rm()函数删除文件或目录
转载请注明原创:http://www.cnblogs.com/StartoverX/p/4600866.html 在linux下有两个函数可以用来删除文件: #include <unistd.h ...