Fampidirana fohifohy momba ny BPF sy eBPF

Salama, Habr! Tianay ny mampahafantatra anareo fa manomana boky havoaka izahay”.Linux Observability miaraka amin'ny BPF".

Fampidirana fohifohy momba ny BPF sy eBPF
Koa satria ny milina virtoaly BPF dia mitohy mivoatra ary ampiasaina amin'ny fampiharana, dia nadika ho anao lahatsoratra iray mamaritra ny fahaiza-manaony sy ny toe-javatra misy azy ankehitriny.

Tao anatin'ny taona vitsivitsy izay, nanjary nalaza be ny fitaovana sy ny teknika fandaharana mba hanonerana ny fetran'ny kernel Linux amin'ny toe-javatra izay ilaina ny fanodinana fonosana avo lenta. Ny iray amin'ireo teknika malaza indrindra amin'ity karazana ity dia antsoina hoe kernel bypass (kernel bypass) ary mamela, mandingana ny sarin'ny tamba-jotra kernel, manao ny fanodinana fonosana rehetra avy amin'ny habaka mpampiasa. Ny fandalovana ny kernel dia midika koa ny fanaraha-maso ny karatra tambajotra avy habaka mpampiasa. Raha lazaina amin'ny teny hafa, rehefa miasa amin'ny karatra tambajotra dia miantehitra amin'ny mpamily isika habaka mpampiasa.

Amin'ny alΓ lan'ny famindrana ny fanaraha-maso feno amin'ny karatry ny tambazotra mankany amin'ny fandaharan'asan'ny habaka mpampiasa, dia mampihena ny overhead kernel (fanodinana ny toe-javatra, fanodinana sosona tambajotra, fanelingelenana, sns.), izay tena zava-dehibe rehefa mihazakazaka amin'ny hafainganam-pandeha 10Gb/s na mihoatra. Kernel bypass miampy fitambarana endri-javatra hafa (fanodinana batch) ary ny fampitandremana tsara ny fampisehoana (Ny kaonty NUMA, CPU mitoka-monina, sns.) mifanaraka amin'ny fototry ny fanodinana tambajotra mahomby amin'ny habaka mpampiasa. Angamba ohatra iray fakan-tahaka amin'ity fomba fiasa vaovao amin'ny fanodinana fonosana ity DPDK avy amin'ny Intel (Kit fampandrosoana ny fiaramanidina data), na dia misy fitaovana sy teknika malaza hafa aza, anisan'izany ny Cisco VPP (Vector Packet Processing), Netmap ary mazava ho azy, snab.

Ny fandaminana ny fifaneraserana amin'ny tambajotra amin'ny habaka mpampiasa dia misy fatiantoka maromaro:

  • Ny kernel OS dia sosona abstraction ho an'ny loharanom-pitaovana. Satria tsy maintsy mitantana mivantana ny loharanon-karenany ny programa habaka mpampiasa, tsy maintsy mitantana ny fitaovany manokana ihany koa izy ireo. Matetika izany dia midika hoe mila manomana ny mpamily anao manokana.
  • Satria lavintsika tanteraka ny habaka kernel, dia afointsika ihany koa ny fampiasa tambajotra rehetra omen'ny kernel. Ny programa habaka mpampiasa dia tsy maintsy mamerina mamerina ireo endri-javatra izay mety efa omen'ny kernel na ny rafitra fandidiana.
  • Ny fandaharana dia miasa amin'ny fomba sandbox, izay mametra mafy ny fifandraisany ary manakana azy ireo tsy hiditra amin'ny ampahany hafa amin'ny rafitra miasa.

