Introduzzjoni qasira għall-BPF u l-eBPF

Hello, Habr! Nixtiequ ninfurmawkom li qed inħejju ktieb għall-ħruġ."Osservabilità tal-Linux b'BPF".

Introduzzjoni qasira għall-BPF u l-eBPF
Peress li l-magna virtwali BPF tkompli tevolvi u tintuża b'mod attiv fil-prattika, ittraduċijna għalik artiklu li jiddeskrivi l-kapaċitajiet ewlenin tagħha u l-istat attwali.

F'dawn l-aħħar snin, l-għodod u t-tekniki tal-ipprogrammar saru dejjem aktar popolari biex jikkumpensaw għal-limitazzjonijiet tal-qalba tal-Linux f'każijiet fejn ikun meħtieġ ipproċessar ta 'pakketti ta' prestazzjoni għolja. Waħda mit-tekniki l-aktar popolari ta 'dan it-tip tissejjaħ bypass tal-qalba (bypass tal-kernel) u jippermetti, billi jinjora s-saff tan-netwerk tal-kernel, li jwettaq l-ipproċessar kollu tal-pakkett mill-ispazju tal-utent. It-tneħħija tal-qalba tinvolvi wkoll il-kontroll tal-kard tan-netwerk minn spazju għall-utent. Fi kliem ieħor, meta naħdmu ma 'karta tan-netwerk, aħna niddependu fuq is-sewwieq spazju għall-utent.

Billi tittrasferixxi l-kontroll sħiħ tal-karta tan-netwerk għal programm ta 'spazju ta' l-utent, innaqqsu l-overhead tal-qalba (bdil tal-kuntest, ipproċessar ta 'saff tan-netwerk, interruzzjonijiet, eċċ.), li huwa pjuttost importanti meta taħdem b'veloċitajiet ta' 10Gb/s jew ogħla. Bypass tal-kernel flimkien ma' taħlita ta' karatteristiċi oħra (ipproċessar tal-lott) u rfinar bir-reqqa tal-prestazzjoni (Kontabilità NUMA, Iżolament tas-CPU, eċċ.) jikkorrispondu mal-prinċipji fundamentali tal-ipproċessar tan-netwerk ta 'prestazzjoni għolja fl-ispazju tal-utent. Forsi eżempju eżemplari ta 'dan l-approċċ ġdid għall-ipproċessar tal-pakketti huwa DPDK minn Intel (Kit ta' Żvilupp tal-Pjan tad-Data), għalkemm hemm għodod u tekniki oħra magħrufa, inkluż il-VPP (Vector Packet Processing) ta' Cisco, Netmap u, ovvjament, snab.

L-organizzazzjoni tal-interazzjonijiet tan-netwerk fl-ispazju tal-utent għandha numru ta 'żvantaġġi:

  • Il-qalba tal-OS hija saff ta' astrazzjoni għar-riżorsi tal-ħardwer. Minħabba li l-programmi spazjali tal-utent iridu jimmaniġġjaw ir-riżorsi tagħhom direttament, iridu wkoll jimmaniġġjaw il-ħardwer tagħhom stess. Dan spiss ifisser li jkollok tipprogramma s-sewwieqa tiegħek stess.
  • Minħabba li qed inċedu għal kollox l-ispazju tal-kernel, qed inċedu wkoll il-funzjonalità tan-netwerking kollha pprovduta mill-kernel. Programmi ta' spazju għall-utent iridu jimplimentaw mill-ġdid funzjonijiet li jistgħu jkunu diġà pprovduti mill-kernel jew mis-sistema operattiva.
  • Il-programmi joperaw fil-modalità sandbox, li tillimita serjament l-interazzjoni tagħhom u ma tħallihomx jintegraw ma 'partijiet oħra tas-sistema operattiva.

