---
title: JANOG45 パケット処理の独自実装や高速化手法の比較と実践 独自パケット処理の実装方法の解説（XDP）
tags:  #janog #xdp #ebpf  
author: [Yuya Kusakabe](https://www.docswell.com/user/higebu)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/4JQ611WWJP.jpg?width=480
description: JANOG45 パケット処理の独自実装や高速化手法の比較と実践 の登壇資料です。 https://www.janog.gr.jp/meeting/janog45/program/pktfwd/ https://www.janog.gr.jp/meeting/janog45/application/files/1615/7984/1029/008_pktfwd-xdp_kusakabe_00.pdf
published: January 24, 20
canonical: https://www.docswell.com/s/higebu/Z3GV9V-janog45-pktfwd-xdp
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/4JQ611WWJP.jpg)

パケット処理の独自実装や高速化手法の
比較と実践
独自パケット処理の実装方法の解説（XDP）
日下部雄也
BBSakura Networks株式会社
小樽市在住
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 2

![Page Image](https://bcdn.docswell.com/page/K744RRK171.jpg)

XDPとは
Application
Userspace
AF_XDP Socket
Socket
Protocol Stack
Kernel
XDP_REDIRECT
XDP_PASS
eBPF Map
XDP
XDP_DROP
Driver
XDP_REDIRECT
XDP_TX
HW
NIC
NIC
※XDP_REDIRECTはbpf_redirect(), bpf_redirect_map()を経由して使う
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 3

![Page Image](https://bcdn.docswell.com/page/LJ14QQX5JG.jpg)

ユースケース（再掲）
●
●
●
●
●
●
●
bpfilter: iptablesをXDPにオフロード
Cloudflare(DDoS Mitigation)
Facebook(Katran): L4LB
Cilium: Kubernetes上での透過的なセキュリティ、ネットワーク、LB
XFLAG(Static NATなど)
LINE(L4LB, SRv6)
BBSakura Networks(Mobile Core)
○
○
●
●
さくらのクラウドで XDPを使えるようになっている
サーバのタグに @nic-double-queue と入れると使える
OvS-AF_XDP
DPDK-AF_XDP
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 4

![Page Image](https://bcdn.docswell.com/page/GJWXMMNWE2.jpg)

XDPで使える機能(関数)
●
bpf_map_{lookup,update,delete}_elem
○
●
bpf_fib_lookup
○
●
●
eBPF Mapの参照、更新、削除
FIB(Forwarding Information Base、ルーティングテーブル )の参照
bpf_xdp_adjust_head
○
パケットデータの先頭をずらす
○
encap/decapで使う
bpf_xdp_adjust_tail
○
パケットデータの末尾をずらす
○
パケットのヘッダだけ欲しいときに使うらしい (例: XFLAG ペイロードカッター )


# Page. 5

![Page Image](https://bcdn.docswell.com/page/4EZ6QQ32E3.jpg)

XDPで使える機能(関数)
●
●
bpf_xdp_adjust_meta
○
パケットデータの先頭にメタデータの領域を確保する
○
XDP_PASS後にtc-bpfでskb-&gt;markに入れてtcやiptablesと連携するのによく使う
○
ちなみにvirtio_netなど非対応NICが多いので注意
○
■ xdp_set_data_meta_invalidでdriversフォルダをgrepするとわかる
■ virtio_netのパッチはある
4.18まではVLANのパケットだと動かなかったが 4.19から直ってる
bpf_tail_call
○
別のプログラムを呼んで引き続きパケットを処理させる
○
xdpcapのようなキャプチャ用のプログラムや、メトリクス収集用、フィルタだけ先にやりたいので独
立させるなどの用途がある
○
プログラムの命令数制限が緩和されたのと有限ループがサポートされたのでプログラムが大きくて
渋々分けてtail_callというのはなくなりそう


# Page. 6

![Page Image](https://bcdn.docswell.com/page/Y76266Z6EV.jpg)

XDPで使えるeBPF Mapの種類
●
普通のMap
○
○
○
○
○
○
●
Map in Map
○
○
●
BPF_MAP_TYPE_ARRAY_OF_MAPS
BPF_MAP_TYPE_HASH_OF_MAPS
特殊なMap
○
○
○
○
○
○
●
BPF_MAP_TYPE_HASH
BPF_MAP_TYPE_ARRAY
BPF_MAP_TYPE_PERCPU_HASH: PERCPUなのでロックがなくなり性能が良い
BPF_MAP_TYPE_PERCPU_ARRAY
BPF_MAP_TYPE_LRU_HASH: LRU(マップが溢れたときにあまり使われないデータから消してくれる)
BPF_MAP_TYPE_LRU_PERCPU_HASH
BPF_MAP_TYPE_LPM_TRIE: ルートテーブルのようなテーブルを作りたいときに使う
BPF_MAP_TYPE_PROG_ARRAY: bpf_tail_callで使う
BPF_MAP_TYPE_PERF_EVENT_ARRAY: ユーザスペースに対してイベントを送りたいときに使う
BPF_MAP_TYPE_DEVMAP: XDP_REDIRECTで別のNICにパケットを渡すときに使う
BPF_MAP_TYPE_CPUMAP: XDP_REDIRECTで別のCPUにパケットを渡すときに使う
BPF_MAP_TYPE_XSKMAP: AF_XDPで使う
使い方はLinuxの samples/bpf


# Page. 7

![Page Image](https://bcdn.docswell.com/page/G75266W574.jpg)

開発の流れ
1.
わりと制限のあるCでソースコードを書く
2.
LLVMを使ってバイトコードにコンパイル
3.
コンパイルしたオブジェクトファイルをNICにアタッチ


# Page. 8

![Page Image](https://bcdn.docswell.com/page/9J24MMQG7R.jpg)

わりと制限のあるC
●
命令数制限
○
4.13までは4096
○
4.14から128K https://patchwork.ozlabs.org/patch/798665/
○
5.3から1M https://patchwork.ozlabs.org/patch/1073794/
○
※iproute2でロードしたときは今のところ、常に 4096まで
https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/lib/bpf.c?h=v5.4.0&amp;#n305
●
●
ループ制限
○
無限ループは禁止
○
5.2から有限ループ OK https://lwn.net/Articles/794934/
○
5.1まではunrollする必要がある ←プログラムサイズが大きくなりがち
その他
○
到達不可能な命令がないこと
○
有効なメモリにのみアクセスする（明示的に有効かどうかのチェックが必要）


# Page. 9

![Page Image](https://bcdn.docswell.com/page/DEYMXXWGEM.jpg)

コンパイル方法
●
●
シンプルなプログラムの場合
○
clang -O2 -target bpf -c example.c -o example.o
○
ただし、 linux/if_ether.h などをincludeしたらエラーになるため、ほぼ使えない
実用的なプログラムの場合
○
clang -I./include -DDEBUG -D__KERNEL__ -Wno-unused-value -Wno-pointer-sign
-Wno-compare-distinct-pointer-types -O2 -emit-llvm -c -g src/example.c -o -| llc -march=bpf
-filetype=obj -o src/example.o
○
●
サンプル https://github.com/higebu/ebpf-template
BCCの場合はソースを読み込むのが普通
○
詳細はリンク先参照
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 10

![Page Image](https://bcdn.docswell.com/page/VJNW1198J8.jpg)

テスト
●
BPF_PROG_TEST_RUNを使うと実際にNICにアタッチすることなくテストすること
ができる
●
libbpfを使った場合の例
○
●
https://github.com/higebu/ebpf-template/blob/master/test/test_xdp.c
ただし、カーネルのバージョンや、NICのドライバによって、対応している機能が異
なっていたり、特有のバグがあったりするので、本番で動かす前には必ず本番と同
じ環境でテストする
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 11

![Page Image](https://bcdn.docswell.com/page/YE9X552X73.jpg)

デバッグ方法
●
llvm-objdump -S --no-show-raw-insn example.o
○
Verifierに怒られたときはとりあえずこれ
○
clangでコンパイルするときに -g を付けていればバイトコードに
対応したソースコードも表示される
●
bpf_trace_printk()
○
性能に影響があるので、本番用のプログラムでは実行されな
いようにする
○
普段は trace-cmd record -e &#039;xdp:*&#039; -O trace_printk という
感じで出力された trace.dat をkernelsharkで見ている
○
trace-cmd stream は動かないことが多い。。。
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 12

![Page Image](https://bcdn.docswell.com/page/GE82YY59ED.jpg)

アタッチの前に気をつけること
●
本番では /proc/sys/net/core/bpf_jit_enable を 1 にしておく
●
フォワーディングするプログラムでは /proc/sys/net/ipv4.ip_forward や
/proc/sys/net/ipv6/conf/all/forwarding を 1 にしておく
●
ethtool -L eth0 combined 2 のようにしてNICのキューの数を調整しておく
●
ethtool -kで有効なオフロード機能を確認し、-Kでオフにしておく
●
MapはLocked Memoryを使うため、ulimit -l unlimitedやsystemdのunitファイル
でLimitMEMLOCK=infinityしておく（デフォルトは64KB）
●
オブジェクトをPinしたいときはbpffsをマウントしておく
mount bpffs /sys/fs/bpf -t bpf
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 13

![Page Image](https://bcdn.docswell.com/page/LEL244YM7R.jpg)

アタッチ/デタッチ
●
iproute2の場合
○
○
●
libbpfの場合
○
○
●
ip link set dev eth0 xdp obj example.o sec xdp_prog
ip link set dev eth0 xdp off
bpf_prog_load()でロードして、 bpf_set_link_xdp_fd()でアタッチ/デタッチ
参考
https://github.com/xdp-project/xdp-tutorial/blob/master/basic01-xdp-pass/xdp_pass_user.c
bpftoolの場合(5.4以上 https://patchwork.ozlabs.org/cover/1145981/
○
○
○
○
bpftool prog load ./example.o /sys/fs/bpf/prog
■ CONFIG_DEBUG_INFO_BTF=yなカーネルでないと libbpfのエラー(22)が表示されるが
ロードはされる
bpftool prog list でidを確認
bpftool net attach xdp id 10 dev eth0
bpftool net detach xdp dev eth0
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 14

![Page Image](https://bcdn.docswell.com/page/4JM8KKN6JW.jpg)

アタッチ/デタッチ
●
●
その他
○ BCC
■ 便利なマクロなどが定義されていて、少しプログラムを書きやすい
■ トレーシング方面で使われている
■ 新機能を追えてないことがあるので注意
○ iovisor/gobpf
■ Go言語で書かれた BCCのラッパー
■ cgoを使うことになるのと新機能を追えてないことがあるので注意
○ newtools/ebpf
■ pure Goで、libbpfと同様のことができるライブラリ
■ libbpf経由でなく、直接 syscallを実行してロードしたりアタッチしたり Mapの読み書きをしたりで
きる
おすすめはbpftool、またはCなどからlibbpfを使う方法で、 CプレーンをGoで書く場合は、
newtools/ebpf
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 15

![Page Image](https://bcdn.docswell.com/page/PJR5XXDNE9.jpg)

パケットキャプチャ
●
問題が起きたときやデバッグのために XDPで処理されたパケットをキャプチャしたくなりますが、カーネル
が処理する前に落としたり、返したりしてしまうので、 tcpdumpでは追えない
●
そこで、 xdpcap(https://github.com/cloudflare/xdpcap) を使う
●
詳しくはリンク先を参照
●
Wiresharkで見ると、プログラムのリターンコードもわかって便利
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 16

![Page Image](https://bcdn.docswell.com/page/PEXK6618JX.jpg)

コード解説（XDP編）
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 17

![Page Image](https://bcdn.docswell.com/page/3EK5112LJD.jpg)

コード解説
大変申し訳ありませんが、動くコードを実装
できませんでした🙇🙇🙇
※開発はアルバイトで来ている東北学院大学3年生の早坂彪流さ
んにご協力いただきました。
ありがとうございました🙇🙇🙇
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 18

![Page Image](https://bcdn.docswell.com/page/L73KQQ4675.jpg)

コード解説
Endは動くのでEnd部分の解説をします
ソー
ス:https://github.com/takehaya/srv6-gtp/b
lob/feature/t_m_GTP4_D/src/srv6.c
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 19

![Page Image](https://bcdn.docswell.com/page/87D399QMJG.jpg)

コード解説
パケットの先頭と末尾のポインタ
ヘッダのパース
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 20

![Page Image](https://bcdn.docswell.com/page/VJP4ZZLQ78.jpg)

コード解説
パケットの先頭と末尾のポインタ
ヘッダのパース
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 21

![Page Image](https://bcdn.docswell.com/page/2EVXWWQPJQ.jpg)

コード解説
IPv6で、nexthdrがNEXTHDR_ROUTING
で、SEG6_LOCAL_ACTION_END
のときにaction_end()を実行
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 22

![Page Image](https://bcdn.docswell.com/page/57GVDDWQ7L.jpg)

コード解説(End)
SRヘッダのパースと内容チェック
segmentのパース
パケット書き換え及び REDIRECT
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 23

![Page Image](https://bcdn.docswell.com/page/4EQ6113WEP.jpg)

コード解説(REDIRECT辺り)
bpf_fib_lookupしてる
REDIRECT
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 24

![Page Image](https://bcdn.docswell.com/page/KJ44RR11J1.jpg)

コード解説(bpf_fib_lookup辺り)
これが動かない
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 25

![Page Image](https://bcdn.docswell.com/page/LE14QQG5EG.jpg)

コード解説
プルリクエスト、アドバイス、お待ちしており
ます🙇🙇🙇
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 26

![Page Image](https://bcdn.docswell.com/page/GEWXMMKW72.jpg)

XDPの開発でつらかったところ
●
ロード時のエラーがわかりにくい
reference to missing symbolなどよくある
●
使っているカーネルのバージョンによってエラーの箇所が変わる
●
bpf_trace_printkを足しただけでロードできなくなった
printkの行とは関係ない箇所でreference to missing symbolになる
●
netns内からbpffsをマウントできない→開発しづらい
●
bpf_fib_lookupが動かないときに原因がわかりにくい
v6のlookup結局動かなかった。。。
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 27

![Page Image](https://bcdn.docswell.com/page/47Z6QQZ273.jpg)

以下おまけ
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 28

![Page Image](https://bcdn.docswell.com/page/YJ6266867V.jpg)

最近のXDP関連の開発の様子
●
bpf: add bpf_ct_lookup_{tcp,udp}() helpers
○
●
xdp: Introduce bulking for non-map XDP_REDIRECT Accepted
○
●
●
●
●
●
bpf_redirect_mapの方がbpf_redirectより速かったが、差がなくなる
XDP in tx path RFC
Introduce the BPF dispatcher Accepted
xdp_flow: Flow offload to XDP RFC
virtio_net XDP offload RFC
Introduce XDP to ena
○
●
conntrack tableの参照ができるようになりそう
EC2のElastic Network AdapterのXDP対応
sfc: Add XDP support
○
SolarflareのNICのXDP対応


# Page. 29

![Page Image](https://bcdn.docswell.com/page/GJ526695J4.jpg)

XDPを使うときによく見る資料
●
●
●
●
Cilium BPF and XDP Reference Guide
Suricata eBPF and XDP
Linux Documantation/bpf
Linux samples/bpf
○
●
●
XDP Hands-On Tutorial
BPF Features by Linux Kernel Version
○
●
●
この機能どのバージョンから使える？というときに見る
Linux Observability with BPF(本) (sysdigのサイトに情報登録すると無料でダウン
ロードできる)
yunazuno.log
○
●
●
見るときは使うカーネルのバージョンに合わせて見る
日本語で検索すると大抵このブログがヒットする
@IT Berkeley Packet Filter（BPF）入門
あとはドライバなどのソースコードを見る。。。
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


# Page. 30

![Page Image](https://bcdn.docswell.com/page/LE3KQQY5E5.jpg)

EOF
パケット処理の独自実装や高速化手法の比較と実践｜ JANOG45＠札幌｜2020/01/24