Raha ny tena izy, rehefa mifandray amin'ny habaka mpampiasa, dia tratra ny tombony amin'ny alΓ lan'ny famindrana ny fanodinana fonosana avy amin'ny kernel mankany amin'ny habaka mpampiasa. Ny XDP dia manao ny mifanohitra amin'izany: mamindra ny programa amin'ny tambajotra avy amin'ny habaka mpampiasa (sivana, solver, routing, sns.) mankany amin'ny faritra kernel. Ny XDP dia mamela antsika hanao asa amin'ny tambajotra raha vantany vao misy fonosana iray mamely ny seha-pifandraisana iray ary alohan'ny hanombohany miakatra ao amin'ny subsysteme network kernel. Vokatr'izany dia mitombo be ny hafainganam-pandehan'ny fanodinana fonosana. Na izany aza, ahoana no ahafahan'ny kernel mamela ny mpampiasa manatanteraka ny programany amin'ny habaka kernel? Alohan'ny hamaliana ity fanontaniana ity, andeha hojerentsika ny atao hoe BPF.

BPF sy eBPF

Na dia eo aza ny anarana mampisafotofoto, ny BPF (Berkeley Packet Filtering) dia modely milina virtoaly. Ity milina virtoaly ity dia natao tany am-boalohany mba hikarakarana ny sivana fonosana, noho izany ny anarana.

Ny iray amin'ireo fitaovana malaza indrindra mampiasa BPF dia tcpdump. Rehefa misambotra fonosana mampiasa tcpdump ny mpampiasa dia afaka mamaritra fomba fiteny hanivanana fonosana. Ny fonosana mifanandrify amin'io fomba fiteny io ihany no horaisina. Ohatra, ny teny hoe "tcp dst port 80” dia manondro ny fonosana TCP rehetra tonga ao amin'ny seranan-tsambo 80. Ny mpanangom-bokatra dia afaka manafohy io fitenenana io amin'ny alΓ lan'ny famadihana azy ho 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

Ity no tena ataon'ity programa etsy ambony ity:

  • Torolalana (000): Ampidiro ao amin'ny mpanangona ny fonosana amin'ny offset 12, ho teny 16-bit. Ny offset 12 dia mifanitsy amin'ny ethertype an'ny fonosana.
  • Torolalana (001): mampitaha ny sanda ao amin'ny accumulator amin'ny 0x86dd, izany hoe, miaraka amin'ny sanda etertype ho an'ny IPv6. Raha marina ny valiny, dia mankany amin'ny fampianarana (002) ny kaontera fandaharana, ary raha tsy izany, dia mankany amin'ny (006).
  • Torolalana (006): mampitaha ny sanda amin'ny 0x800 (sanda ethertype ho an'ny IPv4). Raha marina ny valiny, dia mankany amin'ny (007) ny programa, raha tsy izany, dia mankany amin'ny (015).

Ary dia toy izany mandra-packet sivana fandaharana mamerina vokatra. Ity dia matetika Boolean. Ny famerenana ny sanda tsy aotra (instruction (014)) dia midika fa nekena ny fonosana, ary ny famerenana ny sanda aotra (instruction (015)) dia midika fa tsy nekena ilay fonosana.

Ny milina virtoaly BPF sy ny bytecode dia natolotr'i Steve McCann sy Van Jacobson tamin'ny faramparan'ny taona 1992 rehefa navoaka ny taratasiny. BSD Packet Filter: Architecture vaovao ho an'ny mpampiasa-Level Packet Capture, io teknolojia io dia naseho voalohany tamin'ny fihaonambe Usenix tamin'ny ririnina 1993.

Satria milina virtoaly ny BPF, dia mamaritra ny tontolo iainan'ny programa. Ho fanampin'ny bytecode, dia mamaritra ihany koa ny maodely fitadidiana batch (fampiharana an-kolaka amin'ny batch ny toromarika enta-mavesatra), rejisitra (A sy X; rejistra mpanangona sy fanondroana), fitahirizana fitadidiana scratch, ary counter programm implicit. Mahaliana fa ny BPF bytecode dia modely taorian'ny Motorola 6502 ISA. Araka ny tsaroan'i Steve McCann tao amin'ny azy tatitry ny pleno tao amin'ny Sharkfest '11, nahazatra azy ny fananganana 6502 tamin'ny fandaharan'asan'ny sekoly ambaratonga faharoa tamin'ny Apple II, ary nisy fiantraikany tamin'ny asany tamin'ny famolavolana ny BPF bytecode izany fahalalana izany.

Ny fanohanan'ny BPF dia ampiharina amin'ny kernel Linux amin'ny dikan-teny v2.5 sy ambony kokoa, nampian'ny ezaka nataon'i Jay Schullist indrindra. Tsy niova ny kaody BPF hatramin'ny taona 2011, rehefa nanamboatra ny mpandika teny BPF i Eric Dumaset mba handeha amin'ny fomba JIT (Loharano: JIT ho an'ny sivana fonosana). Aorian'izany, ny kernel, fa tsy mandika ny BPF bytecode, dia afaka manova mivantana ny programa BPF amin'ny maritrano kendrena: x86, ARM, MIPS, sns.

