Docs.com へのサインインに使うメール アドレスまたは電話番号を入力してください。 Office など、Microsoft の他のサービスで既にお使いのアカウントがあれば、そのアカウントを入力してください。
アカウントを記憶する
または次の方法でサインインします:
サインインすると、コンテンツのダウンロードや「いいね!」をすることができ、作成者が認識します。
埋め込みコード: Linuxless DPDK
サイズの選択
Porting DPDK to a Unikernel
Linuxless DPDK
@syuu1228
https://doc.co/wb9Knr
Who am I
syuu1228
ScyllaDB Ltd. (Israel)
DPDK?
DPDK: Data Plane Development Kit
http://dpdk.org/ http://dpdk.org/
むちゃくちゃ速いネットワーク IOを行うためのライブラリ
むちゃくちゃ速くするために既存のソケット API、ネットワークスタック、 NICドライバなどすべてを迂回
ライブラリから直接 NICの MMIO領域にアクセスしてパケット送受信
何故必要になるのか
10G NIC のラインレート
最小サイズのフレームを 10Gbpsいっぱいで送ると、秒間 14.88Mpps(packet/sec)
14.88Mpps を1 秒で処理するには、1 パケットあたり67.2ns で処理する必要がある
3GHz のCPU だと約200 サイクル
余計なことをやっている暇が全くない
参考:
http://netoptimizer.blogspot.jp/2014/05/the-calculations-10gbits-wirespeed.html http://netoptimizer.blogspot.jp/2014/05/the-calculations-10gbits-wirespeed.html
FreeBSD でのsendto() の実行時間計測例
Function
Time (ns)
sendto
96
sosend_dgram
137
udp_output
57
ip_output
198
ether_output
162
ixgbe_xmit
220
Total
950
システムコールを呼んだだけで 67.2ns超えてる
http://info.iet.unipi.it/~luigi/papers/20120503-netmap-atc12.pdf http://info.iet.unipi.it/~luigi/papers/20120503-netmap-atc12.pdf
全部迂回したい
カーネルバイパスの実現方法
PCI UIO Driver
# modprobe uio_pci_generic # echo -n 0000:00:19.0 > /sys/bus/pci/drivers/e1000e/unbind # echo -n 0000:00:19.0 > /sys/bus/pci/drivers/uio_pci_generic/bind
fd = open(/dev/uio0)
address = mmap(fd)
DPDK で使われているその他の高速化
Hugepages: TLBmiss を避けるため、DPDK で使用するメモリをhugetlbfs 経由で割り当て
CPU affinity: CPU 毎にスレッドを張付 キャッシュ競合、ロック競合が起きないように各CPU を使用 例:NIC のポートごとに別CPU を割り当て CPU 間でパケットを渡すためのロックレスring
デフォルトで -march=native SSE, AVXなど使えるもの全部使用
DPDK アプリ例
ポート 0・ポート 1間で相互にパケットを転送(超簡易的ブリッジ)
while (true) {
for (rx_portid = 0; rx_portid < 2; rx_portid++) {
tx_portid = !rx_portid;
nb_rx = rte_eth_rx_burst(rx_portid, 0, pkts_burst, 32);
rte_eth_tx_burst(tx_portid, 0, pkts_burst, nb_rx);
}
https://github.com/syuu1228/dpdk_seccamp_2016/blob/master/simple_bridge/main.c https://github.com/syuu1228/dpdk_seccamp_2016/blob/master/simple_bridge/main.c
DPDK – Linux = ?
Linux 要らないのでは
DPDK のAPI さえ走ればLinux みたいな大きなOS が動いている必要ない
むしろ他のプロセスやカーネルスレッドなどが走ると邪魔になるのでは
理想:ベアメタル環境で DPDKアプリだけがずっとビジーループしてる
なんかこんなのでいいのでは
Kernel mode
DPDK
ブート・初期化コード 的ななにか
そもそも
そもそも初期の非公開バージョンの DPDKではベアメタルで動いていた模様
この部分のコードは公開されていないらしい
そういえば
シングルプロセス
ちょっと頑張ると実機で動く 参考:
http://www.yushiomote.org/blog/?p=469 Osp
http://www.yushiomote.org/blog/?p=469 : Bare-metal
http://www.yushiomote.org/blog/?p=469 OSv
ちょっと頑張れば不要な部分は外せる
Linux アプリと そこそこ 互換性がある→完全なOS なし環境より簡単に持ってこれる
移植してみた
ここまで DPDKは Linuxの上で動かすものとして説明してきたが、実際には複数の環境に対応できるように実装されている
FreeBSD サポート済み
環境の違いを吸収するレイヤが存在 ( EAL: Environment Abstraction Layer)
EAL にOSv サポート用のコードを追加、OS 依存なHugepage 確保のコードやPCI デバイスへのアクセスコード、 スレッドのAffinity 設定などを実装すれば動くはず (FreeBSD 版をコピーしてきて必要な部分を実装)
最低限必要っぽいもの
PCI 初期化
OSv の内部インタフェースを呼び出し、PCI デバイスのリストを取得
一つずつ PCIデバイスクラスのインスタンスを取り出して DPDKの構造体に変換
PCI デバイスクラスのインスタンスよりMMIO メモリ領域のアドレスを取得、DPDK の構造体に書き込み(UIO デバイスのmmap() に相当)
pci_device_list に追加
https://github.com/syuu1228/dpdk/blob/osv-1.8.0-cleanup/lib/librte_eal/osvapp/eal/eal_pci.cc#L163
PCI デバイス発見とドライバ初期化開始
PCI デバイスに対応するUIO デバイスを探してmmap() するコードの部分は不要になるのですべて削除(初期化時にアドレスは取得済み)
ベンダ ID、デバイス IDが一致するならドライバ初期化開始
https://github.com/syuu1228/dpdk/blob/osv-1.8.0-cleanup/lib/librte_eal/osvapp/eal/eal_pci.cc#L109
OSv 側のNIC ドライバを無効にする
OSv のカーネル引数に--maxnic=<n> オプションを実装
N 個以上のNIC をプローブしない 0 が指定されたら一つもプローブしない
Hugepage での メモリ割り付け
そもそも OSvでは Hugepageが常に有効なので、単にページアラインされた連続領域をリクエストサイズ分確保
メモリアドレスを DPDKの構造体に代入
https://github.com/syuu1228/dpdk/blob/osv-1.8.0-cleanup/lib/librte_eal/osvapp/eal/eal_memory.cc#L90
スレッドに対する CPU Affinty設定
単に pthread_setaffinty_np ()を呼ぶ(実装されている)
https://github.com/syuu1228/dpdk/blob/osv-1.8.0-cleanup/lib/librte_eal/osvapp/eal/eal_thread.c#L121
タイマー
Linux のEAL に/dev/hpet をmmap() して直接HPET のカウンタを読み出す豪快なコードが実装されてい る
/dev/hpet をopen() & mmap() する部分を削除
ACPI Table からHPET のアドレスを取得して 物理アドレス→論理アドレス変換するコードを追加
https://github.com/syuu1228/dpdk/blob/osv-1.8.0-cleanup/lib/librte_eal/osvapp/eal/eal_timer.cc#L190
CPU 情報
CPU 数をOSv の内部インタフェースから取得してDPDK の構造体に代入
https://github.com/syuu1228/dpdk/blob/osv-1.8.0-cleanup/lib/librte_eal/osvapp/eal/eal_lcore.cc#L82
Makefile
OSv のヘッダをinclude
.cc ファイルをg++ でコンパイル
コード量
$ git diff 6fb3161060fc894295a27f9304c56ef34492799d|wc -l
3842
動いた
l2fwd
更に Seastarも載せてみる
Seastar(TCP/IP)
まとめ
OSv を利用してベアメタルDPDK っぽい 何かが実装できた
今のところ KVM & virtio -netで動作
OSv のLinux 互換機能を利用してSeastar+DPDK も動作
TODO
動いた、以上の状態ではないのでパフォーマンスチューニング必要
まともにベンチマーク取る
少し古い成果でメンテし続けられてないので最新版で動かない バージョンアップ必要
PCI パススルー/SR-IOV
実機で動かす
OSv から要らない機能を削って余計なスレッドへコンテキストスイッチしないようにしたい
Code
https://github.com/syuu1228/dpdk/tree/osv-1.8.0-cleanup
https://github.com/syuu1228/osv-apps/tree/seastar
https://github.com/syuu1228/osv-apps/tree/seastarて
Linux のEAL