Ifihan kukuru kan si BPF ati eBPF

Kaabo, Habr! A fẹ lati sọ fun ọ pe a ngbaradi iwe kan fun itusilẹ."Lainos Observability pẹlu BPF".

Ifihan kukuru kan si BPF ati eBPF
Niwọn igba ti ẹrọ foju BPF tẹsiwaju lati dagbasoke ati pe o nlo ni adaṣe ni iṣe, a ti tumọ nkan fun ọ ti n ṣapejuwe awọn agbara akọkọ rẹ ati ipo lọwọlọwọ.

Ni awọn ọdun aipẹ, awọn irinṣẹ siseto ati awọn imọ-ẹrọ ti di olokiki pupọ si isanpada fun awọn aropin ti ekuro Linux ni awọn ọran nibiti a ti nilo sisẹ soso iṣẹ-giga. Ọkan ninu awọn imọ-ẹrọ olokiki julọ ti iru yii ni a pe ekuro fori (ọpa ekuro) ati gba laaye, ni ikọja Layer nẹtiwọki ekuro, lati ṣe gbogbo sisẹ soso lati aaye olumulo. Sisẹ ekuro tun kan ṣiṣakoso kaadi nẹtiwọki lati aaye olumulo. Ni awọn ọrọ miiran, nigba ṣiṣẹ pẹlu kaadi nẹtiwọki kan, a gbẹkẹle awakọ naa aaye olumulo.

Nipa gbigbe iṣakoso kikun ti kaadi nẹtiwọọki si eto aaye olumulo kan, a dinku ekuro lori oke (iyipada ọrọ, sisẹ Layer nẹtiwọki, awọn idilọwọ, ati bẹbẹ lọ), eyiti o ṣe pataki pupọ nigbati o nṣiṣẹ ni awọn iyara ti 10Gb/s tabi ga julọ. Kernel fori pẹlu apapo awọn ẹya miiran (ipele processing) ati iṣatunṣe iṣẹ iṣọra (NUMA iṣiro, Sipiyu ipinya, ati bẹbẹ lọ) ni ibamu si awọn ipilẹ ti sisẹ nẹtiwọọki iṣẹ-giga ni aaye olumulo. Boya apẹẹrẹ apẹẹrẹ ti ọna tuntun yii si sisẹ apo jẹ DPDK lati Intel (Data ofurufu Development Kit), botilẹjẹpe awọn irinṣẹ ati imọ-ẹrọ miiran ti a mọ daradara wa, pẹlu Sisiko's VPP (Ṣiṣe Packet Vector), Netmap ati, dajudaju, Snabb.

Ṣiṣeto awọn ibaraẹnisọrọ nẹtiwọki ni aaye olumulo ni nọmba awọn aila-nfani:

  • Ekuro OS jẹ Layer abstraction fun awọn orisun ohun elo. Nitoripe awọn eto aaye olumulo ni lati ṣakoso awọn orisun wọn taara, wọn tun ni lati ṣakoso ohun elo tiwọn. Eyi nigbagbogbo tumọ si nini eto awọn awakọ tirẹ.
  • Nitoripe a nfi aaye kernel silẹ patapata, a tun n fi gbogbo iṣẹ ṣiṣe netiwọki silẹ ti ekuro ti pese. Awọn eto aaye olumulo gbọdọ tun mu awọn iṣẹ ṣiṣe ti o le ti pese tẹlẹ nipasẹ ekuro tabi ẹrọ ṣiṣe.
  • Awọn eto ṣiṣẹ ni ipo iyanrin, eyiti o ṣe idiwọ ibaraenisepo wọn ni pataki ati ṣe idiwọ wọn lati ṣepọ pẹlu awọn ẹya miiran ti ẹrọ iṣẹ.