Taty aoriana, tamin'ny 2014, Alexey Starovoitov dia nanolotra rafitra JIT vaovao ho an'ny BPF. Raha ny marina, ity JIT vaovao ity dia lasa maritrano vaovao mifototra amin'ny BPF ary nantsoina hoe eBPF. Heveriko fa niara-niaina nandritra ny fotoana kelikely ny VM roa, fa amin'izao fotoana izao ny sivana packet dia ampiharina amin'ny eBPF. Raha ny marina, amin'ny ohatra maro amin'ny antontan-taratasy maoderina, ny BPF dia heverina ho eBPF, ary ny BPF klasika dia fantatra amin'ny anarana hoe cBPF.

Ny eBPF dia manitatra ny milina virtoaly BPF mahazatra amin'ny fomba maro:

  • Miorina amin'ny maritrano maoderina 64-bit. Ny eBPF dia mampiasa rejisitra 64-bit ary mampitombo ny isan'ny rejisitra misy avy amin'ny 2 (accumulator sy X) ho 10. Ny eBPF koa dia manome opcode fanampiny (BPF_MOV, BPF_JNE, BPF_CALL...).
  • Misaraka amin'ny subsystem sosona tambajotra. Ny BPF dia mifamatotra amin'ny maodely data batch. Koa satria nampiasaina tamin'ny fanivanana fonosana izy, dia hita ao amin'ny subsystem izay manome fifandraisana amin'ny tambajotra ny kaodiny. Na izany aza, ny milina virtoaly eBPF dia tsy mifamatotra amin'ny maodely data ary azo ampiasaina amin'ny tanjona rehetra. Noho izany, ankehitriny ny programa eBPF dia azo ampifandraisina amin'ny tracepoint na kprobe. Izany dia manokatra ny lalana mankany amin'ny fitaovana eBPF, famakafakana ny zava-bita, ary tranga fampiasana maro hafa amin'ny tontolon'ny subsystems kernel hafa. Ankehitriny ny kaody eBPF dia hita amin'ny lΓ lany manokana: kernel/bpf.
  • Fivarotana angona manerantany antsoina hoe Maps. Sarintany dia toeram-pivarotana manan-danja izay ahafahana mifanakalo angona eo amin'ny habaka mpampiasa sy ny habaka kernel. Ny eBPF dia manome karazana sari-tany maromaro.
  • Asa faharoa. Indrindra indrindra, mba hanoratana indray fonosana, kajy ny checksum, na clone fonosana. Ireo fiasa ireo dia mandeha ao anatin'ny kernel ary tsy programa ampiasain'ny mpampiasa. Azonao atao ihany koa ny manao antso an-tariby avy amin'ny programa eBPF.
  • Tapaho ny antso. Ny haben'ny programa ao amin'ny eBPF dia voafetra ho 4096 bytes. Ny endri-javatra antso amin'ny rambony dia ahafahan'ny programa eBPF mamindra ny fanaraha-maso amin'ny programa eBPF vaovao ary mandingana io fetra io (hatramin'ny programa 32 no azo ampifandraisina amin'izany fomba izany).

eBPF: ohatra

Misy ohatra maromaro momba ny eBPF ao amin'ny loharano kernel Linux. Misy amin'ny santionany/bpf/. Mba hanangonana ireto ohatra ireto dia midira fotsiny:

$ sudo make samples/bpf/

Tsy hanoratra ohatra vaovao ho an'ny eBPF ny tenako, fa hampiasa ny iray amin'ireo santionany misy amin'ny samples/bpf/. Hojereko ny ampahany sasany amin'ny kaody ary hanazava ny fomba fiasany. Ohatra, nisafidy ny programa aho tracex4.

