Yon entwodiksyon tou kout sou BPF ak eBPF

Bonjou, Habr! Nou ta renmen enfòme w ke n ap prepare yon liv pou lage."Obsèvabilite Linux ak BPF".

Yon entwodiksyon tou kout sou BPF ak eBPF
Depi machin vityèl BPF la kontinye evolye epi li itilize aktivman nan pratik, nou tradui pou ou yon atik ki dekri kapasite prensipal li yo ak eta aktyèl la.

Nan dènye ane yo, zouti pwogramasyon ak teknik yo te vin de pli zan pli popilè pou konpanse limit yo nan nwayo Linux la nan ka kote pwosesis pake pèfòmans-wo obligatwa. Youn nan teknik ki pi popilè nan kalite sa yo rele kontoune nwayo (bypass nwayo) ak pèmèt, kontourne kouch rezo nwayo a, fè tout pwosesis pake soti nan espas itilizatè. Bypasser nwayo a enplike tou kontwole kat rezo a soti nan espas itilizatè. Nan lòt mo, lè w ap travay ak yon kat rezo, nou konte sou chofè a espas itilizatè.

Lè nou transfere kontwòl konplè sou kat rezo a nan yon pwogram espas itilizatè, nou redwi sou tèt nwayo (chanje kontèks, pwosesis kouch rezo a, entèwonp, elatriye), ki trè enpòtan lè w ap kouri nan vitès 10Gb/s oswa pi wo. Bypass Kernel plis yon konbinezon de lòt karakteristik (pwosesis pakèt) ak akor pèfòmans atansyon (Kontablite NUMA, CPU izòlman, elatriye) koresponn ak fondamantal yo nan pwosesis rezo-wo pèfòmans nan espas itilizatè. Petèt yon egzanp egzanplè nouvo apwòch sa a nan pwosesis pake se DPDK soti nan Intel (Twous Devlopman Avyon Done), byenke gen lòt zouti ak teknik byen li te ye, ki gen ladan VPP Cisco a (Vector Packet Processing), Netmap ak, nan kou, Snabb.

Òganize entèraksyon rezo nan espas itilizatè a gen yon kantite dezavantaj:

  • Kernel OS la se yon kouch abstrè pou resous pyès ki nan konpitè. Paske pwogram espas itilizatè yo dwe jere resous yo dirèkteman, yo dwe jere pwòp pyès ki nan konpitè yo tou. Sa vle di souvan gen pou pwogram pwòp chofè ou.
  • Paske n ap abandone espas nwayo a nèt, nou tou abandone tout fonksyonalite rezo ke nwayo a bay. Pwogram espas itilizatè yo dwe reimplemente karakteristik ke nwayo a oswa sistèm opere yo ka deja bay yo.
  • Pwogram yo opere nan mòd sandbox, ki seryezman limite entèraksyon yo epi anpeche yo entegre ak lòt pati nan sistèm operasyon an.

Nan sans, lè rezo nan espas itilizatè, pwogrè pèfòmans yo reyalize lè w deplase pwosesis pake soti nan nwayo a nan espas itilizatè. XDP fè egzakteman opoze a: li deplase pwogram rezo soti nan espas itilizatè (filtè, rezolisyon, routage, elatriye) nan espas nwayo. XDP pèmèt nou fè yon fonksyon rezo le pli vit ke yon pake frape yon koòdone rezo epi anvan li kòmanse deplase nan subsistèm rezo nwayo a. Kòm yon rezilta, vitès pwosesis pake a ogmante anpil. Sepandan, ki jan nwayo a pèmèt itilizatè a egzekite pwogram yo nan espas nwayo a? Anvan ou reponn kesyon sa a, ann gade kisa BPF ye.

BPF ak eBPF

Malgre non an konfizyon, BPF (Berkeley Packet Filtering) se, an reyalite, yon modèl machin vityèl. Machin vityèl sa a te fèt orijinal pou okipe filtraj pake, pakonsekan non an.

Youn nan zouti ki pi popilè lè l sèvi avèk BPF se tcpdump. Lè w ap kaptire pake lè l sèvi avèk tcpdump itilizatè a ka presize yon ekspresyon pou filtre pake. Se sèlman pake ki matche ak ekspresyon sa a pral kaptire. Pa egzanp, ekspresyon "tcp dst port 80” refere a tout pake TCP ki rive sou pò 80. Konpilatè a ka diminye ekspresyon sa a lè li konvèti li nan 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

