eBPFスタックトレースのコマンドポインタに同じIPが2回あり、関係のない奇妙なIPを持つeBPFプログラムが含まれているのはなぜですか?

eBPFスタックトレースのコマンドポインタに同じIPが2回あり、関係のない奇妙なIPを持つeBPFプログラムが含まれているのはなぜですか?

eBPFプログラムからカーネルスタックトレースを取得すると、重複して奇妙なエントリが表示されます。誰かがこれを説明できますか?

まず、関連するeBPFプログラムの断片から始めましょう。次のようにスタックトレースグラフを宣言します。

struct {
    __uint(type, BPF_MAP_TYPE_STACK_TRACE);
    __type(key, u32);
    __type(value, stack);
    __uint(max_entries, 1 << 14);
} stacks SEC(".maps");

後で添付するeBPFプログラムは、cap_capable次のようにスタックトレースを保存し、スタックトレースIDをユーザースペースに送信します。

kstackid = bpf_get_stackid(ctx, &stacks, 0);

Goのユーザースペースの観点からCiliumを使用すると非常に便利です。ebpf Goモジュール。特定のスタックトレースへのコマンドポインタを読み取るには、次の手順を実行します。

ips := make([]uint64, MaxStackDepth)
if err := objs.Stacks.Lookup(event.Kstackid, ips); err != nil {
    slog.Error("looking up kernel stack trace", "error", err)
    continue
}
l := len(ips)
for idx, ip := range ips {
    if ip == 0 {
        l = idx
        break
    }
}
ev := Event{
    bpfCapevent: event,
    KernelStack: ips[:l],
}

データを使用してコマンドポインタを解析すると、/proc/kallsymsIPも表示する次のスタックが作成されます。

bpf_prog_47f71ae01d77a0b5_fentry_cap_capable ffffffffc00860ed
bpf_prog_47f71ae01d77a0b5_fentry_cap_capable ffffffffc00860ed
udp_tunnel_nic_init_module ffffffffc0e2004f
cap_capable ffffffff9ea9b1a5
  1. なぜそこにいるのですか?二つFentryのIPアドレスは何ですかcap_capable?どちらも同じ返送先ですが、ここで何が起こっているのでしょうか。
  2. cap_capable私のeBPFプログラム間の中間機能は何ですかudp_tunnel_nic_init_module?誤解があると思いますか?トランポリンと関連があるのでしょうか…?

関連情報