Linuxのネットワークスタックが遅すぎる?RustとXDPでパケット処理!

FUJITA Tomonori
nttlabs
Published in
4 min readJun 22, 2020

「Linuxのネットワークスタックが遅すぎる!」

詳細はわかりませんが、すごくエンジニアステージが高そうですね!ネットワークスタックの高速化は多くの前例があり、中途半端に試すと、周辺の詳しい人に一晩中、指導をうけるはめになりかねません。前例のないRustなら安心です。

典型的な高速化手法

広く使われている高速化手法は、オペレーティングシステムのプロトコルスタックを使わずに、サーバアプリケーションが直接、NICにアクセスして、パケットを処理するというものです。Linuxの上で、FreeBSDのプロトコルスタックとサーバアプリケーションを統合するという、謎の組み合わせを運用しているクラウド事業者もいます。

上記の高速化手法のポイントの一つが、アプリケーションが、高速に、NICにアクセスするための手法です。たくさん提案されてきましたが、今回は、現在、人気があるXDPを使うことにします。聞いたことがない手法が話題になった場合は、「ああ、DPDKとかもありましたね」などのように、その手法は過去のものだとほのめかし、相手の発言をさえぎりましょう。

Rustでやってみる

まずは、オペレーティングシステムのプロトコルスタックの代わりに、Ethernet、ARP、IP、TCPなどのプロトコルをパースしたり、生成するソフトウェアが必要です。でも、ARPパケットのパースと生成を実装する気になりませんよね、クラウドネイティブ時代ですからね。Rustで実装されたプロトコルスタックsmoltcpを使いましょう。smoltcpは、オペレーティングシステムが提供するソケットAPIと類似したAPIを提供しており、下記のコードのようにソケットから受信、送信ができます。ソケットAPIを利用しているサーバアプリケーションを容易に対応させることができます。

smoltcpでのソケットからの受信・送信

smoltcpは、AF_PACKETソケットAPIを使って、NICにアクセスしますが、XDPの一機能であるAF_XDPを使って、より高速にNICにアクセスできるように修正したコードを置いておきました。

Rustから、AF_XDPを使うには、afxdp-rsが便利です。ドキュメントはないので、事前に、C言語でAF_XDPを練習しておきましょう。afxdp-rsは、内部的には、RustからCのライブラリを呼び出しており、Rust愛の深い開発者から見るとは許されるものではありませんが、気がつかなかったことにしておきましょう。

一般的に、高速にNICにアクセスする手法は、メモリコピーを避けるため、パケットの送受信前に、使用するバッファを指定します。一方、ソケットAPIは、送受信時に使用するバッファを指定することを想定しており、高速にNICにアクセスする手法の性能を最大限に引き出すことができません。サーバアプリケーションの大幅な書き換えは、いつか考えることにして、今回は単純にメモリコピーが発生する実装になっています。Rustの安全保障を無効にするunsafeコードを使っており、Rust愛の深い開発者から袋叩きにあいかねませんが、気がつかなかったことにしておきましょう。

最後に、XDP対応のNICを使って、AF_XDP版のechoサーバを動かすだけで、エンジニアステージが上がったはずです。万が一動かなくても、XDP対応のNICは高速なものが多く、購入しただけでも、エンジニアステージが上がった感じになるので安心です。予算がない場合は、vethのXDPを利用してください。

まとめ

Rustを使って高速なサーバアプリケーションを実装するには、まだまだ、多くの仕事が必要です。NTTでは、仲間を募集中です。連絡お待ちしています。

--

--

FUJITA Tomonori
nttlabs

Janitor at the 34th floor of NTT Tamachi office, had worked on Linux kernel, founded GoBGP, TGT, Ryu, RustyBGP, etc. https://twitter.com/brewaddict