Amin'ny ankapobeny, ny tsirairay amin'ireo ohatra ao amin'ny samples/bpf/ dia misy rakitra roa. Raha izany dia:

  • tracex4_kern.c, dia misy ny kaody loharano hovonoina ao amin'ny kernel ho eBPF bytecode.
  • tracex4_user.c, misy programa avy amin'ny habaka mpampiasa.

Amin'ity tranga ity dia mila manangona isika tracex4_kern.c amin'ny eBPF bytecode. Amin'izao fotoana izao gcc tsy misy backend ho an'ny eBPF. Soa ihany, clang afaka mamoaka eBPF bytecode. Makefile fampiasana clang ho an'ny fanangonana tracex4_kern.c mankany amin'ny rakitra zavatra.

Nolazaiko teo ambony fa ny iray amin'ireo endri-javatra mahaliana indrindra amin'ny eBPF dia sarintany. tracex4_kern dia mamaritra sarintany iray:

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 dia iray amin'ireo karazana karatra maro atolotry ny eBPF. Amin'ity tranga ity, tenifototra fotsiny izany. Mety nahatsikaritra doka iray koa ianao SEC("maps"). SEC dia macro ampiasaina hamoronana fizarana vaovao amin'ny rakitra binary. Raha ny marina, amin'ny ohatra tracex4_kern fizarana roa hafa no voafaritra:

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

Ireo fiasa roa ireo dia ahafahanao mamafa ny fidirana amin'ny sari-tany (kprobe/kmem_cache_free) ary ampio fampidirana vaovao amin'ny sari-tany (kretprobe/kmem_cache_alloc_node). Ny anaran'ny asa rehetra voasoratra amin'ny litera lehibe dia mifanandrify amin'ny macro voafaritra ao bpf_helpers.h.

Raha manary ny ampahan'ny rakitra object aho dia tokony ho hitako fa efa voafaritra ireto fizarana vaovao ireto:

$ 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

Misy koa tracex4_user.c, programa lehibe. Amin'ny ankapobeny, ity programa ity dia mihaino hetsika kmem_cache_alloc_node. Rehefa misy trangan-javatra toy izany, ny kaody eBPF mifanaraka aminy dia tanterahina. Ny kaody dia mitahiry ny toetran'ny IP an'ilay zavatra ao anaty sarintany, ary avy eo ilay zavatra dia mihodina amin'ny programa fototra. Ohatra:

$ 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

Ahoana no ifandraisan'ny programa habaka mpampiasa sy ny programa eBPF? Amin'ny initialization tracex4_user.c mitondra rakitra zavatra tracex4_kern.o mampiasa ny asa 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;
}

Amin'ny fanaovana load_bpf_file Ny probes voafaritra ao amin'ny rakitra eBPF dia ampiana /sys/kernel/debug/tracing/kprobe_events. Ankehitriny dia mihaino ireo hetsika ireo izahay ary afaka manao zavatra ny fandaharanay rehefa mitranga izany.

$ 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

Ny programa hafa rehetra ao amin'ny sample/bpf/ dia voarafitra mitovy. Misy rakitra roa foana izy ireo:

  • XXX_kern.c: programa eBPF.
  • XXX_user.c: fandaharana lehibe.

Ny programa eBPF dia mamaritra sarintany sy fiasa mifandraika amin'ny fizarana iray. Rehefa mamoaka hetsika iray karazana iray ny kernel (ohatra, tracepoint), ny asa mifatotra dia tanterahina. Ny karatra dia manome fifandraisana eo amin'ny programa kernel sy ny programa habaka mpampiasa.

famaranana

Ity lahatsoratra ity dia niresaka momba ny BPF sy ny eBPF amin'ny teny ankapobeny. Fantatro fa be dia be ny fampahalalana sy loharano momba ny eBPF androany, noho izany dia hanoro loharanom-baovao vitsivitsy aho ho an'ny fandalinana fanampiny

Manoro hevitra aho hamaky:

Source: www.habr.com

Add a comment