これは JANOG LT のフォローアップブログです。 Go+XDPな開発何も説明できなかったことに気がついたので書きました。
SRv6,GTPv1,XDPの大まかな説明は世の中に神な資料があるので特に説明はしません。
もしebpfとはなんぞなどの疑問がある方は
などを合わせて見ていただけるといいと思います。
TL;TR
- Go+XDPな開発をしたいなら
cilium/ebpf
を使うといい - https://github.com/takehaya/goxdp-templateという雛形を作ったので始めるときに参考にして欲しい。
GoでXDPをやるときの選択肢と最近の利点
Goを利用する際の開発においての選択肢は以下のようにいくつかあります。
..etc
自分はもしその中であればcilium/ebpfを利用した開発をお勧めしております。
いくつかの理由がありますが、まず他が微妙というのもあります。 上記にあげたnewtools/ebpf をcloudflareの中の人が作っていて、それをciliumで利用を使うとなったことで新しく移動したのが cilium/ebpfです。なので中の人が同じであります。 また、 dropbox/goebpfもありますが直近ではあまりコントリビュートされず、そもそもdropboxの中のひともcilium/ebpfにコントリビュートしてるので恐らく方針としてはこちらはもう下火になると思われます。 iovisor/gobpfはCGoなので互換性問題を考えるときに辛いと思います(これは個人の趣味ぽいですね...)
で、なぜお勧めするかというと BTF対応が一番進んでいて ciliumのような巨大な実績のあるプロダクトを参考に開発を進めることができるからというのが一番大きいです。また大きい会社がバックでコントリビュートしてるのも大きいでしょう。
例えばBTFの対応の一番見かけるパターンの話の例としては、今の最新の ebpf map においての定義は 以下のようなxdpcapの書き換えのようにに .maps
と書く必要があります。またトレーシングをやる人はCO-RE
の影響を受けるのでなおさらBTFが必要になるでしょう。実際 kernelの sample/bpf
を見ても全て今は .maps
に書き換わっています。
// https://github.com/cloudflare/xdpcap // old case // struct bpf_map_def SEC("maps") xdpcap_hook = { // .type = BPF_MAP_TYPE_PROG_ARRAY, \ // .key_size = sizeof(int), \ // .value_size = sizeof(int), \ // .max_entries = 5, \ // } struct xdpcap_hook { __uint(type, BPF_MAP_TYPE_PROG_ARRAY); __uint(key_size, sizeof(int)); __uint(value_size, sizeof(int)); __uint(max_entries, 5); } xdpcap_hook SEC(".maps");
また、ebpfを使う弱点の一例としてはバイナリ一つに落とすことができないのがあったと思います。これではせっかくのGoの利点が台無しです。
なので今まではなんとか github.com/rakyll/statik などでシリアライズをしてバイナリをgoのコードにつめてワンバイナリで嬉しいですね?とか言ってたわけです。(しかもビルドのタイミングは自分でmakeなりに書く必要があって本当に面倒)
しかし cilium/ebpfには bpf2goが入り go:generate
を使ってclangを叩いてビルドをしてコードに詰めて、それらをマップした構造体まで用意してくれるという便利機能が入りました。
bpf2goは今回のgoxdp-templateでは go:generate
の例で動いてるので参考になると思います。
ちなみにですが、激推ししてるけどまだまだダメなところもあります。例えばnewtoolsではできた innermap をelfから生成したり、ebpfmapに書き込む際に構造体のアライメント周りが粗雑になってたりしてるので定義して使うときにはいくつかのワークアラウンドを必要とするケースがありますのでそこは今後に期待というところでしょうか....
もしこれを使ってDplaneを開発するぞ!となったらxdp-tutorial などを見てDplane開発を進めるのが良いでしょう。
終わりに
今回JANOG初参加だったんですが(オンラインだとこれは参加したと言えるのかという気持ちですが...😇)勢いで出したLTがギリギリ通っててよかったです。
学生生活最後だったので現地開催でいきたかったんですが、、、行けるときに行っておくのは重要だなぁと思いました。
あとどこかの機会で自作SRv6+XDP Dplane: Vinberoで使ってるワークアラウンドとかブログネタにしたいなぁと思いました。 例えば
- 可変スタック上に乗る場合は ebpfmap を変数にして使うと便利
- loopsizeにおいての上限値制限は and演算 をすると便利
とかどこのブログにも載ってなさそうなネタだと思うので、もしきになる人がいたらコードを読んでください。
また、l3vpn exampleとかあるのでよければ気が向いた時にでも遊んでみてください。まだまだ荒削りなのでバグが(多分)あると思うんですが優しくissueに書いてくれると助かります。
ではでは。