Tag: Linux

SO_REUSEPORT 完全に理解した(い)

こんにちは! 今回は、弊研にて雑談中に SO_REUSEPORT の話題になった際に「どのようにソケットを選んで振り分けているの?」と聞かれて気になったので調査してみました(わかったとは言っていない)。 SO_REUSEPORT とは SO_REUSEPORT は、複数のスレッド、プロセスから同じポートを bind() できるようにするためのソケットオプションです。Linuxでは、Kernel 3.9 からサポートされています。 SO_REUSEPORT を用いて複数のスレッド・プロセスで同じポートで待ち受けることにより、TCPでコネクションを張る際の accept() 部分を負荷分散できるようになります。 使い方 SO_REUSEPORT で検索をするとCのサンプルコードなど多数ヒットするため割愛します。 端的に言えば、ソケットを bind() するまえに、setsockopt() で SO_REUSEPORT を設定すればよいです。 ちなみにRustで SO_REUSEPORT を利用したい場合は、libc や nix でも可能ですが、socket2 の利用が一番簡単でおすすめです。 どのように調査したか Linux Kernel のソースコードを読みました。 はじめに Interactive map of Linux kernel で読み始める箇所にあたりをつけました。今回はL4LBであるため protocols のレイヤー(一番右の列の中段あたりにあります)に絞ったのち、勘に頼ってそれらしいところを探していきました。 しばらくコードの森に迷い込んだのち、 tcp_v4_rcv() の lookup: でソケットバッファのコピー先になるソケットを見つけていることがわかりました。 コールスタックをたどっていくと、lookup_reuseport() という関数が見つかります。下記に lookup_reuseport() の一部を抜粋します。 inet_ehashfn()では、ハードウェア乱数生成器を用いて生成される乱数、送り元のアドレス、送り元のポート番号、送り先のアドレス、送り先のポート番号の5つの値からハッシュ値を計算しています。…

Read the full article