P4 tutorials实验 - load_balance
P4 tutorials实验 - load_balance
基础知识
- ECMP: Equal-Cost Multi-Path,等价多路径,参考链接
- 负载均衡:将负载分配到多个服务器上,避免少数服务器过载
- 哈希函数:
hash()
函数有五个参数,分别是存放hash结果、使用的hash算法、base值、哈希因子、count值 - 本实验中哈希因子选取五元组,即源ip、目的IP、协议、源端口、目的端口(注意两个端口应该在TCP报头获取)
- 本例中base=0,哈希运算的结果是0到count-1
实验部分
实验链接:https://github.com/p4lang/tutorials/tree/master/exercises/load_balance
本实验实现基于等成本多路径转发的简单版本的负载均衡。我们实现的交换机将会用两个table(ecmp_group
和ecmp_nhop
),将数据包随机地转发到两个目标主机中的一个。ecmp_group
表使用哈希函数选择一个目标主机,ecmp_nhop
表使用计算出的哈希值将数据包转发到所选的主机。
TODO 1:对五元组进行哈希运算并将运算结果保存到meta.ecmp_select中
action set_ecmp_select(bit<16> ecmp_base, bit<32> ecmp_count) {
/* TODO: hash on 5-tuple and save the hash result in meta.ecmp_select
so that the ecmp_nhop table can use it to make a forwarding decision accordingly */
hash (meta.ecmp_select, //存放result
HashAlgorithm.crc16, //选择的hash算法
ecmp_base,//base值
{
hdr.ipv4.srcAddr, hdr.ipv4.dstAddr, hdr.ipv4.protocol, hdr.tcp.srcPort, hdr.tcp.dstPort
},//哈希因子
ecmp_count);//count值
}
TODO 2: 应用ecmp_group表与ecmp_nhop表
apply {
if (hdr.ipv4.ttl > 0 && hdr.ipv4.isValid()) {
//当ipv4头部有效且ttl还没有减到0时
ecmp_group.apply();
ecmp_nhop.apply();
}
}
编译运行,尝试发送多条消息,可以看到h1向同一个目的ip发出的消息可能被h2或者h3接收
tips
问题1:step 1
中,直接进行make
操作,可能出现以下报错:
AttributeError: Could not find 'MyIngress.ecmp_group' of type tables
make: *** [../../utils/Makefile:35: run] Error 1
在原始的load_balance.p4
代码中,确实可以看到MyIngress
的apply
部分为空,但如果在apply
部分直接应用这两个表,即直接写入如下代码的话,虽然可以消除报错,但在运行未完整代码时,h2可以收到信息,不满足其实验现象。
ecmp_group.apply();
ecmp_nhop.apply();
解决方案:直接完成apply
部分的TODO
任务,重新编译运行step 1
中的操作,可以满足其实验现象。
further observation
用来进行哈希运算的操作set_ecmp_select
的参数ecmp_base
和ecmp_count
是sX-runtime.json
中下发的,分别取值为0和2,且该表项的match
字段是目的ip地址,这意味着只有目的ip为10.0.0.1
的数据包才会被这条规则进行负载均衡,如下s1-runtime.json
代码显示:
{
"table": "MyIngress.ecmp_group",
"match": {
"hdr.ipv4.dstAddr": ["10.0.0.1", 32]
},
"action_name": "MyIngress.set_ecmp_select",
"action_params": {
"ecmp_base": 0,
"ecmp_count": 2
}
},
此外,哈希函数中count值(即本例中的ecmp_count
)的限制作用,是<= count-1
而不是<= count
,可参考sX-runtime.json
中下发的规则,其用来存放哈希结果的元数据meta.ecmp_select
只有两个匹配值,分别为0和1,分别对应拓扑中的主机h2和h3,(如下s1-runtime.json
代码显示),这意味着哈希运算的结果只有0或1两种可能,所以是<= count-1
。
{
"table": "MyIngress.ecmp_nhop",
"match": {
"meta.ecmp_select": 0
},
"action_name": "MyIngress.set_nhop",
"action_params": {
"nhop_dmac": "00:00:00:00:01:02",
"nhop_ipv4": "10.0.2.2",
"port" : 2
}
},
{
"table": "MyIngress.ecmp_nhop",
"match": {
"meta.ecmp_select": 1
},
"action_name": "MyIngress.set_nhop",
"action_params": {
"nhop_dmac": "00:00:00:00:01:03",
"nhop_ipv4": "10.0.3.3",
"port" : 3
}
},