Sa a se sa pwogram ki anwo a fondamantalman fè:

  • Enstriksyon (000): Chaje pake a nan konpanse 12, kòm yon mo 16-bit, nan akimilatè a. Offset 12 koresponn ak ethertype pake a.
  • Enstriksyon (001): konpare valè nan akimilatè a ak 0x86dd, se sa ki, ak valè ethertype pou IPv6. Si rezilta a se vre, Lè sa a, kontwa pwogram lan ale nan enstriksyon (002), epi si se pa, Lè sa a, nan (006).
  • Enstriksyon (006): konpare valè a ak 0x800 (valè ethertype pou IPv4). Si repons lan se vre, Lè sa a, pwogram nan ale nan (007), si se pa, Lè sa a, nan (015).

Ak sou sa jiskaske pwogram nan filtraj pake retounen yon rezilta. Sa a se nòmalman yon Boolean. Retounen yon valè ki pa zewo (enstriksyon (014)) vle di ke yo te aksepte pake a, epi retounen yon valè zewo (enstriksyon (015)) vle di ke pake a pa te aksepte.

Machin vityèl BPF la ak bytecode li yo te pwopoze pa Steve McCann ak Van Jacobson nan fen ane 1992 lè yo te pibliye papye yo. BSD Pake Filter: Nouvo Achitekti pou Capture Pake Itilizatè Nivo, teknoloji sa a te premye prezante nan konferans Usenix nan sezon fredi 1993.

Paske BPF se yon machin vityèl, li defini anviwònman kote pwogram yo kouri. Anplis bytecode a, li defini tou modèl memwa pakèt la (enstriksyon chaj yo aplike implicitement nan pakèt la), rejis (A ak X; akimilatè ak rejis endèks), depo memwa grate, ak yon kontwa pwogram implicite. Enteresan, bytecode BPF te modle apre Motorola 6502 ISA la. Jan Steve McCann te raple nan li rapò plenyè nan Sharkfest '11, li te abitye ak bati 6502 nan pwogram li jou lekòl segondè sou Apple II a, ak konesans sa a enfliyanse travay li desine bytecode BPF la.

Sipò BPF aplike nan nwayo Linux nan vèsyon v2.5 ak pi wo, te ajoute sitou pa efò Jay Schullist. Kòd BPF a te rete san okenn chanjman jiska 2011, lè Eric Dumaset te reamenaje entèprèt BPF a pou l te kouri nan mòd JIT (Sous: JIT pou filtè pake). Apre sa, nwayo a, olye pou yo entèprete BPF bytecode, te kapab dirèkteman konvèti pwogram BPF nan achitekti sib la: x86, ARM, MIPS, elatriye.

Apre sa, nan 2014, Alexey Starovoitov te pwopoze yon nouvo mekanis JIT pou BPF. An reyalite, nouvo JIT sa a te vin tounen yon nouvo achitekti ki baze sou BPF epi yo te rele eBPF. Mwen panse ke tou de VM yo ansanm pou kèk tan, men kounye a se filtraj pake aplike ki baze sou eBPF. An reyalite, nan anpil egzanp nan dokiman modèn, BPF konprann yo dwe eBPF, ak BPF klasik jodi a ke yo rekonèt kòm cBPF.

eBPF pwolonje machin vityèl BPF klasik la nan plizyè fason:

  • Ki baze sou achitekti modèn 64-bit. eBPF itilize rejis 64-bit ak ogmante kantite rejis ki disponib soti nan 2 (akimilatè ak X) a 10. eBPF bay tou opcodes adisyonèl (BPF_MOV, BPF_JNE, BPF_CALL...).
  • Detache nan subsistèm kouch rezo a. BPF te mare ak modèl done pakèt la. Depi yo te itilize li pou filtraj pake, kòd li a te lokalize nan subsistèm ki bay kominikasyon rezo a. Sepandan, eBPF machin vityèl la pa mare ankò ak modèl done a epi yo ka itilize pou nenpòt ki rezon. Se konsa, kounye a pwogram eBPF ka konekte ak tracepoint oswa kprobe. Sa a ouvè wout la nan enstriman eBPF, analiz pèfòmans, ak anpil lòt ka itilize nan kontèks lòt subsistèm nwayo. Koulye a, kòd eBPF la sitiye nan pwòp chemen li yo: kernel/bpf.
  • Depo done mondyal yo rele Maps. Kat yo se magazen kle-valè ki pèmèt echanj done ant espas itilizatè ak espas nwayo. eBPF bay plizyè kalite kat.
  • Fonksyon segondè. An patikilye, pou reekri yon pake, kalkile yon sòm chèk, oswa klonaj yon pake. Fonksyon sa yo kouri andedan nwayo a epi yo pa pwogram espas itilizatè. Ou kapab tou fè apèl sistèm nan pwogram eBPF.
  • Fini apèl yo. Gwosè pwogram nan eBPF limite a 4096 octets. Karakteristik ke apèl la pèmèt yon pwogram eBPF transfere kontwòl nan yon nouvo pwogram eBPF epi konsa kontoune limit sa a (jiska 32 pwogram yo ka lye nan fason sa a).