Essenzjalment, meta jsir netwerking fl-ispazju tal-utent, il-kisbiet fil-prestazzjoni jinkisbu billi l-ipproċessar tal-pakketti jiġi mċaqlaq mill-qalba għall-ispazju tal-utent. XDP jagħmel eżattament l-oppost: iċċaqlaq il-programmi tan-netwerking mill-ispazju tal-utent (filtri, resolvers, routing, eċċ.) għall-ispazju tal-kernel. XDP jippermettilna nwettqu funzjoni tan-netwerk hekk kif pakkett jolqot interface tan-netwerk u qabel ma jibda jimxi 'l fuq fis-subsistema tan-netwerk tal-kernel. Bħala riżultat, il-veloċità tal-ipproċessar tal-pakketti tiżdied b'mod sinifikanti. Madankollu, kif il-kernel jippermetti lill-utent jesegwixxi l-programmi tiegħu fl-ispazju tal-kernel? Qabel ma twieġeb din il-mistoqsija, ejja nħarsu lejn x'inhu BPF.

BPF u eBPF

Minkejja l-isem konfuż, BPF (Berkeley Packet Filtering) huwa, fil-fatt, mudell ta 'magna virtwali. Din il-magna virtwali kienet oriġinarjament iddisinjata biex timmaniġġja l-iffiltrar tal-pakketti, għalhekk l-isem.

Waħda mill-aktar għodod famużi li jużaw BPF hija tcpdump. Meta jinqabad pakketti bl-użu tcpdump l-utent jista' jispeċifika espressjoni biex jiffiltra l-pakketti. Se jinqabdu biss pakketti li jaqblu ma' din l-espressjoni. Pereżempju, l-espressjoni “tcp dst port 80” tirreferi għall-pakketti TCP kollha li jaslu fuq il-port 80. Il-kompilatur jista’ jqassar din l-espressjoni billi jikkonvertiha f’bytecode BPF.

$ 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

Dan huwa dak li l-programm ta 'hawn fuq bażikament jagħmel:

  • Istruzzjoni (000): Tgħabbi l-pakkett f'offset 12, bħala kelma ta '16-il bit, fl-akkumulatur. Offset 12 jikkorrispondi għall-ethertype tal-pakkett.
  • Istruzzjoni (001): tqabbel il-valur fl-akkumulatur ma '0x86dd, jiġifieri, mal-valur ethertype għall-IPv6. Jekk ir-riżultat huwa minnu, allura l-counter tal-programm imur għall-istruzzjoni (002), u jekk le, imbagħad għal (006).
  • Istruzzjoni (006): tqabbel il-valur ma '0x800 (valur ethertype għal IPv4). Jekk it-tweġiba hija vera, allura l-programm imur għal (007), jekk le, allura għal (015).

U hekk sakemm il-programm ta 'filtrazzjoni tal-pakketti jirritorna riżultat. Dan huwa normalment Boolean. Ir-ritorn ta' valur mhux żero (struzzjoni (014)) ifisser li l-pakkett ġie aċċettat, u r-ritorn ta' valur żero (struzzjoni (015)) ifisser li l-pakkett ma ġiex aċċettat.

Il-magna virtwali BPF u l-bytecode tagħha ġew proposti minn Steve McCann u Van Jacobson fl-aħħar tal-1992 meta l-karta tagħhom ġiet ippubblikata BSD Packet Filter: Arkitettura Ġdida għall-Qbid tal-Pakketti fil-Livell tal-Utent, din it-teknoloġija ġiet ippreżentata għall-ewwel darba fil-konferenza Usenix fix-xitwa tal-1993.

