I350のRSS Queueが溢れた

明けましておめでとうございます。
今年も本糞ブログを細々と続けていくのでよろしくお願いします。
去年はイーサネットフレームのバイト数もわからない様々な人たちに自社のインフラにクラウド導入を促されてキレそうになっていましたが、今年は遠慮なくキレようと思います。

コミケにフル参戦していたため年を越してしまいましたが、年末に起きたちょっとしたRSSのQueueに関する騒動をまとめます。

新しく構築した環境の特定のサーバで以前に書いたI350の受信バッファが溢れた時と同様にifconfigのoverrunsのカウンターの急上昇を確認しました。
なんだまたリングバッファ溢れかとその時は思いましたが、前回とは異なりパケットドロップ、破棄のカウンター上昇はありませんでした。

前例からoverrunsが出ている時点でパケットが捨てられているという先入観があったため、最初は意味がわかりませんでしたがぼちぼち調査を開始しました。

例によってethtool -S | grep dropで調べたところ、以下のカウンターがゴリゴリあがっていました。

     rx_queue_0_drops: 0
     rx_queue_1_drops: 0
     rx_queue_2_drops: 1098532642
     rx_queue_3_drops: 5009716490

カーネルソースを読んだところ、このキューはRSSのキューです。
このサーバはRSSでIRQを4個掴んでいるためこのようなキューの合計数になっています。

今回はここからが本題です。

この問題は自社では新しい環境のリアルサーバとLVSとで初めて確認されました。
原因は特定のホストとの同一の条件の通信が大量発生することによるRSSのキューイングアルゴリズムの偏りです。

RSSはデフォルトではIPとPortをHask keyにして各キューに分散しているため、特定のホストと同じ条件の通信が集中するとRSSのキューの分散に偏りがでます。
偏った結果、キューが溢れ順番にリキューされ、上記のようにdropのカウンターが階段状になります。

対策としてRSSのキュー自体を綺麗に分散する方法を考えましたが、現状Linuxで実用的な方法はないようです。
Symmetrical RSSというロードバランス方法がひっそり世間に出つつあるようなので期待しています。

自社の対策としてはキューであるリングバッファの設定値をデフォルトの256から4096にすることも考えましたが、現状の通信状況を考慮してあえてデフォルトの256のままで運用することにしました。
根拠は以下の図の通りです。

rss_queueキューが偏っている状態でキューサイズであるリングバッファの設定を増やしても遅延するだけと考えました。
現状では効率は悪いけどリキューさせたほうがまだ遅延しないという判断です。

各界で言われているようにバッファは確かに遅延を招きます、しかしバッファが溢れドロップした場合はさらに膨大な遅延を招きます。
キューやバッファマネージメントは土管が太くなる一方の世の中で、我々ネットワークに携わる者に求められる能力になると思います。