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