Minħabba li BPF hija magna virtwali, tiddefinixxi l-ambjent li fih jaħdmu l-programmi. Minbarra l-bytecode, jiddefinixxi wkoll il-mudell tal-memorja tal-lott (l-istruzzjonijiet tat-tagħbija huma applikati b'mod impliċitu għall-lott), reġistri (A u X; reġistri tal-akkumulatur u tal-indiċi), ħażna tal-memorja scratch, u counter tal-programm impliċitu. Interessanti, il-bytecode BPF kien immudellat wara l-Motorola 6502 ISA. Kif fakkar Steve McCann fil tiegħu rapport plenarju f'Sharkfest '11, kien familjari mal-build 6502 mill-ipprogrammar tal-ġranet tal-iskola sekondarja tiegħu fuq l-Apple II, u dan l-għarfien influwenza x-xogħol tiegħu li jfassal il-bytecode BPF.

L-appoġġ tal-BPF huwa implimentat fil-kernel tal-Linux fil-verżjonijiet v2.5 u ogħla, miżjud prinċipalment bl-isforzi ta 'Jay Schullist. Il-kodiċi BPF baqa' ma nbidilx sal-2011, meta Eric Dumaset iddisinja mill-ġdid l-interpretu BPF biex jaħdem fil-modalità JIT (Sors: JIT għall-filtri tal-pakkett). Wara dan, il-kernel, minflok jinterpreta l-bytecode BPF, jista 'jikkonverti direttament programmi BPF għall-arkitettura fil-mira: x86, ARM, MIPS, eċċ.

Aktar tard, fl-2014, Alexey Starovoitov ippropona mekkaniżmu JIT ġdid għal BPF. Fil-fatt, din il-JIT il-ġdida saret arkitettura ġdida bbażata fuq BPF u kienet imsejħa eBPF. Naħseb li ż-żewġ VMs koeżistu għal xi żmien, iżda bħalissa l-iffiltrar tal-pakketti huwa implimentat ibbażat fuq eBPF. Fil-fatt, f'ħafna eżempji ta 'dokumentazzjoni moderna, BPF huwa mifhum li huwa eBPF, u BPF klassiku llum huwa magħruf bħala cBPF.

eBPF jestendi l-magna virtwali klassika BPF b'diversi modi:

  • Ibbażat fuq arkitetturi moderni 64-bit. eBPF juża reġistri ta '64 bit u jżid in-numru ta' reġistri disponibbli minn 2 (akkumulatur u X) għal 10. eBPF jipprovdi wkoll opcodes addizzjonali (BPF_MOV, BPF_JNE, BPF_CALL...).
  • Maqlugħ mis-subsistema tas-saff tan-netwerk. BPF kien marbut mal-mudell tad-dejta tal-lott. Peress li kien użat għall-iffiltrar tal-pakketti, il-kodiċi tiegħu kien jinsab fis-subsistema li tipprovdi komunikazzjonijiet tan-netwerk. Madankollu, il-magna virtwali eBPF m'għadhiex marbuta mal-mudell tad-dejta u tista 'tintuża għal kwalunkwe skop. Allura, issa l-programm eBPF jista 'jiġi konness ma' tracepoint jew kprobe. Dan jiftaħ it-triq għal strumentazzjoni eBPF, analiżi tal-prestazzjoni, u ħafna każijiet ta 'użu oħra fil-kuntest ta' sottosistemi oħra tal-kernel. Issa l-kodiċi eBPF jinsab fit-triq tiegħu stess: kernel/bpf.
  • Ħażniet tad-dejta globali msejħa Mapep. Il-mapep huma ħwienet tal-valur ewlieni li jippermettu l-iskambju tad-dejta bejn l-ispazju tal-utent u l-ispazju tal-kernel. eBPF jipprovdi diversi tipi ta' mapep.
  • Funzjonijiet sekondarji. B'mod partikolari, biex tikteb pakkett mill-ġdid, tikkalkula checksum, jew tikklona pakkett. Dawn il-funzjonijiet jaħdmu ġewwa l-kernel u mhumiex programmi ta' spazju għall-utent. Tista' wkoll tagħmel sejħiet tas-sistema minn programmi eBPF.
  • Tmiem is-sejħiet. Id-daqs tal-programm fl-eBPF huwa limitat għal 4096 bytes. Il-karatteristika tail call tippermetti li programm eBPF jittrasferixxi l-kontroll għal programm eBPF ġdid u b'hekk jevita din il-limitazzjoni (sa 32 programm jistgħu jiġu konnessi b'dan il-mod).

eBPF: eżempju

Hemm diversi eżempji għall-eBPF fis-sorsi tal-kernel tal-Linux. Huma disponibbli fuq samples/bpf/. Biex tiġbor dawn l-eżempji, sempliċement daħħal:

$ sudo make samples/bpf/

