tc flowerオフロードを利用してNICハードウェア上でパケットフィルタを実施する
Linuxのtc
には、指定した条件にマッチしたパケットをドロップしたりヘッダを書き換えたりするためのflower
フィルタが存在する。
tc-flower(8) - Linux manual page
最近のNICの中にはこの処理をハードウェアにオフロードできるものがあり、通常のソフトウェア処理と比較して高スループットを実現しつつCPU使用率低減が期待できる。ここではtc flowerのNICハードウェアオフロード機能の動作を試してみる。
対応するNICドライバ
Linuxカーネル4.16.7のソースコード上で確認する限り、以下のNICドライバでtc flowerハードウェアオフロードに対応しているようである。ちなみに対応状況はTC_SETUP_CLSFLOWERないしTC_SETUP_BLOCK*1といったキーワードで検索するとおおよそ掴める。
- Broadcom
bnxt
(BCM573xx; NetXtreme C-series/E-series) - Chelsio
cxgb4
(T4/T5/T6) - Intel
i40e
(710 series) - Mellanox
mlx5
(ConnectX-4/5) - Netronme
nfp
(Agilio) - (Mellanox
mlxsw
*2 )
ただし、オフロード可能なマッチング条件 (ヘッダのフィールド) およびアクションはNICドライバおよびハードウェアによって異なる。ドライバが対応していてもハードウェアの世代やファームウェアバージョンによっては動作しない場合もある。たとえばi40e
はtc flowerハードウェアオフロード自体には対応しているがaction drop
のオフロードに対応していない*3ため、これから述べるパケットフィルタの例は動作しない*4。
設定方法
ethtool
コマンドでtc offloadを有効にしたのち、tc
コマンドでフィルタを設定してやればよい。
$ uname -a Linux server01 4.16.5-300.fc28.x86_64 #1 SMP Fri Apr 27 17:38:36 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux $ tc -V tc utility, iproute2-ss180129 $ ethtool -i enp7s0f0 driver: mlx5_core version: 5.0-0 firmware-version: 14.22.1002 (MT_2420110004) (snip)
ethtool -K IFACE hw-tc-offload on
でtc offloadを有効にしたのち、対象インタフェースのqdisc
にingress
を追加する。qdisc
はingress
ではなくclsact
を使用してもよい。clsact
はingress
をegress方向への操作にも適用できるように一般化したもの (net, sched: add clsact qdisc)。ただしegress方向へのflower
適用に対応しているNICは現状無さそう*5なので、特に差異は無いはず。また詳しく追えていないがFedora 28でNetworkManagerが動作していると、追加したingress
がしばらく経過すると削除される事象がみられた。
$ sudo ethtool -K enp7s0f0 hw-tc-offload on $ sudo tc qdisc add dev enp7s0f0 ingress $ tc qdisc show dev enp7s0f0 qdisc mq 0: root qdisc fq_codel 0: parent :8 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 32Mb ecn qdisc fq_codel 0: parent :7 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 32Mb ecn qdisc fq_codel 0: parent :6 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 32Mb ecn qdisc fq_codel 0: parent :5 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 32Mb ecn qdisc fq_codel 0: parent :4 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 32Mb ecn qdisc fq_codel 0: parent :3 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 32Mb ecn qdisc fq_codel 0: parent :2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 32Mb ecn qdisc fq_codel 0: parent :1 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 32Mb ecn qdisc ingress ffff: parent ffff:fff1 ----------------
tc filter add ... flower ... action ...
の形式でマッチ条件と動作を指定する。ここでは8080/tcp
宛のパケットをドロップするよう設定している。skip_sw
を指定するとハードウェアオフロードのみを試行し、オフロードできない場合はエラーとなる。skip_hw
を指定するとソフトウェア処理のみを試行する。何も指定しない場合はまずハードウェアオフロードを試行し、オフロードできない場合はソフトウェア処理にフォールバックする。また、実際にオフロードされていればin_hw
が、そうでなければnot_in_hw
が表示される。
$ sudo tc filter add dev enp7s0f0 ingress protocol ip \ flower skip_sw ip_proto tcp dst_port 8080 action drop $ tc filter show dev enp7s0f0 ingress filter protocol ip pref 49152 flower chain 0 filter protocol ip pref 49152 flower chain 0 handle 0x1 eth_type ipv4 ip_proto tcp dst_port 8080 skip_sw in_hw action order 1: gact action drop random type none pass val 0 index 1 ref 1 bind 1
tc
コマンドに-s
オプションを付ければ統計情報も出力される。ここでは別ホストからhping -S -p 8080 --flood
で8080/tcp
宛にパケットを送ってみたが、CPU使用率の上昇は特にみられなかった。
$ tc -s filter show dev enp7s0f0 ingress filter protocol ip pref 49152 flower chain 0 filter protocol ip pref 49152 flower chain 0 handle 0x1 eth_type ipv4 ip_proto tcp dst_port 8080 skip_sw in_hw action order 1: gact action drop random type none pass val 0 index 1 ref 1 bind 1 installed 947 sec used 0 sec Action statistics: Sent 1002736860 bytes 16712281 pkt (dropped 16712281, overlimits 0 requeues 0) backlog 0b 0p requeues 0
削除はtc filter del
コマンドで。
$ sudo tc filter del dev enp7s0f0 ingress protocol ip pref 49152 handle 1 flower
tc-flower offloadのその他の利用例
ここまでtc flower offloadを使って特定のパケットをハードウェア上でドロップする例を見てきたが、実のところ同様のことはntupleフィルタをethtool
経由で設定することで以前から実現可能である:
ethtool
を用いたntupleフィルタと比較したtc flower offloadの利点は、drop
以外のアクションをオフロードすることでNICハードウェアに多彩な動作を行わせることが(仕組み上)可能な点にある。
たとえばpedit
アクションとcsum
アクションをオフロードすれば、簡易的なstatic NATを実装できる*6:
また、mirred
アクションをオフロードすれば、NICをL2スイッチや簡易的なL3スイッチのように振る舞わせることができる。これをSR-IOV switchdev modeと組み合わせれば、SR-IOVでVM向けに高パフォーマンスなネットワーク環境を提供しつつ、ハイパーバイザ側からVM間通信の挙動を制御することができる。実際にOpen vSwitch 2.8以降はこれらを利用してVM間のL2通信をNICハードウェアにオフロードする機能が実装されている。
SR-IOV switchdev modeの概要:
Introduction to switchdev SR-IOV offloads - Netdev 1.2
OpenStackとの組み合わせ例:
OpenStack Docs: Open vSwitch hardware offloading
Getting started with Mellanox ASAP^2 | Mellanox Interconnect Community
参考資料
- TC Flower Offload - Netdev 2.2
- tc flower offloadのイントロダクション的なセッション。スライド、ビデオあり
- TC Workshop - Netdev 2.2
- 各NICベンダの対応状況など。スライド、ビデオあり
- tc flower offload関連のman pages
*1:https://github.com/torvalds/linux/commit/6529eaba33f0465fc6d228e1d05b1745f7d0e8c9
*2:NICドライバではなく、MellanoxのイーサネットスイッチASIC (spectrum) をネイティブなLinuxネットワークAPIで操作できるようにするドライバ
*3:https://github.com/torvalds/linux/commit/2f4b411a3d6766e6362ffbf00e0495a2dfe92507 https://patchwork.ozlabs.org/cover/824130/ あたりを参照
*4:正確に言うとtc filter add ... skip_sw ... action dropコマンドは通るが動作している気配が無い@Intel X710
*5:対応しているのは恐らくswitch ASICであるところのmlxswのみ https://github.com/Mellanox/mlxsw/wiki/ACLs
*6:ConnectX-4 Lxでは mlx5: parsed 0 pedit actions, can't do more と言われて設定できなかった; https://github.com/torvalds/linux/blob/v4.16/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c#L1653-L1656