2019年10月31日
一、需求
- 内核如何支持udp gso;
- 测试(包括性能);
- 用户如何使用udp gso;
二、背景
针对上述问题,本小节展开一定的论述,基础知识就不再赘述了。
Linux支持udp下的generic segmentation offload特性有两种实现方式,一种是在protocal stack做,一种是在NIC driver做。协议栈中做的udp gso我们亦可称为uso,基于协议栈支持的前提下,若硬件支持我们可称为udp gso offload或uso offload,顾名思义,后者基于前者再做offload。[注:udp gso容易和几年前开发的ufo混淆,ufo特性是做在NIC网卡driver上,而ufo问题频发导致很多NIC不再做支持。]
2018年Willem de Bruijn公布了draft论文Optimizing UDP for Content Delivery with GSO, Pacing and Zerocopy ;2018年4月26日,社区合并了第一份uso的patchset(总共10个patch); 2018年11月14日举办了Linux Plumbers Conference论文的presentation。2018年12月3日youtube公开了对应的演讲视频。
2018年6月社区合并了第一个网卡driver(mlx5-core)的特性支持;2019年10月intel提供了自己的三块网卡(igb/ixgbe/i40e)的支持,但是暂未合并到主线。netdevconf的session的公开资料。
这里列出一些uso的基本原理:
1. 下图的表示了ufo和uso切割packet时候的处理方式不同,uso是每一块都需要带上udp header头部(ipv4,8字节),而ufo不需要。
2. 下图展示了三种情况,从左到右,1)正常upd发包流程,在proto协议栈层ip层分片,一路小包到NIC再到接收端大量小包;2)开启gso后,proto协议栈层不再做分片,一路大包到NIC网卡,在网卡发送前做分片;3)开启gso+gro(gro是接收端),在发送端同(2)一样,只是接收端在接收到大量小包后合包成大包;理论上加上测试数据来看,从左到右是性能上依次的升级。
3. 下图展示了三种NIC前处理包情况,1)开启udp gso,如果packet正好是gso切割包大小的整数倍,则正常处理每一块并做好checksum,2)开启udp gso,如果packet不是gso的整数倍,则需要对最后一块做额外处理,3)开启udp gso,且支持gso partial(请注意和driver的gso partial不是一个),则可以将前面的若干包合并只是用一个header,最后一块作为non-gso块处理即可。做更细的理解,此gso partial的代码["mss *= skb_shinfo(segs)->gso_segs;"]中将MSS的值扩大成了gso_segs倍,也就是如前所说若干的小包合并为一个。
注:driver层如mlx5-core的gso partial支持,只是为了在网卡特性开启(ethtool -K [网卡] xxx on/off)时能够区分开正常gso和udp gso offload功能而已,可以让用户能够支持gso的情况下开启或关闭udp gso offload,原始设计时候二者是混为一谈,用同一开关来控制。综上,此gso partial非上文提及的gso partial。
三、测试
测试过程,请按如下准备:
1)两台机器client和server。可选在同一网段,并保证OS是linux4.18.0+系列。
2)两个内核代码。在两台机器分别下载对应版本的内核代码,并进入到tools/testing/selftests/net的目录下,make编译即可。
3)server端输入命令 ./udpgso_bench_rx 即可作为udp监听程序,如果加参数"-t"表示监听tcp程序。
4)client端输入命令 sudo perf stat -a -C 5 -e cycles ./udpgso_bench_tx -l 4 -4 -D {server ip addr} -S 即可开启uso功能,如果不加参数"-s"表示正常udp发包。
5)如想开启硬件支持uso offload,需查看网卡是否为mlx5-core,并且查看网卡特性是否在gso-partial下有udp-segmentation-offload开关。
6)记录第(4)步骤结果,即可。
测试结果,请阅读以下细节:
- TH-PUT即THROUGHPUT单位MB/s;
- CALLS单位calls/s;越小越好,带来cpu开销就越小;
- MESSAGES单位msg/s;
- 测试命令前可加入time命令,可测量SYS/USER的开销。
- perf测试尽可能不要使用多核,否则由于cpu调度会带来实验结果的不一致性,绑核一个cpu即可。
如下是一组实测数据对比:
MACHINE | TYPE | TH-PUT | CALLS | MESSAGES | USER | SYS |
client | udp | 839 | 663894 | 14245 | 0m0.343s | 0m3.385s |
udp gso | 1139 | 19333 | 19333 | 0m0.038s | 0m2.018s | |
server | udp | 932 | 663896 |
| ||
udp gso | 1135 | 808258 |
如下是作者公开数据:
Types | calls/s | Mcycles/s | Speed-up (%) |
TCP | 19040 | 618 | 487 |
UDP | 812000 | 2801 | 100 |
UDP GSO | 18248 | 1726 | 174 |
上述的测试过程、方法及结果已找udp gso作者Willem de Bruijn确认。
- 开启gso后,client的calls次数相对于server降低40倍;而未开启的两端calls几乎一样。
- 开启gso后,USER开销方面,udp gso相对于gso提升了8倍。
- 开启gso后,SYS开销方面,udp gso相对于gso提升了0.67倍。
四、应用
- 开启内核支持
如下是最初需要的socket设置:
static void set_pmtu_discover(int fd, bool is_ipv4)
{
int level, name, val;
if (is_ipv4) {
level = SOL_IP;
name = IP_MTU_DISCOVER;
val = IP_PMTUDISC_DO;
} else {
level = SOL_IPV6;
name = IPV6_MTU_DISCOVER;
val = IPV6_PMTUDISC_DO;
}
if (setsockopt(fd, level, name, &val, sizeof(val)))
error(1, errno, "setsockopt path mtu");
}
如下是udp发包的过程:
static int send_udp_segment(int fd, char *data)
{
char control[CMSG_SPACE(sizeof(cfg_mss))] = {0};
struct msghdr msg = {0};
struct iovec iov = {0};
int ret;
iov.iov_base = data;
iov.iov_len = cfg_payload_len;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = control;
msg.msg_controllen = sizeof(control);
send_udp_segment_cmsg(CMSG_FIRSTHDR(&msg));
msg.msg_name = (void *)&cfg_dst_addr;
msg.msg_namelen = cfg_alen;
ret = sendmsg(fd, &msg, cfg_zerocopy ? MSG_ZEROCOPY : 0);
if (ret == -1)
error(1, errno, "sendmsg");
if (ret != iov.iov_len)
error(1, 0, "sendmsg: %u != %lu\n", ret, iov.iov_len);
return 1;
}
确定测试或业务方使用的代码包括上面的socket设置部分和发包方式即可。
仅作了解:
开启gso后,大概流程如此:发包流程将延迟分片,本在ip层做分片(ipv4/output.c文件下ip_fragment()函数),而现在将分片推迟到NIC发送前一刻。
五、未来展望
目前在4.18.0 redhat8或centos8版本内核有如下问题:
- 在应用层代码中使用sendmsg(),而sendmmsg()是无法和uso一起工作。
- udp gso不支持MGS_ZEROCOPY。
- 使用udp gso offload代替udp gso是否会带来真正性能上的提升。
- 目前udp gso offload只有mlx5-core支持,而intel近一个月才提交patch还未进入upstream。
- udp gso设置packet size是否有最优值。
如上只是一些brainstorm,未来可做事情依然很多,但是技术方案并不成熟,最大的问题是兼容性。虽然合并到了upstream,但是不能代表能再生产环境稳定运行。
附录
- LPC presentation PPT
- NETCONF2017 PPT
- mlx5-core UDP GSO support
- intel系列网卡support
- LPC presentation video
- 世民谈云计算blog