Ni pataki, nigbati Nẹtiwọọki ba waye ni aaye olumulo, awọn anfani iṣẹ jẹ aṣeyọri nipasẹ gbigbe sisẹ soso lati ekuro si aaye olumulo. XDP ṣe deede idakeji: o gbe awọn eto Nẹtiwọọki lati aaye olumulo (awọn asẹ, awọn ipinnu, ipa-ọna, ati bẹbẹ lọ) sinu aaye ekuro. XDP gba wa laaye lati ṣe iṣẹ nẹtiwọọki kan ni kete ti soso kan ba lu wiwo nẹtiwọọki kan ati ṣaaju ki o to bẹrẹ gbigbe soke sinu eto inu nẹtiwọọki ekuro. Bi abajade, iyara processing apo pọ si ni pataki. Sibẹsibẹ, bawo ni ekuro ṣe gba olumulo laaye lati ṣiṣẹ awọn eto wọn ni aaye ekuro? Ṣaaju ki o to dahun ibeere yii, jẹ ki a wo kini BPF jẹ.

BPF ati eBPF

Pelu orukọ iruju, BPF (Berkeley Packet Filtering) jẹ, ni otitọ, awoṣe ẹrọ foju kan. Ẹrọ foju foju yii jẹ apẹrẹ ni akọkọ lati mu sisẹ soso, nitorinaa orukọ naa.

Ọkan ninu awọn irinṣẹ olokiki julọ nipa lilo BPF ni tcpdump. Nigba yiya awọn apo-iwe lilo tcpdump olumulo le pato ikosile lati àlẹmọ awọn apo-iwe. Awọn apo-iwe nikan ti o baamu ikosile yii ni yoo gba. Fun apẹẹrẹ, ọrọ naa "tcp dst port 80” tọka si gbogbo awọn apo-iwe TCP ti o de lori ibudo 80. Olupilẹṣẹ naa le dinku ikosile yii nipa yiyipada rẹ si BPF bytecode.

$ sudo tcpdump -d "tcp dst port 80"
(000) ldh [12] (001) jeq #0x86dd jt 2 jf 6
(002) ldb [20] (003) jeq #0x6 jt 4 jf 15
(004) ldh [56] (005) jeq #0x50 jt 14 jf 15
(006) jeq #0x800 jt 7 jf 15
(007) ldb [23] (008) jeq #0x6 jt 9 jf 15
(009) ldh [20] (010) jset #0x1fff jt 15 jf 11
(011) ldxb 4*([14]&0xf)
(012) ldh [x + 16] (013) jeq #0x50 jt 14 jf 15
(014) ret #262144
(015) ret #0

Eyi ni ohun ti eto ti o wa loke ṣe ni ipilẹ:

  • Ilana (000): Kojọpọ apo-iwe ni aiṣedeede 12, bi ọrọ 16-bit, sinu akojo. Aiṣedeede 12 ni ibamu si ethertype ti apo-iwe naa.
  • Ilana (001): ṣe afiwe iye ti o wa ninu ikojọpọ pẹlu 0x86dd, iyẹn ni, pẹlu iye ethertype fun IPv6. Ti abajade ba jẹ otitọ, lẹhinna counter eto lọ si itọnisọna (002), ati bi ko ba ṣe bẹ, lẹhinna si (006).
  • Ilana (006): ṣe afiwe iye pẹlu 0x800 (iye ethertype fun IPv4). Ti idahun ba jẹ otitọ, lẹhinna eto naa lọ si (007), ti kii ba ṣe bẹ, lẹhinna si (015).

Ati bẹbẹ lọ titi ti eto sisẹ apo-iwe yoo pada abajade kan. Eyi nigbagbogbo jẹ Boolean. Pada a ti kii-odo iye (ilana (014)) tumo si wipe awọn soso ti a gba, ati ki o pada a odo iye (ilana (015)) tumo si wipe awọn soso ti a ko ti gba.

Ẹrọ foju BPF ati bytecode rẹ ni a dabaa nipasẹ Steve McCann ati Van Jacobson ni ipari ọdun 1992 nigbati iwe wọn ti tẹjade BSD Packet Ajọ: Tuntun faaji fun Olumulo-Ipele Packet Yaworan, imọ-ẹrọ yii ni akọkọ gbekalẹ ni apejọ Usenix ni igba otutu ti 1993.

