P4 tutorials实验 - basic-tunnel
基础知识
- 隧道(tunnel):可以将IP隧道视为一对节点之间的虚拟点对点链路
- 虚拟链路是在隧道入口处的路由器内创建的,当隧道入口处的路由器想通过这个虚拟链路发送数据包时,就将数据包封装在IP数据报中,IP报头中,目标地址是隧道远端路由器的地址,源地址是封装路由器的地址
- P4程序定义了数据包处理流水线,但每个表中的规则是由控制平面插入。当一个规则匹配一个数据包时,它的操作将使用控制平面提供的参数,作为规则的一部分进行调用
- 表(table):定义匹配域以及对应的执行动作,定义了匹配字段(key)、可选的动作(action)和一些其他相关属性
实验预览
实验链接:https://github.com/p4lang/tutorials/tree/master/exercises/basic_tunnel
本实验为basic实验中实现的IP路由器,添加对基本的隧道协议的支持。basic交换机是基于目标IP地址进行转发的,我们的工作是定义一个新的header类型来封装IP数据包,并修改交换机的代码,使得交换机使用新的隧道报头来决定目标端口。
新的header类型会包含一个协议ID,用来表示封装的数据包的类型,还会包含一个用于路由的目的ID
我们能够根据自定义封装报头的内容进行转发,并且在数据包中不存在封装报头的情况下,执行正常的IP转发
注意到header结构体中,多了一个新的header类型myTunnel:
struct headers {
ethernet_t ethernet;
myTunnel_t myTunnel;
ipv4_t ipv4;
}
todo1:修改parser部分,使其也能够解析mytunnel报头
todo2:定义一个新的action,名称为myTunnel_forward
,操作是将出端口(例如standard_metadata
中的egress_spec字段)设置为控制平面提供的端口号
todo3:定义一个新的table,名称为myTunnel_exact
,这个表在myTunnel报头的dst_id
字段进行精确匹配,如果表中存在匹配项,应该调用myTunnel_forward
操作,如果没有,调用丢包操作
todo4:更新apply语句,使得当myTunnel报头有效时,应用新定义的myTunnel_exact表,否则,如果ipv4报头有效,调用ipv4_ipm表
todo5:更新deparser,提交以太网报头、myTunnel报头和ipv4报头,deparser仅在报头有效时才会进行emit,因为header的隐含有效位是由parser在提取时设置的,所以这里不需要检查header的有效性
具体实验
step 1:未使用隧道技术
step 2:修改basic_tunnel.p4
- parser部分
parser MyParser(packet_in packet,
out headers hdr,
inout metadata meta,
inout standard_metadata_t standard_metadata) {
state start{
packet.extract(hdr.ethernet);
transition select(hdr.ethernet.etherType){
//根据etherType字段,提取出mytunnel报头或ipv4报头
TYPE_IPV4: ipv4_parser;
TYPE_MYTUNNEL:mytunnel_parser;
//如果匹配TYPE_MYTUNNEL的值,则跳转到mytunnel_parser状态
default: accept;
}
state ipv4_parser{//ipv4解析部分
packet.extract(hdr.ipv4);//取出ipv4包头
transition accept;
}
state mytunnel_parser{//mytunnel解析部分
packet.extract(hdr.myTunnel);
transition select(hdr.myTunnel.proto_id){
TYPE_IPV4:ipv4_parser;
//proto_id是被封装的数据包的类型
//如果proto_id==TYPE_IPV4,说明被封装的是ipv4报文,解析器在mytunnel报头之后,还需要提取ipv4报头
default:accept;
}
}
}
}
- control部分
key由一个个表单对组成(e:m),其中e是对应数据包中匹配的字段,而m是一个match_kind常数,用来表示匹配的算法,默认的有:lpm最长前缀匹配,exact精确匹配,ternary三元匹配
action myTunnel_forward(egressSpec_t port) {
standard_metadata.egress_spec = port;
//port是控制平面提供的端口号
//通过修改egress_spec字段,来实现对应功能
}
table myTunnel_exact {
key = {
hdr.myTunnel.dst_id: exact;//exact:精确匹配
//dst_id是目标主机的ID,是要进行精确匹配的字段
}
actions = {//可选的动作
myTunnel_forward;
drop;
NoAction;
}
//size = 1024; size是表的大小,不定义也可以
default_action = drop();//default_action是当table miss的时候执行的动作
}
apply{
if(hdr.myTunnel.isValid()){//当myTunnel报头有效时
myTunnel_exact.apply();//应用新定义的myTunnel_exact表
}
else if(hdr.ipv4.isValid()){
ipv4_lpm.apply();//否则,如果ipv4报头有效,调用ipv4_ipm表
}
//注意要进行apply()才会用上对应的table
}
- deparser部分
control MyDeparser(packet_out packet, in headers hdr) {
apply {
packet.emit(hdr.ethernet);
packet.emit(hdr.myTunnel);//对myTunnel报头进行emit
packet.emit(hdr.ipv4);
}
}
step 3:使用隧道技术的效果
如果将ip地址改为h3的ip地址,发现交换机实现隧道转发,根据dst指定的地址进行转发,不受到ip地址的影响:
标签:myTunnel,hdr,P4,tunnel,parser,packet,ipv4,tutorials,报头 From: https://www.cnblogs.com/CCchaos/p/16854510.html