Jien mhux se nikteb eżempju ġdid għall-eBPF jien, imma se nuża wieħed mill-kampjuni disponibbli f'kampjuni/bpf/. Ser inħares lejn xi partijiet tal-kodiċi u nispjega kif jaħdem. Bħala eżempju, għażilt il-programm tracex4.

B'mod ġenerali, kull wieħed mill-eżempji f'kampjuni/bpf/ jikkonsisti f'żewġ fajls. F'dan il-każ:

  • tracex4_kern.c, fih il-kodiċi tas-sors li għandu jiġi esegwit fil-qalba bħala eBPF bytecode.
  • tracex4_user.c, fih programm mill-ispazju tal-utent.

F'dan il-każ, għandna bżonn niġbru tracex4_kern.c għal eBPF bytecode. Bħalissa fi gcc m'hemm l-ebda backend għall-eBPF. Fortunatament, clang jista' joħroġ eBPF bytecode. Makefile użi clang għall-kumpilazzjoni tracex4_kern.c għall-fajl tal-oġġett.

Semmejt hawn fuq li waħda mill-aktar karatteristiċi interessanti tal-eBPF huma l-mapep. tracex4_kern jiddefinixxi mappa waħda:

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 hija waħda mill-ħafna tipi ta' karti offruti mill-eBPF. F'dan il-każ, huwa biss hash. Inti jista 'wkoll innotajt reklam SEC("maps"). SEC huwa makro użat biex tinħoloq sezzjoni ġdida ta 'fajl binarju. Fil-fatt, fl-eżempju tracex4_kern żewġ taqsimiet oħra huma definiti:

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;
}   

Dawn iż-żewġ funzjonijiet jippermettulek tħassar dħul mill-mappa (kprobe/kmem_cache_free) u żid entrata ġdida fil-mappa (kretprobe/kmem_cache_alloc_node). L-ismijiet tal-funzjonijiet kollha miktuba b'ittri kapitali jikkorrispondu għal macros definiti fi bpf_helpers.h.

Jekk narmi t-taqsimiet tal-fajl tal-oġġett, għandi nara li dawn it-taqsimiet il-ġodda huma diġà definiti:

$ 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

Hemm ukoll tracex4_user.c, programm ewlieni. Bażikament, dan il-programm jisma 'avvenimenti kmem_cache_alloc_node. Meta jseħħ avveniment bħal dan, jiġi esegwit il-kodiċi eBPF korrispondenti. Il-kodiċi jiffranka l-attribut IP ta 'l-oġġett f'mappa, u l-oġġett imbagħad jiġi looped permezz tal-programm prinċipali. Eżempju:

$ 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

Kif huma relatati programm spazjali għall-utent u programm eBPF? Fuq l-inizjalizzazzjoni tracex4_user.c jgħabbi fajl oġġett tracex4_kern.o bl-użu tal-funzjoni 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;
}

Billi tagħmel load_bpf_file sondi definiti fil-fajl eBPF huma miżjuda magħhom /sys/kernel/debug/tracing/kprobe_events. Issa nisimgħu għal dawn l-avvenimenti u l-programm tagħna jista 'jagħmel xi ħaġa meta jiġri.

$ 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

Il-programmi l-oħra kollha fil-kampjun/bpf/ huma strutturati bl-istess mod. Dejjem ikun fihom żewġ fajls:

  • XXX_kern.c: programm eBPF.
  • XXX_user.c: programm ewlieni.

Il-programm eBPF jidentifika mapep u funzjonijiet assoċjati ma' sezzjoni. Meta l-kernel joħroġ avveniment ta' ċertu tip (per eżempju, tracepoint), il-funzjonijiet marbuta huma esegwiti. Il-karti jipprovdu komunikazzjoni bejn il-programm tal-qalba u l-programm tal-ispazju tal-utent.

Konklużjoni

Dan l-artikolu ddiskuta BPF u eBPF f'termini ġenerali. Naf li llum hemm ħafna informazzjoni u riżorsi dwar l-eBPF, għalhekk nirrakkomanda ftit aktar riżorsi għal aktar studju

Nirrakkomanda li taqra:

Sors: www.habr.com

Żid kumment