Nitori BPF jẹ ẹrọ foju kan, o ṣalaye agbegbe ti awọn eto nṣiṣẹ. Ni afikun si bytecode, o tun ṣalaye awoṣe iranti ipele (awọn itọnisọna fifuye ni a lo taara si ipele), awọn iforukọsilẹ (A ati X; ikojọpọ ati awọn iforukọsilẹ atọka), ibi ipamọ iranti ibere, ati iṣiro eto aitọ. O yanilenu, BPF bytecode jẹ apẹrẹ lẹhin Motorola 6502 ISA. Bi Steve McCann ranti ninu rẹ plenary iroyin ni Sharkfest '11, o jẹ faramọ pẹlu Kọ 6502 lati rẹ ile-iwe giga ọjọ siseto lori Apple II, ki o si yi imo nfa iṣẹ rẹ nse BPF bytecode.

Atilẹyin BPF jẹ imuse ni ekuro Linux ni awọn ẹya v2.5 ati ti o ga julọ, ti a ṣafikun ni pataki nipasẹ awọn akitiyan ti Jay Schullist. Koodu BPF ko yipada titi di ọdun 2011, nigbati Eric Dumaset ṣe atunto onitumọ BPF lati ṣiṣẹ ni ipo JIT (Orisun: JIT fun awọn asẹ apo). Lẹhin eyi, ekuro, dipo itumọ BPF bytecode, le ṣe iyipada awọn eto BPF taara si faaji ibi-afẹde: x86, ARM, MIPS, ati bẹbẹ lọ.

Nigbamii, ni 2014, Alexey Starovoitov dabaa ilana JIT tuntun fun BPF. Ni otitọ, JIT tuntun yii di faaji ti o da lori BPF tuntun ati pe a pe ni eBPF. Mo ro pe awọn VM mejeeji wa papọ fun igba diẹ, ṣugbọn sisẹ soso lọwọlọwọ ti wa ni imuse ti o da lori eBPF. Ni otitọ, ni ọpọlọpọ awọn apẹẹrẹ ti awọn iwe-ipamọ ode oni, BPF ni oye lati jẹ eBPF, ati BPF kilasika ni a mọ loni bi cBPF.

eBPF gbooro ẹrọ foju BPF Ayebaye ni awọn ọna pupọ:

  • Da lori igbalode 64-bit faaji. eBPF nlo awọn iforukọsilẹ 64-bit ati pe o pọ si nọmba awọn iforukọsilẹ ti o wa lati 2 (accumulator ati X) si 10. eBPF tun pese awọn afikun opcodes (BPF_MOV, BPF_JNE, BPF_CALL...).
  • Yasọtọ lati inu eto-ipilẹ nẹtiwọki nẹtiwọki. BPF ti so si awoṣe data ipele. Niwọn igba ti o ti lo fun sisẹ apo-iwe, koodu rẹ wa ninu eto ipilẹ ti o pese awọn ibaraẹnisọrọ nẹtiwọọki. Sibẹsibẹ, ẹrọ foju eBPF ko ni so mọ awoṣe data ati pe o le ṣee lo fun idi eyikeyi. Nitorinaa, ni bayi eto eBPF le ni asopọ si aaye tracepoint tabi kprobe. Eyi ṣii ọna lati lọ si ohun elo eBPF, itupalẹ iṣẹ, ati ọpọlọpọ awọn ọran lilo miiran ni aaye ti awọn eto abẹlẹ ekuro miiran. Bayi koodu eBPF wa ni ọna tirẹ: kernel/bpf.
  • Awọn ile itaja data agbaye ti a pe ni Maps. Awọn maapu jẹ awọn ile itaja iye-bọtini ti o mu ki paṣipaarọ data ṣiṣẹ laarin aaye olumulo ati aaye ekuro. eBPF n pese awọn oriṣi awọn maapu pupọ.
  • Awọn iṣẹ keji. Ni pataki, lati tun package kọ, ṣe iṣiro checksum, tabi ẹda oniye kan package. Awọn iṣẹ wọnyi nṣiṣẹ inu ekuro ati kii ṣe awọn eto aaye olumulo. O tun le ṣe awọn ipe eto lati awọn eto eBPF.
  • Pari awọn ipe. Iwọn eto ni eBPF ni opin si 4096 awọn baiti. Ẹya ipe iru gba eto eBPF laaye lati gbe iṣakoso lọ si eto eBPF tuntun ati nitorinaa fori aropin yii (to awọn eto 32 le ni asopọ ni ọna yii).