eBPF: egzanp

Gen plizyè egzanp pou eBPF nan sous nwayo Linux yo. Yo disponib nan echantiyon/bpf/. Pou konpile egzanp sa yo, tou senpleman antre:

$ sudo make samples/bpf/

Mwen pa pral ekri yon nouvo egzanp pou eBPF tèt mwen, men mwen pral sèvi ak youn nan echantiyon ki disponib nan echantiyon/bpf/. Mwen pral gade kèk pati nan kòd la epi eksplike kijan li fonksyone. Kòm yon egzanp, mwen te chwazi pwogram nan tracex4.

An jeneral, chak egzanp nan samples/bpf/ konsiste de de dosye. Nan ka sa:

  • tracex4_kern.c, gen kòd sous yo dwe egzekite nan nwayo a kòm eBPF bytecode.
  • tracex4_user.c, gen yon pwogram ki soti nan espas itilizatè.

Nan ka sa a, nou bezwen konpile tracex4_kern.c nan eBPF bytecode. Kounye a nan gcc pa gen okenn backend pou eBPF. Erezman, clang ka bay eBPF bytecode. Makefile itilizasyon clang pou konpilasyon tracex4_kern.c nan dosye objè a.

Mwen mansyone pi wo a ke youn nan karakteristik ki pi enteresan nan eBPF yo se kat. tracex4_kern defini yon kat:

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 se youn nan plizyè kalite kat eBPF ofri. Nan ka sa a, li se jis yon hash. Ou ka remake tou yon anons SEC("maps"). SEC se yon makro ki itilize pou kreye yon nouvo seksyon nan yon dosye binè. Aktyèlman, nan egzanp lan tracex4_kern de lòt seksyon yo defini:

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

De fonksyon sa yo pèmèt ou efase yon antre nan kat la (kprobe/kmem_cache_free) epi ajoute yon nouvo antre nan kat la (kretprobe/kmem_cache_alloc_node). Tout non fonksyon ki ekri an lèt majiskil koresponn ak makro yo defini nan bpf_helpers.h.

Si mwen jete seksyon yo nan fichye objè a, mwen ta dwe wè ke nouvo seksyon sa yo deja defini:

$ 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

Genyen tou tracex4_user.c, pwogram prensipal la. Fondamantalman, pwogram sa a koute evènman yo kmem_cache_alloc_node. Lè yon evènman konsa rive, kòd eBPF korespondan an egzekite. Kòd la sove atribi IP objè a nan yon kat jeyografik, epi objè a se answit nan pwogram prensipal la. Egzanp:

$ 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

Ki jan yon pwogram espas itilizatè yo ak yon pwogram eBPF gen rapò? Sou inisyalizasyon tracex4_user.c chaje yon fichye objè tracex4_kern.o lè l sèvi avèk fonksyon an 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;
}

Pa fè load_bpf_file yo ajoute sond ki defini nan dosye eBPF /sys/kernel/debug/tracing/kprobe_events. Koulye a, nou koute evènman sa yo ak pwogram nou an ka fè yon bagay lè yo rive.

$ 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

Tout lòt pwogram nan echantiyon/bpf/ yo estriktire menm jan an. Yo toujou gen de dosye:

  • XXX_kern.c: pwogram eBPF.
  • XXX_user.c: pwogram prensipal la.

Pwogram eBPF la idantifye kat ak fonksyon ki asosye ak yon seksyon. Lè nwayo a bay yon evènman nan yon sèten kalite (pa egzanp, tracepoint), fonksyon yo mare yo egzekite. Kat yo bay kominikasyon ant pwogram nwayo a ak pwogram espas itilizatè a.

Konklizyon

Atik sa a te diskite BPF ak eBPF an tèm jeneral. Mwen konnen gen anpil enfòmasyon ak resous sou eBPF jodi a, kidonk mwen pral rekòmande kèk lòt resous pou plis etid.

Mwen rekòmande lekti:

Sous: www.habr.com

Add nouvo kòmantè