eBPF: apẹẹrẹ

Awọn apẹẹrẹ pupọ lo wa fun eBPF ninu awọn orisun ekuro Linux. Wọn wa ni awọn ayẹwo/bpf/. Lati ṣajọ awọn apẹẹrẹ wọnyi, tẹ sii nirọrun:

$ sudo make samples/bpf/

Emi kii yoo kọ apẹẹrẹ tuntun fun eBPF funrarami, ṣugbọn yoo lo ọkan ninu awọn ayẹwo ti o wa ni awọn ayẹwo/bpf/. Emi yoo wo diẹ ninu awọn ẹya ti koodu naa ki o ṣalaye bi o ṣe n ṣiṣẹ. Fun apẹẹrẹ, Mo yan eto naa tracex4.

Ni gbogbogbo, kọọkan ninu awọn apẹẹrẹ ni awọn ayẹwo/bpf/ ni awọn faili meji. Fun idi eyi:

  • tracex4_kern.c, ni koodu orisun lati wa ni pipa ni ekuro bi eBPF bytecode.
  • tracex4_user.c, ni eto lati aaye olumulo.

Ni idi eyi, a nilo lati ṣajọ tracex4_kern.c to eBPF bytecode. Lọwọlọwọ ninu gcc ko si ẹhin fun eBPF. O da, clang le jade eBPF bytecode. Makefile awọn lilo clang fun akopo tracex4_kern.c si faili ohun.

Mo mẹnuba loke pe ọkan ninu awọn ẹya ti o nifẹ julọ ti eBPF jẹ awọn maapu. tracex4_kern ṣe alaye maapu kan:

struct pair {
    u64 val;
    u64 ip;
};  

struct bpf_map_def SEC("maps") my_map = {
    .type = BPF_MAP_TYPE_HASH,
    .key_size = sizeof(long),
    .value_size = sizeof(struct pair),
    .max_entries = 1000000,
};

BPF_MAP_TYPE_HASH jẹ ọkan ninu awọn ọpọlọpọ awọn orisi ti awọn kaadi funni nipasẹ eBPF. Ni idi eyi, o kan hash. O le tun ti ṣe akiyesi ipolowo kan SEC("maps"). SEC jẹ Makiro ti a lo lati ṣẹda apakan tuntun ti faili alakomeji kan. Ni otitọ, ninu apẹẹrẹ tracex4_kern Awọn apakan meji miiran ti wa ni asọye:

SEC("kprobe/kmem_cache_free")
int bpf_prog1(struct pt_regs *ctx)
{   
    long ptr = PT_REGS_PARM2(ctx);

    bpf_map_delete_elem(&my_map, &ptr); 
    return 0;
}
    
SEC("kretprobe/kmem_cache_alloc_node") 
int bpf_prog2(struct pt_regs *ctx)
{
    long ptr = PT_REGS_RC(ctx);
    long ip = 0;

    // получаем ip-адрес вызывающей стороны kmem_cache_alloc_node() 
    BPF_KRETPROBE_READ_RET_IP(ip, ctx);

    struct pair v = {
        .val = bpf_ktime_get_ns(),
        .ip = ip,
    };
    
    bpf_map_update_elem(&my_map, &ptr, &v, BPF_ANY);
    return 0;
}   

Awọn iṣẹ meji wọnyi gba ọ laaye lati pa titẹ sii lati maapu naa (kprobe/kmem_cache_free) ki o si fi titẹ sii titun kun maapu naa (kretprobe/kmem_cache_alloc_node). Gbogbo awọn orukọ iṣẹ ti a kọ sinu awọn lẹta nla ni ibamu si awọn macros ti a ṣalaye ninu bpf_helpers.h.

Ti MO ba ju awọn apakan ti faili ohun naa silẹ, Mo yẹ ki o rii pe awọn apakan tuntun wọnyi ti ni asọye tẹlẹ:

$ objdump -h tracex4_kern.o

tracex4_kern.o: file format elf64-little

Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000000 0000000000000000 0000000000000000 00000040 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 kprobe/kmem_cache_free 00000048 0000000000000000 0000000000000000 00000040 2**3
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
2 kretprobe/kmem_cache_alloc_node 000000c0 0000000000000000 0000000000000000 00000088 2**3
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
3 maps 0000001c 0000000000000000 0000000000000000 00000148 2**2
CONTENTS, ALLOC, LOAD, DATA
4 license 00000004 0000000000000000 0000000000000000 00000164 2**0
CONTENTS, ALLOC, LOAD, DATA
5 version 00000004 0000000000000000 0000000000000000 00000168 2**2
CONTENTS, ALLOC, LOAD, DATA
6 .eh_frame 00000050 0000000000000000 0000000000000000 00000170 2**3
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

O tun wa tracex4_user.c, akọkọ eto. Ni ipilẹ, eto yii tẹtisi awọn iṣẹlẹ kmem_cache_alloc_node. Nigbati iru iṣẹlẹ ba waye, koodu eBPF ti o baamu wa ni ṣiṣe. Awọn koodu fi awọn IP abuda ti awọn ohun sinu kan maapu, ati awọn ohun ti wa ni ki o si looped nipasẹ awọn akọkọ eto. Apeere:

$ sudo ./tracex4
obj 0xffff8d6430f60a00 is 2sec old was allocated at ip ffffffff9891ad90
obj 0xffff8d6062ca5e00 is 23sec old was allocated at ip ffffffff98090e8f
obj 0xffff8d5f80161780 is 6sec old was allocated at ip ffffffff98090e8f

Bawo ni eto aaye olumulo ati eto eBPF ṣe ni ibatan? Lori ipilẹṣẹ tracex4_user.c kojọpọ faili ohun kan tracex4_kern.o lilo iṣẹ naa load_bpf_file.

int main(int ac, char **argv)
{
    struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
    char filename[256];
    int i;

    snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);

    if (setrlimit(RLIMIT_MEMLOCK, &r)) {
        perror("setrlimit(RLIMIT_MEMLOCK, RLIM_INFINITY)");
        return 1;
    }

    if (load_bpf_file(filename)) {
        printf("%s", bpf_log_buf);
        return 1;
    }

    for (i = 0; ; i++) {
        print_old_objects(map_fd[1]);
        sleep(1);
    }

    return 0;
}

Nipa ṣiṣe load_bpf_file Awọn iwadii asọye ninu faili eBPF ti wa ni afikun si /sys/kernel/debug/tracing/kprobe_events. Bayi a gbọ fun awọn iṣẹlẹ wọnyi ati pe eto wa le ṣe ohun kan nigbati wọn ba ṣẹlẹ.

$ sudo cat /sys/kernel/debug/tracing/kprobe_events
p:kprobes/kmem_cache_free kmem_cache_free
r:kprobes/kmem_cache_alloc_node kmem_cache_alloc_node

Gbogbo awọn eto miiran ti o wa ninu apẹẹrẹ/bpf/ ti wa ni igbekale bakanna. Wọn nigbagbogbo ni awọn faili meji ninu:

  • XXX_kern.c: eBPF eto.
  • XXX_user.c: akọkọ eto.

Eto eBPF n ṣe idanimọ awọn maapu ati awọn iṣẹ ti o ni nkan ṣe pẹlu apakan kan. Nigbati ekuro ba ṣejade iṣẹlẹ kan ti iru kan (fun apẹẹrẹ, tracepoint), awọn iṣẹ dè ti wa ni ṣiṣe. Awọn kaadi naa pese ibaraẹnisọrọ laarin eto ekuro ati eto aaye olumulo.

ipari

Nkan yii jiroro lori BPF ati eBPF ni awọn ofin gbogbogbo. Mo mọ pe alaye pupọ ati awọn orisun wa nipa eBPF loni, nitorinaa Emi yoo ṣeduro awọn orisun diẹ diẹ sii fun ikẹkọ siwaju

Mo ṣeduro kika:

orisun: www.habr.com

Fi ọrọìwòye kun