BPF yevadiki, chikamu chekutanga: yakawedzera BPF

Pakutanga kwaive netechnology uye yainzi BPF. Takamutarisa yapfuura, nyaya yeTestamente Yekare yeiyi nhevedzano. Muna 2013, kuburikidza nekuedza kwaAlexei Starovoitov naDaniel Borkman, iyo yakagadziridzwa vhezheni yayo, yakagadziridzwa yemazuva ano 64-bit michina, yakagadziridzwa uye yakaiswa muLinux kernel. Iyi tekinoroji nyowani yakadanwa muchidimbu kunzi Internal BPF, ndokuzopihwa zita rekuti Extended BPF, uye ikozvino, mushure memakore akati wandei, munhu wese anongoidaidza kuti BPF.

Zvichireva kutaura, BPF inokutendera kuti umhanye kodhi-inopihwa nemushandisi munzvimbo yeLinux kernel, uye chivakwa chitsva chakabudirira zvekuti isu tichada gumi nemaviri zvimwe zvinyorwa kutsanangura mashandisiro ayo ese. (Chinhu chega icho vagadziri vasina kuita zvakanaka, sezvauri kuona mune kodhi yekuita pazasi, yaive kugadzira yakanaka logo.)

Ichi chinyorwa chinotsanangura chimiro cheiyo BPF chaiyo muchina, kernel interfaces yekushanda neBPF, maturusi ekuvandudza, pamwe nepfupi, pfupi pfupi yezvekwaniso iripo, i.e. zvese zvatichada mune ramangwana kuti tidzidze zvakadzama nezve mashandisiro anoita BPF.
BPF yevadiki, chikamu chekutanga: yakawedzera BPF

Pfupiso yechinyorwa

Nhanganyaya kune BPF architecture. Chekutanga, isu tinotora ziso reshiri rekuona kweBPF dhizaini uye totsanangura zvinhu zvikuru.

Marejista uye system yekuraira yeBPF chaiyo muchina. Tatova nepfungwa yezvivakwa zvakazara, isu tichatsanangura chimiro cheiyo BPF chaiyo muchina.

Hupenyu kutenderera kwezvinhu zveBPF, bpffs faira system. Muchikamu chino, tichanyatsotarisisa kutenderera kwehupenyu hweBPF zvinhu - zvirongwa nemamepu.

Kugadzirisa zvinhu uchishandisa iyo bpf system call. Nekumwe kunzwisisa kweiyo system yatove panzvimbo, isu tinozopedzisira tatarisa maitiro ekugadzira nekushandisa zvinhu kubva munzvimbo yemushandisi uchishandisa yakakosha system call - bpf(2).

ПишСм ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ BPF с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ libbpf. Ehe, iwe unogona kunyora zvirongwa uchishandisa system call. Asi zvakaoma. Nokuda kwechinoitika chaichoicho, vagadziri vepurogiramu dzenyukireya vakagadzira raibhurari libbpf. Isu tichagadzira yakakosha BPF application skeleton yatichashandisa mumienzaniso inotevera.

Kernel Helpers. Pano tichadzidza kuti zvirongwa zveBPF zvinogona sei kuwana kernel mubatsiri mabasa - chishandiso icho, pamwe nemamepu, chinowedzera hunyanzvi hweBPF nyowani zvichienzaniswa neyekare.

Kuwana mepu kubva kuBPF zvirongwa. Panguva ino, tichaziva zvakakwana kuti tinzwisise kuti tingagadzira sei zvirongwa zvinoshandisa mepu. Uye ngatitorei nekukurumidza kutarisa mune yakakura uye ine simba verifier.

Zvishandiso zvekuvandudza. Batsira chikamu pamaunganidziro anodiwa uye kernel yekuyedza.

The conclusion. Pakupera kwechinyorwa chacho, avo vanorava kusvika zvino vachawana mashoko anokurudzira nerondedzero pfupi yezvichaitika munyaya dzinotevera. Isu tichanyorawo akati wandei malink ekuzviverengera kune avo vasina chishuwo kana kugona kumirira kuenderera mberi.

Nhanganyaya yeBPF Architecture

Tisati tatanga kufunga nezveBPF dhizaini, isu tichataura kekupedzisira (o) kune classic BPF, iyo yakagadzirwa semhinduro yekuuya kwemichina yeRISC uye yakagadzirisa dambudziko rekushanda kwepacket filtering. Iyo dhizaini yakave yakabudirira zvekuti, yakazvarwa mumakore makumi mapfumbamwe muBerkeley UNIX, yakatakurwa kune mazhinji aripo masisitimu ekushandisa, yakapona kusvika makumi maviri anopenga uye ichiri kutsvaga maapplication matsva.

Iyo BPF nyowani yakagadziridzwa semhinduro kune yakajairika ye64-bit michina, makore masevhisi uye kuwedzera kudiwa kwezvishandiso zvekugadzira SDN (Skunze-defined networking). Yakagadzirwa nekernel network mainjiniya seyakagadziridzwa kutsiva iyo yekirasi BPF, iyo BPF nyowani mushure memwedzi mitanhatu yakazowana zvikumbiro mubasa rakaoma rekutevera Linux masisitimu, uye ikozvino, makore matanhatu mushure mekuonekwa kwayo, isu tichada chinyorwa chinotevera chete. nyora mhando dzakasiyana dzezvirongwa.

Funny pictures

Papakati payo, BPF ijecha rejecha rinokutendera kuti umhanye "zvisinganzwisisike" kodhi munzvimbo yekernel pasina kukanganisa kuchengetedzeka. Mapurogiramu eBPF anogadzirwa munzvimbo yemushandisi, akaiswa mukernel, uye akabatana kune imwe chiitiko sosi. Chiitiko chinogona kunge chiri, semuenzaniso, kuendeswa kwepaketi kune network network, kutangwa kweimwe kernel basa, nezvimwe. Panyaya yepakeji, chirongwa cheBPF chichakwanisa kuwana data uye metadata yepakiti (yekuverenga uye, zvichida, kunyora, zvichienderana nerudzi rwepurogiramu); munyaya yekushanda kernel basa, nharo dze. basa racho, kusanganisira zvinongedzo kune kernel memory, nezvimwe.

Ngatinyatsoongororai maitiro aya. Kutanga, ngatitaure nezve musiyano wekutanga kubva kuBPF yekare, mapurogiramu ayo akanyorwa muassembler. Muchinyorwa chitsva, chivakwa chakawedzerwa kuitira kuti mapurogiramu anyorwe mumitauro yepamusoro, kunyanya, hongu, muC. Nokuda kweizvi, backend yellvm yakagadzirwa, iyo inokubvumira kuti uite bytecode yeBPF architecture.

BPF yevadiki, chikamu chekutanga: yakawedzera BPF

Iyo BPF dhizaini yakagadzirwa, muchidimbu, kuti ishande nemazvo pamichina yemazuva ano. Kuita kuti basa iri rishande, iyo BPF bytecode, kana yaiswa mukernel, inoshandurirwa mukodhi yemuno uchishandisa chikamu chinonzi JIT compiler (Just In Tini). Tevere, kana iwe uchirangarira, mukirasi BPF chirongwa chakaiswa mu kernel uye chakanamirwa kune chiitiko sosi atomu - mumamiriro ekufona system imwechete. Muchivakwa chitsva, izvi zvinoitika mumatanho maviri - chekutanga, iyo kodhi inoiswa mukernel uchishandisa system yekufona. bpf(2)uyezve, gare gare, kuburikidza nedzimwe nzira dzinosiyana zvichienderana nerudzi rwepurogiramu, purogiramu inonamatira kune chiitiko chinobva.

Pano muverengi angave nemubvunzo: zvaigoneka here? Ko kuchengetedzwa kwekuita kwekodhi yakadaro kunovimbiswa sei? Kuchengetedzwa kwekuuraya kunovimbiswa kwatiri nedanho rekurodha zvirongwa zveBPF zvinonzi verifier (muChirungu nhanho iyi inonzi verifier uye ini ndicharamba ndichishandisa izwi reChirungu):

BPF yevadiki, chikamu chekutanga: yakawedzera BPF

Verifier is static analyzer inova nechokwadi chekuti chirongwa hachikanganise kushanda kwakajairwa kwekernel. Izvi, nenzira, hazvireve kuti chirongwa hachigone kukanganisa kushanda kwehurongwa - zvirongwa zveBPF, zvichienderana nerudzi, zvinogona kuverenga nekunyorazve zvikamu zvekernel memory, kudzorera kukosha kwemabasa, trim, append, kunyorazve. uye kunyange mberi network packets. Verifier inovimbisa kuti kumhanyisa chirongwa cheBPF hakuzopaza kernel uye kuti chirongwa icho, maererano nemitemo, chine mukana wekunyora, semuenzaniso, data repaketi rinobuda, haringakwanise kunyora kernel memory kunze kwepaketi. Tichatarisa verifier mune zvishoma zvakadzama muchikamu chinoenderana, mushure mekunge tajairana nezvimwe zvese zvikamu zveBPF.

Saka chii chatadzidza kusvika pari zvino? Mushandisi anonyora chirongwa muC, anochiisa mu kernel achishandisa kufona system bpf(2), painotariswa neanosimbisa uye inoshandurirwa mumutauro webytecode. Zvadaro zvakafanana kana mumwe mushandisi anobatanidza chirongwa kune chiitiko sosi uye chinotanga kuita. Kuparadzanisa boot uye kubatana kunodiwa nekuda kwezvikonzero zvakati. Chekutanga, kushandisa verifier kunodhura uye nekudhawunirodha chirongwa chimwe chete kakawanda tinoparadza nguva yekombuta. Chechipiri, chaizvo kuti chirongwa chakabatana sei zvinoenderana nerudzi rwayo, uye imwe "yepasirese" interface yakagadziridzwa gore rapfuura inogona kunge isingakodzeri mhando nyowani dzezvirongwa. (Kunyangwe ikozvino iyo dhizaini iri kuwedzera kukura, pane zano rekubatanidza iyi interface padanho. libbpf.)

Muverengi anoteerera angaona kuti hatisati tapedza nemifananidzo. Chokwadi, zvese zviri pamusoro hazvitsanangure kuti sei BPF ichinyatso chinja mufananidzo uchienzaniswa neBPF yekare. Huviri hutsva hunowedzera zvakanyanya chiyero chekushanda ndiko kugona kushandisa yakagovaniswa ndangariro uye kernel mubatsiri mabasa. MuBPF, ndangariro yakagovaniswa inoshandiswa uchishandisa anonzi mamepu - akagovaniswa data zvimiro neiyo API chaiyo. Vangangove vaine zita iri nekuti mhando yekutanga yemepu kubuda yaive tafura yehashi. Ipapo mitsara yakaonekwa, emunharaunda (per-CPU) hashi matafura uye emunharaunda arrays, kutsvaga miti, mepu dzine anonongedzera kune BPF zvirongwa nezvimwe zvakawanda. Chiri kufadza kwatiri iko zvino ndechekuti zvirongwa zveBPF zvino zvave kugona kuramba nyika pakati pekufona uye kuigovana nemamwe mapurogiramu uye nenzvimbo yemushandisi.

Mamepu anowanikwa kubva kumashandisirwo emushandisi uchishandisa system call bpf(2), uye kubva kuBPF zvirongwa zvinomhanya mu kernel uchishandisa mabasa emubatsiri. Uyezve, vabatsiri varipo kwete chete kushanda nemamepu, asiwo kuwana mamwe kernel kugona. Semuenzaniso, zvirongwa zveBPF zvinogona kushandisa mabasa emubatsiri kutumira mapaketi kune mamwe mainterface, kugadzira zviitiko zveperf, kuwana kernel zvimiro, zvichingodaro.

BPF yevadiki, chikamu chekutanga: yakawedzera BPF

Muchidimbu, BPF inopa kugona kurodha zvisina tsarukano, kureva, verifier-yakaedzwa, mushandisi kodhi munzvimbo yekernel. Iyi kodhi inogona kuchengetedza nyika pakati pekufona uye kuchinjanisa data nenzvimbo yemushandisi, uye zvakare inokwanisa kuwana kernel subsystems inotenderwa nerudzi urwu rwechirongwa.

Izvi zvatove zvakafanana nekugona kunopihwa nekernel modules, zvichienzaniswa neiyo BPF ine zvimwe zvakanakira (zvechokwadi, iwe unogona chete kuenzanisa maapplication akafanana, semuenzaniso, system tracing - haugone kunyora anopokana mutyairi neBPF). Iwe unogona kucherechedza yakaderera yekupinda chikumbaridzo (zvimwe zvinoshandiswa zvinoshandisa BPF hazvidi kuti mushandisi ave nekernel programming hunyanzvi, kana hunyanzvi hwekugadzira zvakazara), runtime kuchengetedza (simudza ruoko rwako mune zvakataurwa kune avo vasina kutyora iyo system pakunyora. kana ma modules ekuedza), atomicity - pane nguva yekudzikira kana kurodhazve mamodules, uye iyo BPF subsystem inovimbisa kuti hapana zviitiko zvinopotswa (kuti zvive zvakanaka, izvi hazvisi zvechokwadi kune ese marudzi ezvirongwa zveBPF).

Kuvapo kwekugona kwakadaro kunoita kuti BPF ive chishandiso chepasi rose chekuwedzera kernel, iyo inosimbiswa mukuita: akawanda uye akawanda marudzi ezvirongwa anowedzerwa kuBPF, makambani mazhinji uye makuru anoshandisa BPF pamasevhisi ehondo 24 Γ— 7, zvakanyanya uye zvakanyanya. kutanga vanovaka bhizinesi ravo pane zvigadziriso zvichibva pane izvo zvinobva paBPF. BPF inoshandiswa kwese kwese: mukudzivirira kubva kuDDoS kurwiswa, kugadzira SDN (semuenzaniso, kuita network yekubernetes), seyakanyanya sisitimu yekuteedzera chishandiso uye muunganidzi wenhamba, mune intrusion yekuona masisitimu uye sandbox masisitimu, nezvimwe.

Ngatipedzei iyo yekutarisa chikamu chechinyorwa pano uye titarise iyo chaiyo muchina uye BPF ecosystem mune zvimwe zvakadzama.

Digression: zvishandiso

Kuti ukwanise kumhanyisa mienzaniso muzvikamu zvinotevera, ungangoda huwandu hwezvishandiso, zvirinani llvm/clang ne bpf rutsigiro uye bpftool... Muchitsauko Zvishandiso zvekuvandudza Iwe unogona kuverenga mirairo yekuunganidza zvishandiso, pamwe nekernel yako. Ichi chikamu chakaiswa pazasi kuti chisavhiringidza kuwirirana kwemharidzo yedu.

BPF Virtual Machine Registers uye Instruction System

Iyo yekuvaka uye yekuraira sisitimu yeBPF yakagadziridzwa tichifunga nezve chokwadi chekuti zvirongwa zvichanyorwa mumutauro weC uye, mushure mekurodha mu kernel, zvakashandurirwa mukodhi yekuzvarwa. Nokudaro, nhamba yezvinyorwa uye seti yemirairo yakasarudzwa neziso kune mharadzano, mupfungwa yemasvomhu, yekugona kwemichina yemazuva ano. Mukuwedzera, zvirambidzo zvakasiyana-siyana zvakaiswa pamapurogiramu, semuenzaniso, kusvika munguva pfupi yapfuura zvakanga zvisingabviri kunyora zvishwe uye subroutines, uye nhamba yemirairo yakanga yakaganhurirwa ku4096 (ikozvino mapurogiramu ane ropafadzo anogona kutakura kusvika kune mamiriyoni emirairo).

BPF ine gumi nerimwe-inosvikika 64-bit marejista r0-r10 uye program counter. Register r10 ine chinongedzo chefuremu uye inoverengwa-chete. Zvirongwa zvinokwanisa kuwana 512-byte stack panguva yekumhanya uye huwandu husingaverengeki hwekugovana ndangariro muchimiro chemepu.

Zvirongwa zveBPF zvinotenderwa kumhanyisa seti chaiyo yepurogiramu-mhando kernel vabatsiri uye, munguva pfupi yapfuura, mabasa enguva dzose. Imwe neimwe inonzi basa inogona kutora nharo dzinosvika shanu, dzakapfuudzwa mumarejista r1-r5, uye kukosha kwekudzoka kunopfuudzwa r0. Inovimbiswa kuti mushure mokudzoka kubva kubasa, zviri mukati mezvinyorwa r6-r9 Hazvizoshanduki.

Kuti ukwanise kududzira chirongwa, marejista r0-r11 kune ese anotsigirwa ekuvaka akaiswa mepu kune chaiwo marejista, tichifunga nezveABI maficha ezvivakwa zvazvino. Somuenzaniso, nokuda x86_64 mabhuku r1-r5, inoshandiswa kupfuudza ma parameter ekushanda, anoratidzwa rdi, rsi, rdx, rcx, r8, iyo inoshandiswa kupfuudza parameters kuti ishande pa x86_64. Semuenzaniso, iyo kodhi kuruboshwe inoshandura kune iyo kodhi kurudyi seizvi:

1:  (b7) r1 = 1                    mov    $0x1,%rdi
2:  (b7) r2 = 2                    mov    $0x2,%rsi
3:  (b7) r3 = 3                    mov    $0x3,%rdx
4:  (b7) r4 = 4                    mov    $0x4,%rcx
5:  (b7) r5 = 5                    mov    $0x5,%r8
6:  (85) call pc+1                 callq  0x0000000000001ee8

Bhalisa r0 zvakare yakashandiswa kudzorera mhedzisiro yekuitwa kwechirongwa, uye murejista r1 chirongwa chinopfuudzwa chinongedzo kumamiriro ezvinhu - zvichienderana nerudzi rwechirongwa, izvi zvinogona kuva, semuenzaniso, chimiro struct xdp_md (yeXDP) kana chimiro struct __sk_buff (yezvirongwa zvakasiyana zvetiweki) kana chimiro struct pt_regs (yemhando dzakasiyana dzezvirongwa zvekutevera), nezvimwe.

Saka, isu takanga tine seti yemarejista, kernel vabatsiri, stack, chinongedzo chinongedzo uye yakagovaniswa ndangariro muchimiro chemepu. Kwete kuti zvese izvi zvakakosha parwendo, asi ...

Ngatienderere mberi netsanangudzo uye titaure nezve yekuraira system yekushanda nezvinhu izvi. Zvese (Zvinenge zvese) BPF mirairo ine yakagadziriswa 64-bit size. Kana iwe ukatarisa kune imwe rairo pane 64-bit Big Endian muchina uchaona

BPF yevadiki, chikamu chekutanga: yakawedzera BPF

zviri Code - iyi ndiyo encoding yemurairo, Dst/Src ndiwo ma encodings emugamuchiri uye sosi, zvichiteerana, Off - 16-bit yakasainwa indentation, uye Imm i32-bit yakasainwa nhamba yakazara inoshandiswa mune mimwe mirairo (yakafanana neiyo cBPF inogara K). Encoding Code ine imwe yemhando mbiri:

BPF yevadiki, chikamu chekutanga: yakawedzera BPF

Makirasi ekuraira 0, 1, 2, 3 anotsanangura mirairo yekushanda nendangariro. Ivo vanodaidzwa, BPF_LD, BPF_LDX, BPF_ST, BPF_STX, zvichiteerana. Makirasi 4, 7 (BPF_ALU, BPF_ALU64) inoumba seti yemirairo yeALU. Makirasi 5, 6 (BPF_JMP, BPF_JMP32) ine mirairo yekusvetuka.

Iyo imwezve hurongwa hwekudzidza iyo BPF yekuraira sisitimu ndeiyi: pachinzvimbo chekunyora zvine hungwaru mirairo yese uye maparamendi avo, isu tichatarisa mienzaniso mishoma muchikamu chino uye kubva kwavari zvichabuda pachena kuti mirairo inoshanda sei uye maitiro ekuita. bvisa nemaoko chero bhinari faira reBPF. Kubatanidza zvinyorwa gare gare muchinyorwa, isu tichasanganawo nemirairo yega muzvikamu nezve Verifier, JIT compiler, dudziro yekirasi BPF, uye kana uchidzidza mepu, kufona mabasa, nezvimwe.

Apo patinotaura pamusoro pemirayiridzo yega yega, tichareva kune mafaira makuru bpf.h ΠΈ bpf_common.h, iyo inotsanangura nhamba dzenhamba dzemirairo yeBPF. Paunenge uchidzidza zvekuvaka uri wega uye/kana kupatsanura mabhinari, unogona kuwana semantics mune anotevera masosi, akarongwa mukurongeka kwekuoma: Unofficial eBPF spec, BPF uye XDP Reference Guide, Mirayiridzo Seti, Documentation/networking/filter.txt uye, hongu, muLinux source code - verifier, JIT, BPF muturikiri.

Muenzaniso: disassembling BPF mumusoro mako

Ngatitarisei muenzaniso watinogadzira chirongwa readelf-example.c uye tarisa zvinoguma binary. Ticharatidza zvinyorwa zvepakutanga readelf-example.c pazasi, mushure mekudzorera logic yayo kubva kumabhinari makodhi:

$ clang -target bpf -c readelf-example.c -o readelf-example.o -O2
$ llvm-readelf -x .text readelf-example.o
Hex dump of section '.text':
0x00000000 b7000000 01000000 15010100 00000000 ................
0x00000010 b7000000 02000000 95000000 00000000 ................

Koramu yekutanga mune zvabuda readelf indentation uye chirongwa chedu saka chine mirairo mina:

Code Dst Src Off  Imm
b7   0   0   0000 01000000
15   0   1   0100 00000000
b7   0   0   0000 02000000
95   0   0   0000 00000000

Makodhi emirairo akaenzana b7, 15, b7 ΠΈ 95. Rangarira kuti zvidiki zvidiki zvitatu ikirasi yekuraira. Kwatiri, chikamu chechina chemirairo yese hachina chinhu, saka makirasi ekuraira anoti 7, 5, 7, 5 zvichiteerana. BPF_ALU64,uye 5i BPF_JMP. Kune ese ari maviri makirasi, iyo yekuraira fomati yakafanana (ona pamusoro) uye isu tinogona kunyora zvakare chirongwa chedu seizvi (panguva imwe chete isu tichanyora patsva makoramu asara muchimiro chemunhu):

Op S  Class   Dst Src Off  Imm
b  0  ALU64   0   0   0    1
1  0  JMP     0   1   1    0
b  0  ALU64   0   0   0    2
9  0  JMP     0   0   0    0

Kushanda b kirasi ALU64 - ichi chi BPF_MOV. Inopa kukosha kune rejista yekuenda. Kana bhiti rakaiswa s (mabviro), ipapo kukosha kunotorwa kubva kubhuku rezvinyorwa, uye kana, sezvatiri isu, isina kuiswa, ipapo kukosha kunotorwa kubva kumunda. Imm. Saka mumirairo yekutanga neyechitatu tinoita oparesheni r0 = Imm. Kupfuurirazve, JMP kirasi 1 mashandiro ari BPF_JEQ (svetuka kana zvakaenzana). Muchiitiko chedu, kubvira zvishoma S iri zero, inofanidza kukosha kweiyo rejista regisheni nemunda Imm. Kana kukosha kwakabatana, ipapo shanduko inoitika kune PC + Offkupi PC, senguva dzose, ine kero yemurairo unotevera. Pakupedzisira, JMP Kirasi 9 Operation iri BPF_EXIT. Uyu murairo unogumisa purogiramu, kudzokera kune kernel r0. Ngatiwedzerei chikamu chitsva patafura yedu:

Op    S  Class   Dst Src Off  Imm    Disassm
MOV   0  ALU64   0   0   0    1      r0 = 1
JEQ   0  JMP     0   1   1    0      if (r1 == 0) goto pc+1
MOV   0  ALU64   0   0   0    2      r0 = 2
EXIT  0  JMP     0   0   0    0      exit

Tinogona kunyora izvi zvakare nenzira iri nyore:

     r0 = 1
     if (r1 == 0) goto END
     r0 = 2
END:
     exit

Kana tikarangarira zviri murejista r1 chirongwa chinopfuudzwa chinongedzo kumamiriro ezvinhu kubva ku kernel, uye murejista r0 kukosha kunodzoserwa kune kernel, zvino tinogona kuona kuti kana chinongedzo chechirevo chiri zero, tozodzosera 1, uye neimwe nzira - 2. Ngatitarisei kuti takarurama nekutarisa kunobva:

$ cat readelf-example.c
int foo(void *ctx)
{
        return ctx ? 2 : 1;
}

Hongu, chirongwa chisina zvachinoreva, asi chinoturikira mumirairo mina chete yakapfava.

Kunze kwemuenzaniso: 16-byte rairo

Takambotaura kuti mimwe mirairo inotora kupfuura 64 bits. Izvi zvinoshanda, semuenzaniso, kune mirairo lddw (Kodhi = 0x18 = BPF_LD | BPF_DW | BPF_IMM) - takura mazwi maviri kubva kuminda kupinda murejista Imm... Chokwadi ndechekuti Imm ine saizi ye32, uye izwi rembiri i64 bits, saka kurodha 64-bit yekukurumidza kukosha murejista mune imwe 64-bit rairo hazvishande. Kuti uite izvi, mirairo miviri yakatarisana inoshandiswa kuchengetedza chikamu chechipiri che 64-bit kukosha mumunda. Imm. Muenzaniso:

$ cat x64.c
long foo(void *ctx)
{
        return 0x11223344aabbccdd;
}
$ clang -target bpf -c x64.c -o x64.o -O2
$ llvm-readelf -x .text x64.o
Hex dump of section '.text':
0x00000000 18000000 ddccbbaa 00000000 44332211 ............D3".
0x00000010 95000000 00000000                   ........

Pane mirairo miviri chete mubhinari chirongwa:

Binary                                 Disassm
18000000 ddccbbaa 00000000 44332211    r0 = Imm[0]|Imm[1]
95000000 00000000                      exit

Tichasangana zvakare nemirayiridzo lddw, patinotaura nezvekutamiswa uye kushanda nemamepu.

Muenzaniso: disassembling BPF uchishandisa maturusi akajairwa

Saka, isu takadzidza kuverenga BPF mabhinari makodhi uye takagadzirira kupaza chero rairo kana zvichidikanwa. Nekudaro, zvakakosha kutaura kuti mukuita zviri nyore uye nekukurumidza kuparadzanisa zvirongwa uchishandisa zvakajairwa maturusi, semuenzaniso:

$ llvm-objdump -d x64.o

Disassembly of section .text:

0000000000000000 <foo>:
 0: 18 00 00 00 dd cc bb aa 00 00 00 00 44 33 22 11 r0 = 1234605617868164317 ll
 2: 95 00 00 00 00 00 00 00 exit

Hupenyu hwezvinhu zveBPF, bpffs faira system

(Ndakatanga ndadzidza zvimwe zvezvinotsanangurwa muchikamu chino kubva post Alexei Starovoitov BPF Blog.)

BPF zvinhu - zvirongwa uye mepu - zvinogadzirwa kubva munzvimbo yemushandisi uchishandisa mirairo BPF_PROG_LOAD ΠΈ BPF_MAP_CREATE system call bpf(2), tichataura pamusoro pekuti izvi zvinoitika sei muchikamu chinotevera. Izvi zvinogadzira kernel data zvimiro uye kune yega yega refcount (reference count) inoiswa kune imwe, uye faira rinotsanangura rinongedza chinhu rinodzoserwa kumushandisi. Mushure mokunge mubato wakavharwa refcount chinhu chacho chinoderedzwa nechimwe, uye kana chasvika zero, chinhu chacho chinoparadzwa.

Kana iyo purogiramu inoshandisa mamepu, saka refcount mamepu aya anowedzerwa neimwe mushure mekurodha chirongwa, i.e. avo faira descriptors anogona kuvharwa kubva mushandisi maitiro uye zvakadaro refcount haizove zero:

BPF yevadiki, chikamu chekutanga: yakawedzera BPF

Mushure mekubudirira kurodha chirongwa, isu tinowanzo batanidza kune imwe mhando yechiitiko jenareta. Semuenzaniso, tinogona kuiisa pane network interface kuti tigadzirise anouya mapaketi kana kuibatanidza kune mamwe tracepoint mukatikati. Panguva ino, referensi counter ichawedzerawo neimwe uye isu tichakwanisa kuvhara iyo faira descriptor muloader chirongwa.

Chii chinoitika kana isu zvino tikavhara iyo bootloader? Izvo zvinoenderana nerudzi rwechiitiko jenareta (hook). Ese mahokwe etiweki anozovepo mushure mekunge mutakuri apedza, aya ndiwo anonzi mahokwe epasi rose. Uye, semuenzaniso, zvirongwa zvekuteedzera zvichaburitswa mushure mekunge maitiro akaagadzira apera (uye nekudaro anonzi emunharaunda, kubva "munzvimbo kuenda kune maitiro"). Nehunyanzvi, hoko dzemuno dzinogara dziine inowirirana faira descriptor munzvimbo yemushandisi uye saka inovhara kana maitiro akavharwa, asi hoko dzepasirese hadzina. Mumufananidzo unotevera, ndichishandisa michinjikwa mitsvuku, ndinoedza kuratidza kuti kugumiswa kwechirongwa chekurodha kunobata sei hupenyu hwezvinhu munyaya yezvikorekedzo zvemuno uye zvepasi rose.

BPF yevadiki, chikamu chekutanga: yakawedzera BPF

Sei paine musiyano pakati pehoko dzemuno nedzepasirese? Kumhanya mamwe marudzi ezvirongwa zvetiweki zvine musoro pasina nzvimbo yekushandisa, semuenzaniso, fungidzira DDoS kudzivirira - iyo bootloader inonyora mitemo uye inobatanidza chirongwa cheBPF kune network network, mushure meiyo bootloader inogona kuenda ndokuzviuraya. Kune rimwe divi, fungidzira chirongwa chekugadzirisa dhizaini chawakanyora pamabvi ako mumaminitsi gumi - kana yapera, ungade kuti pasave nemarara asara muhurongwa, uye zvikorekedzo zvemuno zvinovimbisa izvozvo.

Kune rimwe divi, fungidzira kuti iwe unoda kubatanidza kune tracepoint mu kernel uye kuunganidza nhamba mumakore mazhinji. Mune ino kesi, iwe ungada kupedzisa mushandisi chikamu uye kudzokera kune manhamba nguva nenguva. Iyo bpf faira system inopa mukana uyu. Iyo in-memory-chete pseudo-file system inobvumira kusikwa kwemafaira anoreva zvinhu zveBPF uye nekudaro kuwedzera. refcount zvinhu. Mushure meizvi, mutakuri anogona kubuda, uye zvinhu zvaakagadzira zvicharamba zviri zvipenyu.

BPF yevadiki, chikamu chekutanga: yakawedzera BPF

Kugadzira mafaera mubpffs anonongedzera BPF zvinhu anonzi "pinning" (semumutsara unotevera: "maitiro anogona kubaya chirongwa cheBPF kana mepu"). Kugadzira zvinhu zvefaira zvezvinhu zveBPF zvine musoro kwete chete pakuwedzera hupenyu hwezvinhu zvemuno, asiwo nekushandiswa kwezvinhu zvepasi rose - kudzokera kumuenzaniso nechirongwa chekudzivirira cheDDoS chepasi rose, tinoda kukwanisa kuuya uye kutarisa manhamba. nguva nenguva.

Iyo BPF faira system inowanzoiswa mukati /sys/fs/bpf, asi inogonawo kuiswa munzvimbo, semuenzaniso, seizvi:

$ mkdir bpf-mountpoint
$ sudo mount -t bpf none bpf-mountpoint

Mazita ehurongwa hwemafaira anogadzirwa uchishandisa rairo BPF_OBJ_PIN BPF system call. Kuenzanisira, ngatitorei purogiramu, tiigadzirise, tiiise, uye tiinanidze kwairi bpffs. Chirongwa chedu hachiite chero chinhu chinobatsira, isu tiri kungoratidza kodhi kuti iwe ugone kuburitsa muenzaniso:

$ cat test.c
__attribute__((section("xdp"), used))
int test(void *ctx)
{
        return 0;
}

char _license[] __attribute__((section("license"), used)) = "GPL";

Ngatiunganidzei chirongwa ichi uye tigadzire kopi yemuno yefaira system bpffs:

$ clang -target bpf -c test.c -o test.o
$ mkdir bpf-mountpoint
$ sudo mount -t bpf none bpf-mountpoint

Iye zvino ngatitorei purogiramu yedu tichishandisa zvinoshandiswa bpftool uye tarisa kune inoperekedza system mafoni bpf(2) (mimwe mitsetse isina basa yakabviswa kubva pakubuda kwestrace):

$ sudo strace -e bpf bpftool prog load ./test.o bpf-mountpoint/test
bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_XDP, prog_name="test", ...}, 120) = 3
bpf(BPF_OBJ_PIN, {pathname="bpf-mountpoint/test", bpf_fd=3}, 120) = 0

Pano takaisa purogiramu tichishandisa BPF_PROG_LOAD, yakagamuchira descriptor yefaira kubva kukernel 3 uye kushandisa murairo BPF_OBJ_PIN akapinira iyi faira descriptor sefaira "bpf-mountpoint/test". Mushure meizvi chirongwa chebootloader bpftool akapedza kushanda, asi chirongwa chedu chakaramba chiri mu kernel, kunyangwe isu tisina kubatanidza kune chero network network:

$ sudo bpftool prog | tail -3
783: xdp  name test  tag 5c8ba0cf164cb46c  gpl
        loaded_at 2020-05-05T13:27:08+0000  uid 0
        xlated 24B  jited 41B  memlock 4096B

Tinogona kudzima chinhu chefaira kazhinji unlink(2) uye mushure meizvozvo purogiramu inoenderana ichabviswa:

$ sudo rm ./bpf-mountpoint/test
$ sudo bpftool prog show id 783
Error: get by id (783): No such file or directory

Kudzima zvinhu

Kutaura nezve kudzima zvinhu, zvinodikanwa kujekesa kuti mushure mekunge tabvisa chirongwa kubva kuhoko (jenareta yechiitiko), hapana kana chiitiko chitsva chichatanga kutanga kwayo, zvisinei, zviitiko zvese zvazvino zvechirongwa zvichapedzwa nenzira yakajairika. .

Mamwe marudzi ezvirongwa zveBPF anokubvumira kutsiva purogiramu pane nhunzi, i.e. kupa kutevedzana atomicity replace = detach old program, attach new program. Muchiitiko ichi, zviitiko zvose zvinoshanda zveshanduro yekare yepurogiramu ichapedza basa ravo, uye vatsva vezviitiko vachagadzirwa kubva purogiramu itsva, uye "atomicity" pano inoreva kuti hapana chiitiko chimwe chete chichashaikwa.

Kubatanidza mapurogiramu kune zvinyorwa zvezviitiko

Muchinyorwa chino, isu hatizotsanangure zvakasiyana kubatanidza zvirongwa kune zviitiko masosi, nekuti zvine musoro kudzidza izvi mumamiriro emhando yechirongwa. Cm. muenzaniso pazasi, umo isu tinoratidza kuti zvirongwa zvakaita seXDP zvakabatana sei.

Kugadzirisa Zvinhu Uchishandisa iyo bpf System Call

BPF zvirongwa

Zvese zvinhu zveBPF zvinogadzirwa uye zvinogadziriswa kubva munzvimbo yemushandisi uchishandisa kufona system bpf, ine inotevera prototype:

#include <linux/bpf.h>

int bpf(int cmd, union bpf_attr *attr, unsigned int size);

Heino timu cmd ndeimwe yemhando dzemhando enum bpf_cmd, attr - chinongedzo kune ma parameter echimwe chirongwa uye size - saizi yechinhu maererano neinongedza, i.e. kazhinji izvi sizeof(*attr). Mu kernel 5.8 iyo system call bpf inotsigira 34 mirairo yakasiyana, uye tsanangudzo union bpf_attr inotora mitsara mazana maviri. Asi isu hatifanirwe kutyisidzirwa neizvi, sezvo isu tichave tichizvijaira isu nemirairo uye ma parameter mukati mekufamba kwezvinyorwa zvakati wandei.

Ngatitange nechikwata BPF_PROG_LOAD, iyo inogadzira zvirongwa zveBPF - inotora seti yemirairo yeBPF uye inoiisa mu kernel. Panguva yekurodha, verifier inotangwa, uyezve iyo JIT compiler uye, mushure mekuita kwakabudirira, iyo purogiramu faira descriptor inodzoserwa kumushandisi. Takaona zvichaitika kwaari muchikamu chapfuura nezve kutenderera kwehupenyu hweBPF zvinhu.

Iye zvino tichanyora chirongwa chetsika chinotakura chirongwa chakareruka cheBPF, asi chekutanga tinoda kusarudza rudzi rwechirongwa chatinoda kurodha - isu tichafanirwa kusarudza. mhando uye mukati megadziriro yerudzi urwu, nyora chirongwa chichapfuura bvunzo yeverifier. Nekudaro, kuti urege kuomesa maitiro, heino mhinduro yakagadzirira: isu tichatora chirongwa senge BPF_PROG_TYPE_XDP, iyo ichadzorera kukosha XDP_PASS (ruka mapakeji ese). MuBPF assembler inotaridzika yakapusa:

r0 = 2
exit

Mushure mekunge tasarudza kuti isu tichaisa, tinogona kukuudza kuti tichazviita sei:

#define _GNU_SOURCE
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/bpf.h>

static inline __u64 ptr_to_u64(const void *ptr)
{
        return (__u64) (unsigned long) ptr;
}

int main(void)
{
    struct bpf_insn insns[] = {
        {
            .code = BPF_ALU64 | BPF_MOV | BPF_K,
            .dst_reg = BPF_REG_0,
            .imm = XDP_PASS
        },
        {
            .code = BPF_JMP | BPF_EXIT
        },
    };

    union bpf_attr attr = {
        .prog_type = BPF_PROG_TYPE_XDP,
        .insns     = ptr_to_u64(insns),
        .insn_cnt  = sizeof(insns)/sizeof(insns[0]),
        .license   = ptr_to_u64("GPL"),
    };

    strncpy(attr.prog_name, "woo", sizeof(attr.prog_name));
    syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));

    for ( ;; )
        pause();
}

Zviitiko zvinonakidza muchirongwa zvinotanga netsanangudzo yehurongwa insns - yedu BPF chirongwa mumashini kodhi. Muchiitiko ichi, kuraira kwega kwega kweBPF chirongwa chakazara muchimiro bpf_insn. Chinhu chekutanga insns zvinoenderana nemirairo r0 = 2, wechipiri - exit.

Retreat. Iyo kernel inotsanangura mamwe ari nyore macros ekunyora makodhi makodhi, uye kushandisa iyo kernel musoro faira tools/include/linux/filter.h taigona kunyora

struct bpf_insn insns[] = {
    BPF_MOV64_IMM(BPF_REG_0, XDP_PASS),
    BPF_EXIT_INSN()
};

Asi kubva pakunyora zvirongwa zveBPF mukodhi yeko zvinongodiwa pakunyora bvunzo mukernel uye zvinyorwa nezveBPF, kusavapo kweaya macros hakunyatso kuomesa hupenyu hwemugadziri.

Mushure mekutsanangura chirongwa cheBPF, tinoenderera mberi nekuiisa mu kernel. Yedu minimalist seti yemaparamita attr inosanganisira rudzi rwechirongwa, seti uye nhamba yemirairo, rezinesi rinodiwa, uye zita "woo", iyo yatinoshandisa kuwana chirongwa chedu pane system mushure mekurodha. Iyo purogiramu, sezvakavimbiswa, inotakurwa muhurongwa uchishandisa nharembozha bpf.

Pakupera kwechirongwa isu tinopedzisira tave mune isingaperi loop inotevedzera iyo mubhadharo. Pasina iyo, chirongwa chinozourayiwa nekernel kana iyo faira inotsanangura iyo system yekufona yakadzoserwa kwatiri yakavharwa. bpf, uye isu hatizvione muhurongwa.

Zvakanaka, takagadzirira kuongororwa. Ngatiungane uye tiite chirongwa pasi stracekutarisa kuti zvese zviri kushanda sezvazvinofanira:

$ clang -g -O2 simple-prog.c -o simple-prog

$ sudo strace ./simple-prog
execve("./simple-prog", ["./simple-prog"], 0x7ffc7b553480 /* 13 vars */) = 0
...
bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_XDP, insn_cnt=2, insns=0x7ffe03c4ed50, license="GPL", log_level=0, log_size=0, log_buf=NULL, kern_version=KERNEL_V
ERSION(0, 0, 0), prog_flags=0, prog_name="woo", prog_ifindex=0, expected_attach_type=BPF_CGROUP_INET_INGRESS}, 72) = 3
pause(

Zvese zvakanaka, bpf(2) akadzosera mubato 3 kwatiri uye takapinda infinite loop na pause(). Ngatiedzei kutsvaga chirongwa chedu muhurongwa. Kuti tiite izvi tichaenda kune imwe terminal uye toshandisa iyo yekushandisa bpftool:

# bpftool prog | grep -A3 woo
390: xdp  name woo  tag 3b185187f1855c4c  gpl
        loaded_at 2020-08-31T24:66:44+0000  uid 0
        xlated 16B  jited 40B  memlock 4096B
        pids simple-prog(10381)

Isu tinoona kuti pane chirongwa chakaremerwa pane system woo ane ID yepasi rose i390 uye parizvino iri kuenderera mberi simple-prog pane yakavhurika faira descriptor inonongedza kuchirongwa (uye kana simple-prog achapedzisa basa, ipapo woo ichanyangarika). Sezvinotarisirwa, purogiramu woo inotora 16 bytes - mirairo miviri - yebhinari codes muBPF architecture, asi mumutauro wayo (x86_64) yatova 40 bytes. Ngatitarisei chirongwa chedu muchimiro chayo chepakutanga:

# bpftool prog dump xlated id 390
   0: (b7) r0 = 2
   1: (95) exit

hapana zvinoshamisa. Zvino ngatitarisei iyo kodhi inogadzirwa neJIT compiler:

# bpftool prog dump jited id 390
bpf_prog_3b185187f1855c4c_woo:
   0:   nopl   0x0(%rax,%rax,1)
   5:   push   %rbp
   6:   mov    %rsp,%rbp
   9:   sub    $0x0,%rsp
  10:   push   %rbx
  11:   push   %r13
  13:   push   %r14
  15:   push   %r15
  17:   pushq  $0x0
  19:   mov    $0x2,%eax
  1e:   pop    %rbx
  1f:   pop    %r15
  21:   pop    %r14
  23:   pop    %r13
  25:   pop    %rbx
  26:   leaveq
  27:   retq

haishande zvakanyanya kune exit(2), asi mukururama, chirongwa chedu chakanyanya kupusa, uye kune zvisiri-zvidiki zvirongwa chirevo uye epilogue inowedzerwa neJIT compiler inodiwa, hongu.

Mepu

Zvirongwa zveBPF zvinogona kushandisa nzvimbo dzakarongeka dzekurangarira dzinowanikwa kune mamwe mapurogiramu eBPF uye kumapurogiramu ari munzvimbo yemushandisi. Zvinhu izvi zvinodaidzwa kunzi mepu uye muchikamu chino ticharatidza nzira yekuzvinyengedza uchishandisa system call bpf.

Ngatitii ipapo ipapo kuti kugona kwemepu hakungogumiri pakuwana kune yakagovaniswa ndangariro. Kune akakosha-chinangwa mepu ane, semuenzaniso, anonongedzera kune BPF zvirongwa kana anonongedzera kunetiweki interfaces, mepu dzekushanda nezviitiko zveperf, nezvimwe. Hatichataura nezvavo pano, kuitira kuti tisavhiringa muverengi. Kunze kweizvi, isu tinoregeredza nyaya dzekuwiriranisa, sezvo izvi zvisina kukosha kune yedu mienzaniso. Rondedzero yakazara yemhando dzemepu dziripo dzinogona kuwanikwa mukati <linux/bpf.h>, uye muchikamu chino tichatora semuenzaniso wenhoroondo yekutanga mhando, iyo hashi tafura BPF_MAP_TYPE_HASH.

Kana iwe ukagadzira tafura yehashi mukati, iti, C ++, ungati unordered_map<int,long> woo, iro muchiRussian rinoreva kuti β€œNdinoda tafura woo saizi isina muganho, makiyi ayo ndeemhando int, uye kukosha ndiyo mhando long" Kuti tigadzire tafura yeBPF hashi, isu tinofanirwa kuita chinhu chimwe chete, kunze kwekuti isu tinofanirwa kutsanangura hukuru hwetafura, uye pachinzvimbo chekutsanangura marudzi emakiyi uye kukosha, isu tinofanirwa kutsanangura hukuru hwavo mumabhayiti. . Kugadzira mamepu shandisa rairo BPF_MAP_CREATE system call bpf. Ngatitarisei purogiramu shoma kana shoma inogadzira mepu. Mushure mechirongwa chakapfuura chinotakura zvirongwa zveBPF, iyi inofanirwa kuita seyakapusa kwauri:

$ cat simple-map.c
#define _GNU_SOURCE
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/bpf.h>

int main(void)
{
    union bpf_attr attr = {
        .map_type = BPF_MAP_TYPE_HASH,
        .key_size = sizeof(int),
        .value_size = sizeof(int),
        .max_entries = 4,
    };
    strncpy(attr.map_name, "woo", sizeof(attr.map_name));
    syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));

    for ( ;; )
        pause();
}

Pano tinotsanangura seti yezvipimo attr, umo tinoti β€œNdinoda tafura yehashi ine makiyi uye saizi kukosha sizeof(int), umo ndinogona kuisa zvinhu zvina zvinokwana." Paunenge uchigadzira mamepu eBPF, unogona kutsanangura mamwe ma paramita, semuenzaniso, nenzira imwecheteyo sepamuenzaniso nechirongwa, takatsanangura zita rechinhu se. "woo".

Ngatiunganidze uye tiite chirongwa:

$ clang -g -O2 simple-map.c -o simple-map
$ sudo strace ./simple-map
execve("./simple-map", ["./simple-map"], 0x7ffd40a27070 /* 14 vars */) = 0
...
bpf(BPF_MAP_CREATE, {map_type=BPF_MAP_TYPE_HASH, key_size=4, value_size=4, max_entries=4, map_name="woo", ...}, 72) = 3
pause(

Heino system call bpf(2) akatidzosera nhamba yemepu yekutsanangura 3 uye ipapo purogiramu, sezvaitarisirwa, inomirira mimwe mirairo muhurongwa hwekufona pause(2).

Zvino ngatitumirei chirongwa chedu kumashure kana kuvhura imwe terminal uye titarise chinhu chedu tichishandisa chishandiso bpftool (tinokwanisa kusiyanisa mepu yedu kubva kune vamwe nemazita ayo):

$ sudo bpftool map
...
114: hash  name woo  flags 0x0
        key 4B  value 4B  max_entries 4  memlock 4096B
...

Nhamba 114 ndiyo ID yepasi rose yechinhu chedu. Chero chirongwa chiri pahurongwa chinogona kushandisa ID iyi kuvhura mepu iripo uchishandisa rairo BPF_MAP_GET_FD_BY_ID system call bpf.

Iye zvino tinogona kutamba netafura yedu yehashi. Ngatitarisei zvirimo:

$ sudo bpftool map dump id 114
Found 0 elements

Empty. Ngatiise kukosha mairi hash[1] = 1:

$ sudo bpftool map update id 114 key 1 0 0 0 value 1 0 0 0

Ngatitarisei patafura zvakare:

$ sudo bpftool map dump id 114
key: 01 00 00 00  value: 01 00 00 00
Found 1 element

Hooray! Takakwanisa kuwedzera chinhu chimwe chete. Ziva kuti isu tinofanirwa kushanda padanho rekuita kuti tiite izvi, kubvira bptftool haazive mhando dzemhando dziri muhashi tafura. (Ruzivo urwu runogona kuendeswa kwaari uchishandisa BTF, asi zvimwe pane izvozvi.)

Bpftool inoverenga uye kuwedzera zvinhu sei chaizvo? Ngatitarisei pasi pehodhi:

$ sudo strace -e bpf bpftool map dump id 114
bpf(BPF_MAP_GET_FD_BY_ID, {map_id=114, next_id=0, open_flags=0}, 120) = 3
bpf(BPF_MAP_GET_NEXT_KEY, {map_fd=3, key=NULL, next_key=0x55856ab65280}, 120) = 0
bpf(BPF_MAP_LOOKUP_ELEM, {map_fd=3, key=0x55856ab65280, value=0x55856ab652a0}, 120) = 0
key: 01 00 00 00  value: 01 00 00 00
bpf(BPF_MAP_GET_NEXT_KEY, {map_fd=3, key=0x55856ab65280, next_key=0x55856ab65280}, 120) = -1 ENOENT

Kutanga takavhura mepu neayo ID yepasirese tichishandisa rairo BPF_MAP_GET_FD_BY_ID ΠΈ bpf(2) akadzosa tsananguro kwatiri 3. Uyezve uchishandisa murairo BPF_MAP_GET_NEXT_KEY takawana kiyi yekutanga mutafura nekupfuura NULL sechinongedzo kukiyi "yapfuura". Kana tine kiyi tinokwanisa kuita BPF_MAP_LOOKUP_ELEMiyo inodzosera kukosha kune chinongedzo value. Nhanho inotevera isu tinoedza kutsvaga chinhu chinotevera nekupfuura chinongedzo kune kiyi iripo, asi tafura yedu ine chinhu chimwe chete uye murairo. BPF_MAP_GET_NEXT_KEY anodzoka ENOENT.

Zvakanaka, ngatichinje kukosha nekiyi 1, ngatiti yedu bhizinesi logic inoda kunyoresa hash[1] = 2:

$ sudo strace -e bpf bpftool map update id 114 key 1 0 0 0 value 2 0 0 0
bpf(BPF_MAP_GET_FD_BY_ID, {map_id=114, next_id=0, open_flags=0}, 120) = 3
bpf(BPF_MAP_UPDATE_ELEM, {map_fd=3, key=0x55dcd72be260, value=0x55dcd72be280, flags=BPF_ANY}, 120) = 0

Sezvinotarisirwa, zviri nyore kwazvo: murairo BPF_MAP_GET_FD_BY_ID inovhura mepu yedu neID, uye murairo BPF_MAP_UPDATE_ELEM inobvisa chinhu.

Saka, mushure mekugadzira tafura yehashi kubva kune imwe purogiramu, tinogona kuverenga nekunyora zvirimo kubva kune imwe. Ziva kuti kana isu takakwanisa kuita izvi kubva pamutsetse wekuraira, saka chero imwe chirongwa pane system inogona kuzviita. Pamusoro pemirairo yakatsanangurwa pamusoro, yekushanda nemamepu kubva munzvimbo yemushandisi, zvinotevera:

  • BPF_MAP_LOOKUP_ELEM: tsvaga kukosha nekiyi
  • BPF_MAP_UPDATE_ELEM: gadziridza/gadzira kukosha
  • BPF_MAP_DELETE_ELEM: bvisa kiyi
  • BPF_MAP_GET_NEXT_KEY: tsvaga inotevera (kana yekutanga) kiyi
  • BPF_MAP_GET_NEXT_ID: inokubvumira kuti uende nepakati pemamepu ese aripo, ndiwo mashandiro ayo bpftool map
  • BPF_MAP_GET_FD_BY_ID: vhura mepu iripo nepasi rose ID
  • BPF_MAP_LOOKUP_AND_DELETE_ELEM: atomic gadzirisa kukosha kwechinhu uye dzorera chekare
  • BPF_MAP_FREEZE: ita kuti mepu isashanduke kubva munzvimbo yevashandisi (kushanda uku hakugone kuregererwa)
  • BPF_MAP_LOOKUP_BATCH, BPF_MAP_LOOKUP_AND_DELETE_BATCH, BPF_MAP_UPDATE_BATCH, BPF_MAP_DELETE_BATCH: mabasa akawanda. Semuyenzaniso, BPF_MAP_LOOKUP_AND_DELETE_BATCH - iyi ndiyo yega nzira yakavimbika yekuverenga uye kuseta patsva maitiro kubva pamepu

Haisi yese yemirairo iyi inoshanda kune ese marudzi emepu, asi kazhinji kushanda nemamwe marudzi emepu kubva munzvimbo yemushandisi inotaridzika chaizvo sekushanda nematafura ehashi.

Nekuda kwehurongwa, ngatipedzei maedzo edu etafura yehashi. Rangarira kuti isu takagadzira tafura inogona kuve nemakiyi mana? Ngatiwedzere zvimwe zvishoma:

$ sudo bpftool map update id 114 key 2 0 0 0 value 1 0 0 0
$ sudo bpftool map update id 114 key 3 0 0 0 value 1 0 0 0
$ sudo bpftool map update id 114 key 4 0 0 0 value 1 0 0 0

Kusvika ikozvino zvakanaka:

$ sudo bpftool map dump id 114
key: 01 00 00 00  value: 01 00 00 00
key: 02 00 00 00  value: 01 00 00 00
key: 04 00 00 00  value: 01 00 00 00
key: 03 00 00 00  value: 01 00 00 00
Found 4 elements

Ngatiedzei kuwedzera imwe zvakare:

$ sudo bpftool map update id 114 key 5 0 0 0 value 1 0 0 0
Error: update failed: Argument list too long

Sezvaitarisirwa, hatina kubudirira. Ngatitarisei kukanganisa mune zvakadzama:

$ sudo strace -e bpf bpftool map update id 114 key 5 0 0 0 value 1 0 0 0
bpf(BPF_MAP_GET_FD_BY_ID, {map_id=114, next_id=0, open_flags=0}, 120) = 3
bpf(BPF_OBJ_GET_INFO_BY_FD, {info={bpf_fd=3, info_len=80, info=0x7ffe6c626da0}}, 120) = 0
bpf(BPF_MAP_UPDATE_ELEM, {map_fd=3, key=0x56049ded5260, value=0x56049ded5280, flags=BPF_ANY}, 120) = -1 E2BIG (Argument list too long)
Error: update failed: Argument list too long
+++ exited with 255 +++

Zvese zvakanaka: sezvaitarisirwa, timu BPF_MAP_UPDATE_ELEM inoedza kugadzira nyowani, yechishanu, kiyi, asi inokanganisa E2BIG.

Saka, isu tinokwanisa kugadzira uye kurodha zvirongwa zveBPF, pamwe nekugadzira nekugadzirisa mamepu kubva munzvimbo yemushandisi. Zvino zvine musoro kutarisa kuti tingashandisa sei mamepu kubva kuzvirongwa zveBPF pachavo. Tinogona kutaura pamusoro peizvi mumutauro wezvirongwa zvakaoma-kuverenga-mumakina macro codes, asi chokwadi yasvika nguva yekuratidza kuti zvirongwa zveBPF zvinonyorwa sei uye zvinochengetwa - uchishandisa. libbpf.

(Kune vaverengi vasingagutsikane nekushaikwa kwemuenzaniso wakaderera: isu tichaongorora zvakadzama zvirongwa zvinoshandisa mepu uye mabasa emubatsiri akagadzirwa uchishandisa. libbpf uye ndikuudze zvinoitika padanho rekuraira. Kune vaverengi vasingagutsikani zvakanyanya, takawedzera muenzaniso panzvimbo yakakodzera muchinyorwa.)

Kunyora zvirongwa zveBPF uchishandisa libbpf

Kunyora zvirongwa zveBPF uchishandisa makodhi emuchina zvinogona kunakidza chete kekutanga, uyezve satiety inopinda. Panguva ino iwe unofanirwa kutendeudzira pfungwa dzako kune llvm, iyo ine backend yekugadzira kodhi yeBPF yekuvakisa, pamwe neraibhurari libbpf, iyo inokutendera iwe kunyora mushandisi wedivi reBPF application uye kurodha kodhi yeBPF zvirongwa zvinogadzirwa uchishandisa llvm/clang.

Muchokwadi, sezvatichaona mune ino uye inotevera zvinyorwa, libbpf anoita basa rakawanda pasina iyo (kana maturusi akafanana - iproute2, libbcc, libbpf-go, etc.) hazvibviri kurarama. Chimwe chezvinhu zvinouraya zvepurojekiti libbpf is BPF CO-RE (Compile Kamwe, Mhanya Kwese) - chirongwa chinokubvumira kunyora zvirongwa zveBPF zvinotakurika kubva kune imwe kernel kuenda kune imwe, nekugona kumhanya pane akasiyana APIs (semuenzaniso, kana iyo kernel chimiro ichichinja kubva mushanduro. kune shanduro). Kuti ukwanise kushanda neCO-RE, kernel yako inofanirwa kuunganidzwa nerutsigiro rweBTF (tinotsanangura maitiro ekuita izvi muchikamu. Zvishandiso zvekuvandudza. Unogona kutarisa kana kernel yako yakavakwa neBTF kana kuti kwete zvakanyanya - nekuvapo kweinotevera faira:

$ ls -lh /sys/kernel/btf/vmlinux
-r--r--r-- 1 root root 2.6M Jul 29 15:30 /sys/kernel/btf/vmlinux

Iri faira rinochengeta ruzivo nezve ese data marudzi anoshandiswa mukernel uye rinoshandiswa mumienzaniso yedu yese tichishandisa libbpf. Tichataura zvakadzama nezve CO-RE muchinyorwa chinotevera, asi mune ino - ingozvivakira kernel nayo CONFIG_DEBUG_INFO_BTF.

raibhurari libbpf anogara mudhairekitori tools/lib/bpf kernel uye kukura kwayo kunoitwa kuburikidza netsamba yekutumira [email protected]. Nekudaro, nzvimbo yakaparadzana inochengeterwa zvinodiwa zvekushandisa zvinogara kunze kwekernel https://github.com/libbpf/libbpf umo raibhurari yekernel inoratidzirwa yekuverenga kuverenga zvakanyanya kana zvishoma sezvazviri.

Muchikamu chino tichatarisa kuti ungagadzira sei chirongwa chinoshandisa libbpf, ngatinyore akati wandei (zvakawanda kana zvisingabatsiri) bvunzo zvirongwa uye tiongorore zvakadzama kuti zvese zvinoshanda sei. Izvi zvinotitendera kutsanangura zviri nyore muzvikamu zvinotevera kuti zvirongwa zveBPF zvinodyidzana sei nemamepu, kernel vabatsiri, BTF, nezvimwe.

Kazhinji mapurojekiti anoshandiswa libbpf wedzera GitHub repository segit submodule, isu tichaita zvimwe chete:

$ mkdir /tmp/libbpf-example
$ cd /tmp/libbpf-example/
$ git init-db
Initialized empty Git repository in /tmp/libbpf-example/.git/
$ git submodule add https://github.com/libbpf/libbpf.git
Cloning into '/tmp/libbpf-example/libbpf'...
remote: Enumerating objects: 200, done.
remote: Counting objects: 100% (200/200), done.
remote: Compressing objects: 100% (103/103), done.
remote: Total 3354 (delta 101), reused 118 (delta 79), pack-reused 3154
Receiving objects: 100% (3354/3354), 2.05 MiB | 10.22 MiB/s, done.
Resolving deltas: 100% (2176/2176), done.

Kuenda ku libbpf zvakapusa:

$ cd libbpf/src
$ mkdir build
$ OBJDIR=build DESTDIR=root make -s install
$ find root
root
root/usr
root/usr/include
root/usr/include/bpf
root/usr/include/bpf/bpf_tracing.h
root/usr/include/bpf/xsk.h
root/usr/include/bpf/libbpf_common.h
root/usr/include/bpf/bpf_endian.h
root/usr/include/bpf/bpf_helpers.h
root/usr/include/bpf/btf.h
root/usr/include/bpf/bpf_helper_defs.h
root/usr/include/bpf/bpf.h
root/usr/include/bpf/libbpf_util.h
root/usr/include/bpf/libbpf.h
root/usr/include/bpf/bpf_core_read.h
root/usr/lib64
root/usr/lib64/libbpf.so.0.1.0
root/usr/lib64/libbpf.so.0
root/usr/lib64/libbpf.a
root/usr/lib64/libbpf.so
root/usr/lib64/pkgconfig
root/usr/lib64/pkgconfig/libbpf.pc

Hurongwa hwedu hunotevera muchikamu chino ndohunotevera: tichanyora chirongwa cheBPF se BPF_PROG_TYPE_XDP, zvakafanana nemuenzaniso wapfuura, asi muC, tinoiunganidza tichishandisa clang, uye nyora chirongwa chekubatsira chinozochiisa mu kernel. Muzvikamu zvinotevera tichawedzera kugona kwezvose zviri zviviri chirongwa cheBPF uye chirongwa chemubatsiri.

Muenzaniso: kugadzira yakazara-yakazara application uchishandisa libbpf

Kutanga, tinoshandisa faira /sys/kernel/btf/vmlinux, iyo yakataurwa pamusoro, uye gadzira yakaenzana nayo muchimiro chemusoro faira:

$ bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h

Iri faira rinochengeta ese data zvimiro zviripo mukernel yedu, semuenzaniso, iyi ndiyo nzira iyo IPv4 musoro unotsanangurwa mu kernel:

$ grep -A 12 'struct iphdr {' vmlinux.h
struct iphdr {
    __u8 ihl: 4;
    __u8 version: 4;
    __u8 tos;
    __be16 tot_len;
    __be16 id;
    __be16 frag_off;
    __u8 ttl;
    __u8 protocol;
    __sum16 check;
    __be32 saddr;
    __be32 daddr;
};

Iye zvino tichanyora chirongwa chedu cheBPF muC:

$ cat xdp-simple.bpf.c
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>

SEC("xdp/simple")
int simple(void *ctx)
{
        return XDP_PASS;
}

char LICENSE[] SEC("license") = "GPL";

Kunyange zvazvo purogiramu yedu yakava yakapfava zvikuru, tichiri kufanira kupa ngwariro kuzvinhu zvakawanda. Kutanga, iyo yekutanga musoro faira yatinosanganisira ndeye vmlinux.h, izvo zvatichangobva kugadzira tichishandisa bpftool btf dump - ikozvino isu hatidi kuisa iyo kernel-headers package kuti tizive kuti kernel zvimiro zvinotaridzika sei. Iyo inotevera musoro faira inouya kwatiri kubva kuraibhurari libbpf. Iye zvino isu tinongoda iyo chete kutsanangura iyo macro SEC, iyo inotumira chimiro kune chikamu chakakodzera che ELF chinhu faira. Chirongwa chedu chiri muchikamu xdp/simple, apo tisati tapedza slash tinotsanangura rudzi rwechirongwa BPF - iyi ndiyo gungano rinoshandiswa mukati libbpf, zvichibva pazita rechikamu ichatsiva iyo chaiyo mhando pakutanga bpf(2). Iyo BPF chirongwa pachayo C - iri nyore kwazvo uye ine mutsara mumwe return XDP_PASS. Pakupedzisira, chikamu chakasiyana "license" rine zita rerezinesi.

Tinogona kuunganidza chirongwa chedu tichishandisa llvm/clang, vhezheni>= 10.0.0, kana zvirinani, zvakakura (ona chikamu Zvishandiso zvekuvandudza):

$ clang --version
clang version 11.0.0 (https://github.com/llvm/llvm-project.git afc287e0abec710398465ee1f86237513f2b5091)
...

$ clang -O2 -g -c -target bpf -I libbpf/src/root/usr/include xdp-simple.bpf.c -o xdp-simple.bpf.o

Pakati pezvinhu zvinonakidza: isu tinoratidza chinangwa chekuvaka -target bpf uye nzira inoenda kumisoro libbpf, yatakaisa munguva pfupi yapfuura. Uyewo, usakanganwa nezvazvo -O2, pasina iyi sarudzo unogona kunge uri mune zvinoshamisa mune ramangwana. Ngatitarisei kodhi yedu, takakwanisa here kunyora chirongwa chataida?

$ llvm-objdump --section=xdp/simple --no-show-raw-insn -D xdp-simple.bpf.o

xdp-simple.bpf.o:       file format elf64-bpf

Disassembly of section xdp/simple:

0000000000000000 <simple>:
       0:       r0 = 2
       1:       exit

Hungu, zvakashanda! Zvino, isu tine bhinari faira ine chirongwa, uye isu tinoda kugadzira application inozoiisa mu kernel. Nechinangwa ichi raibhurari libbpf inotipa sarudzo mbiri - shandisa yakaderera-level API kana yepamusoro-level API. Tichaenda nenzira yechipiri, sezvo tichida kudzidza kunyora, kurodha uye kubatanidza zvirongwa zveBPF nekuedza kushoma pakudzidza kwavo kunotevera.

Chekutanga, isu tinofanirwa kugadzira iyo "skeleton" yechirongwa chedu kubva kubhinari yayo tichishandisa chinhu chimwe chete bpftool - banga reSwitzerland renyika yeBPF (iyo inogona kutorwa sezvairi, sezvo Daniel Borkman, mumwe wevagadziri uye vanochengeta BPF, ari Swiss):

$ bpftool gen skeleton xdp-simple.bpf.o > xdp-simple.skel.h

Mufaira xdp-simple.skel.h ine iyo binary kodhi yechirongwa chedu uye mabasa ekugadzirisa - kurodha, kubatanidza, kudzima chinhu chedu. Muchiitiko chedu chakareruka izvi zvinoita sekunge kuwandisa, asi zvinoshandawo mune iyo chinhu faira rine akawanda BPF zvirongwa uye mepu uye kurodha iyi hofori ELF isu tinongoda kugadzira skeleton uye kudana rimwe kana maviri basa kubva kune tsika application isu. vari kunyora Ngatienderere mberi izvozvi.

Kunyatsotaura, chirongwa chedu chekurodha hachina basa:

#include <err.h>
#include <unistd.h>
#include "xdp-simple.skel.h"

int main(int argc, char **argv)
{
    struct xdp_simple_bpf *obj;

    obj = xdp_simple_bpf__open_and_load();
    if (!obj)
        err(1, "failed to open and/or load BPF objectn");

    pause();

    xdp_simple_bpf__destroy(obj);
}

zviri struct xdp_simple_bpf inotsanangurwa mufaira xdp-simple.skel.h uye inotsanangura chinhu chedu faira:

struct xdp_simple_bpf {
    struct bpf_object_skeleton *skeleton;
    struct bpf_object *obj;
    struct {
        struct bpf_program *simple;
    } progs;
    struct {
        struct bpf_link *simple;
    } links;
};

Isu tinogona kuona mitsetse yeyakaderera-level API pano: chimiro struct bpf_program *simple ΠΈ struct bpf_link *simple. Chimiro chekutanga chinotsanangura zvakananga chirongwa chedu, chakanyorwa muchikamu xdp/simple, uye yechipiri inotsanangura kuti chirongwa chinobatana sei kune chiitiko chinobva.

shanda xdp_simple_bpf__open_and_load, inovhura chinhu cheELF, ichiiparadzanisa, inogadzira zvese zvimiro uye zvidimbu (kunze kwechirongwa, ELF inewo zvimwe zvikamu - data, kuverenga chete data, debugging ruzivo, rezinesi, nezvimwewo), uye wozoiisa mu kernel uchishandisa system. call bpf, iyo yatinogona kutarisa nekunyora uye nekumhanyisa chirongwa:

$ clang -O2 -I ./libbpf/src/root/usr/include/ xdp-simple.c -o xdp-simple ./libbpf/src/root/usr/lib64/libbpf.a -lelf -lz

$ sudo strace -e bpf ./xdp-simple
...
bpf(BPF_BTF_LOAD, 0x7ffdb8fd9670, 120)  = 3
bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_XDP, insn_cnt=2, insns=0xdfd580, license="GPL", log_level=0, log_size=0, log_buf=NULL, kern_version=KERNEL_VERSION(5, 8, 0), prog_flags=0, prog_name="simple", prog_ifindex=0, expected_attach_type=0x25 /* BPF_??? */, ...}, 120) = 4

Ngatitarisei ikozvino purogiramu yedu tichishandisa bpftool. Ngatimutsvagirei ID yake:

# bpftool p | grep -A4 simple
463: xdp  name simple  tag 3b185187f1855c4c  gpl
        loaded_at 2020-08-01T01:59:49+0000  uid 0
        xlated 16B  jited 40B  memlock 4096B
        btf_id 185
        pids xdp-simple(16498)

uye kurasa (tinoshandisa fomu rakapfupikiswa remurairo bpftool prog dump xlated):

# bpftool p d x id 463
int simple(void *ctx):
; return XDP_PASS;
   0: (b7) r0 = 2
   1: (95) exit

Chinhu chitsva! Chirongwa chakadhinda zvimedu zvefaira redu reC. Izvi zvakaitwa neraibhurari libbpf, iyo yakawana chikamu chekugadzirisa mubhinari, yakaunganidza kuita chinhu cheBTF, ndokuiisa mu kernel vachishandisa. BPF_BTF_LOAD, uye ndokutsanangura mhedzisiro yefaira inotsanangura paunenge uchiisa chirongwa nemurairo BPG_PROG_LOAD.

Kernel Helpers

Zvirongwa zveBPF zvinogona kuita "kunze" mabasa - kernel vabatsiri. Aya mabasa emubatsiri anobvumira zvirongwa zveBPF kuwana zvimiro zve kernel, kubata mepu, uye zvakare kutaurirana ne "nyika chaiyo" - gadzira zviitiko zveperf, control hardware (semuenzaniso, redirect mapaketi), nezvimwe.

Muenzaniso: bpf_get_smp_processor_id

Mukati megadziriro ye "kudzidza nemuenzaniso" paradigm, ngatitarisei rimwe remabasa ekubatsira, bpf_get_smp_processor_id(), chokwadi mufaira kernel/bpf/helpers.c. Inodzosa nhamba ye processor iyo chirongwa cheBPF chakadaidza chiri kushanda. Asi isu hatisi kufarira semantics yayo sekuti kuita kwayo kunotora mutsara mumwe:

BPF_CALL_0(bpf_get_smp_processor_id)
{
    return smp_processor_id();
}

Iyo BPF mubatsiri basa tsananguro dzakafanana neLinux system call tsananguro. Pano, semuenzaniso, basa rinotsanangurwa risina nharo. (Basa rinotora, toti, nharo nhatu dzinotsanangurwa uchishandisa macro BPF_CALL_3. Nhamba huru yenharo ishanu.) Zvisinei, ichi chinongova chikamu chekutanga chetsanangudzo. Chikamu chechipiri ndechekutsanangura chimiro chemhando struct bpf_func_proto, iyo ine tsananguro yebasa remubatsiri iro verifier inonzwisisa:

const struct bpf_func_proto bpf_get_smp_processor_id_proto = {
    .func     = bpf_get_smp_processor_id,
    .gpl_only = false,
    .ret_type = RET_INTEGER,
};

Kunyoresa Mubatsiri Mabasa

Kuti zvirongwa zveBPF zverudzi rwakati zvishandise basa iri, vanofanirwa kurinyoresa, semuenzaniso werudzi BPF_PROG_TYPE_XDP basa rinotsanangurwa mu kernel xdp_func_proto, iyo inosarudza kubva kumubatsiri basa ID kana XDP inotsigira basa iri kana kwete. Basa redu nderiri zvitsigiso:

static const struct bpf_func_proto *
xdp_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
{
    switch (func_id) {
    ...
    case BPF_FUNC_get_smp_processor_id:
        return &bpf_get_smp_processor_id_proto;
    ...
    }
}

Nyowani BPF chirongwa mhando "inotsanangurwa" mufaira include/linux/bpf_types.h kushandisa macro BPF_PROG_TYPE. Zvinotsanangurwa mumakotesheni nekuti itsanangudzo ine musoro, uye mumutauro weC tsananguro yeseti yezvimiro zvekongiri inoitika kune dzimwe nzvimbo. Kunyanya, mufaira kernel/bpf/verifier.c tsananguro dzese kubva kufaira bpf_types.h anoshandiswa kugadzira hurongwa hwezvivakwa bpf_verifier_ops[]:

static const struct bpf_verifier_ops *const bpf_verifier_ops[] = {
#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type) 
    [_id] = & _name ## _verifier_ops,
#include <linux/bpf_types.h>
#undef BPF_PROG_TYPE
};

Ndiko kuti, kune yega yega chirongwa cheBPF, chinongedzo kune chimiro che data cherudzi chinotsanangurwa struct bpf_verifier_ops, iyo inotangwa nehuwandu _name ## _verifier_ops, kureva, xdp_verifier_ops nokuti xdp. Chimiro xdp_verifier_ops akatsunga na mufaira net/core/filter.c sezvinotevera:

const struct bpf_verifier_ops xdp_verifier_ops = {
    .get_func_proto     = xdp_func_proto,
    .is_valid_access    = xdp_is_valid_access,
    .convert_ctx_access = xdp_convert_ctx_access,
    .gen_prologue       = bpf_noop_prologue,
};

Pano tinoona basa redu rinozivikanwa xdp_func_proto, iyo inomhanyisa verifier pese painosangana nedambudziko vamwe inoshanda mukati mechirongwa cheBPF, ona verifier.c.

Ngatitarisei kuti chirongwa cheBPF chekufungidzira chinoshandisa sei basa racho bpf_get_smp_processor_id. Kuti tiite izvi, tinonyora zvakare chirongwa kubva muchikamu chedu chapfuura sezvinotevera:

#include "vmlinux.h"
#include <bpf/bpf_helpers.h>

SEC("xdp/simple")
int simple(void *ctx)
{
    if (bpf_get_smp_processor_id() != 0)
        return XDP_DROP;
    return XDP_PASS;
}

char LICENSE[] SEC("license") = "GPL";

Symbol bpf_get_smp_processor_id akatsunga na Π² <bpf/bpf_helper_defs.h> raibhurari libbpf sei

static u32 (*bpf_get_smp_processor_id)(void) = (void *) 8;

kureva, bpf_get_smp_processor_id iratidziro yebasa ine kukosha kwayo 8, uko 8 ndiko kukosha BPF_FUNC_get_smp_processor_id chimiro enum bpf_fun_id, iyo inotsanangurwa kwatiri mufaira vmlinux.h (faira bpf_helper_defs.h mu kernel inogadzirwa ne script, saka nhamba dze "magic" dzakanaka). Basa iri haritore nharo uye rinodzosa kukosha kwemhando __u32. Patinoimhanyisa muchirongwa chedu, clang inogadzira murairo BPF_CALL "mhando chaiyo" Ngatiunganidze chirongwa uye titarise chikamu xdp/simple:

$ clang -O2 -g -c -target bpf -I libbpf/src/root/usr/include xdp-simple.bpf.c -o xdp-simple.bpf.o
$ llvm-objdump -D --section=xdp/simple xdp-simple.bpf.o

xdp-simple.bpf.o:       file format elf64-bpf

Disassembly of section xdp/simple:

0000000000000000 <simple>:
       0:       85 00 00 00 08 00 00 00 call 8
       1:       bf 01 00 00 00 00 00 00 r1 = r0
       2:       67 01 00 00 20 00 00 00 r1 <<= 32
       3:       77 01 00 00 20 00 00 00 r1 >>= 32
       4:       b7 00 00 00 02 00 00 00 r0 = 2
       5:       15 01 01 00 00 00 00 00 if r1 == 0 goto +1 <LBB0_2>
       6:       b7 00 00 00 01 00 00 00 r0 = 1

0000000000000038 <LBB0_2>:
       7:       95 00 00 00 00 00 00 00 exit

Mumutsara wekutanga tinoona mirairo call, parameter IMM izvo zvakaenzana na8, uye SRC_REG - zero. Zvinoenderana nechibvumirano cheABI chinoshandiswa neveverifier, uku kufona kumubatsiri basa nhamba sere. Kana yangotangwa, pfungwa yacho iri nyore. Dzosa kukosha kubva kurejista r0 kukopwa ku r1 uye pamitsetse 2,3 inoshandurwa kuita type u32 - iyo yepamusoro 32 bits inocheneswa. Pamitsetse 4,5,6,7 tinodzorera 2 (XDP_PASS) kana 1 (XDP_DROP) zvichienderana nekuti mubatsiri anoshanda kubva mumutsara 0 akadzosa zero kana isiri-zero kukosha.

Ngatizviedzei pachedu: takura chirongwa uye tarisa zvakabuda bpftool prog dump xlated:

$ bpftool gen skeleton xdp-simple.bpf.o > xdp-simple.skel.h
$ clang -O2 -g -I ./libbpf/src/root/usr/include/ -o xdp-simple xdp-simple.c ./libbpf/src/root/usr/lib64/libbpf.a -lelf -lz
$ sudo ./xdp-simple &
[2] 10914

$ sudo bpftool p | grep simple
523: xdp  name simple  tag 44c38a10c657e1b0  gpl
        pids xdp-simple(10915)

$ sudo bpftool p d x id 523
int simple(void *ctx):
; if (bpf_get_smp_processor_id() != 0)
   0: (85) call bpf_get_smp_processor_id#114128
   1: (bf) r1 = r0
   2: (67) r1 <<= 32
   3: (77) r1 >>= 32
   4: (b7) r0 = 2
; }
   5: (15) if r1 == 0x0 goto pc+1
   6: (b7) r0 = 1
   7: (95) exit

Zvakanaka, verifier yakawana iyo chaiyo kernel-mubatsiri.

Muenzaniso: kupfuudza nharo uye pakupedzisira kumhanyisa chirongwa!

Yese run-level mubatsiri mabasa ane prototype

u64 fn(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)

Parameters kumabasa emubatsiri anopfuudzwa mumarejista r1-r5, uye kukosha kunodzorerwa murejista r0. Iko hakuna mabasa anotora nharo dzinopfuura shanu, uye kutsigira kwavo hakutarisirwi kuwedzerwa mune ramangwana.

Ngatitarisei kune mutsva kernel mubatsiri uye kuti BPF inopfuura sei paramita. Ngatinyore patsva xdp-simple.bpf.c sezvinotevera (mamwe mitsara haana kuchinja):

SEC("xdp/simple")
int simple(void *ctx)
{
    bpf_printk("running on CPU%un", bpf_get_smp_processor_id());
    return XDP_PASS;
}

Chirongwa chedu chinodhinda nhamba yeCPU pairi kuita. Ngatizviunganidze uye titarise iyo kodhi:

$ llvm-objdump -D --section=xdp/simple --no-show-raw-insn xdp-simple.bpf.o

0000000000000000 <simple>:
       0:       r1 = 10
       1:       *(u16 *)(r10 - 8) = r1
       2:       r1 = 8441246879787806319 ll
       4:       *(u64 *)(r10 - 16) = r1
       5:       r1 = 2334956330918245746 ll
       7:       *(u64 *)(r10 - 24) = r1
       8:       call 8
       9:       r1 = r10
      10:       r1 += -24
      11:       r2 = 18
      12:       r3 = r0
      13:       call 6
      14:       r0 = 2
      15:       exit

Mumitsetse 0-7 tinonyora tambo running on CPU%un, uye ipapo pamutsara wechi8 tinomhanya yakajairika bpf_get_smp_processor_id. Pamitsetse 9-12 tinogadzirira nharo dzemubatsiri bpf_printk - mabhuku r1, r2, r3. Sei vari vatatu kwete vaviri? Nokuti bpf_printkiyi macro wrapper kumativi mubatsiri chaiye bpf_trace_printk, inoda kupfuudza saizi yetambo yefomati.

Ngatiwedzerei mitsetse miviri xdp-simple.ckuitira kuti purogiramu yedu ibatane kune interface lo uye zvechokwadi akatanga!

$ cat xdp-simple.c
#include <linux/if_link.h>
#include <err.h>
#include <unistd.h>
#include "xdp-simple.skel.h"

int main(int argc, char **argv)
{
    __u32 flags = XDP_FLAGS_SKB_MODE;
    struct xdp_simple_bpf *obj;

    obj = xdp_simple_bpf__open_and_load();
    if (!obj)
        err(1, "failed to open and/or load BPF objectn");

    bpf_set_link_xdp_fd(1, -1, flags);
    bpf_set_link_xdp_fd(1, bpf_program__fd(obj->progs.simple), flags);

cleanup:
    xdp_simple_bpf__destroy(obj);
}

Pano tinoshandisa basa bpf_set_link_xdp_fd, iyo inobatanidza XDP-mhando yeBPF zvirongwa kune network interfaces. We hardcode iyo interface nhamba lo, iyo inogara iri 1. Tinomhanya basa racho kaviri kuti titange kubvisa purogiramu yekare kana yakabatanidzwa. Cherechedza kuti ikozvino hatidi dambudziko pause kana kusingaperi loop: chirongwa chedu chekurodha chinobuda, asi chirongwa cheBPF hachizouraiwa sezvo chakabatana kune chiitiko sosi. Mushure mekubudirira kurodha uye kubatana, chirongwa chinozovhurwa kune yega yega network packet inosvika lo.

Ngatitorei chirongwa uye titarise iyo interface lo:

$ sudo ./xdp-simple
$ sudo bpftool p | grep simple
669: xdp  name simple  tag 4fca62e77ccb43d6  gpl
$ ip l show dev lo
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 xdpgeneric qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    prog/xdp id 669

Chirongwa chatakadhawunirodha chine ID 669 uye isu tinoona imwechete ID pane interface lo. Tichatumira mapepa maviri kune 127.0.0.1 (chikumbiro + mhinduro):

$ ping -c1 localhost

uye zvino ngatitarisei zviri mukati meiyo debug virtual file /sys/kernel/debug/tracing/trace_pipe, mune bpf_printk anonyora mameseji ake:

# cat /sys/kernel/debug/tracing/trace_pipe
ping-13937 [000] d.s1 442015.377014: bpf_trace_printk: running on CPU0
ping-13937 [000] d.s1 442015.377027: bpf_trace_printk: running on CPU0

Mapasuru maviri akaonekwa lo uye yakagadziriswa paCPU0 - yedu yekutanga yakazara yakazara isina revo yeBPF chirongwa chakashanda!

Izvo zvakakosha kuti uzive izvo bpf_printk Haisi nhando iyo inonyora kune debug faira: iyi haisi iyo yakabudirira mubatsiri wekushandisa mukugadzira, asi chinangwa chedu chaive kuratidza chimwe chinhu chiri nyore.

Kuwana mamepu kubva kuBPF zvirongwa

Muenzaniso: kushandisa mepu kubva kuchirongwa cheBPF

Muzvikamu zvakapfuura takadzidza kugadzira nekushandisa mepu kubva munzvimbo yemushandisi, uye zvino ngatitarisei chikamu chekernel. Ngatitange, senguva dzose, nemuenzaniso. Ngatinyore patsva chirongwa chedu xdp-simple.bpf.c sezvinotevera:

#include "vmlinux.h"
#include <bpf/bpf_helpers.h>

struct {
    __uint(type, BPF_MAP_TYPE_ARRAY);
    __uint(max_entries, 8);
    __type(key, u32);
    __type(value, u64);
} woo SEC(".maps");

SEC("xdp/simple")
int simple(void *ctx)
{
    u32 key = bpf_get_smp_processor_id();
    u32 *val;

    val = bpf_map_lookup_elem(&woo, &key);
    if (!val)
        return XDP_ABORTED;

    *val += 1;

    return XDP_PASS;
}

char LICENSE[] SEC("license") = "GPL";

Pakutanga kwechirongwa takawedzera tsananguro yemepu woo: Iyi i8-element array inochengeta zvakakosha senge u64 (muC tinogona kutsanangura hurongwa hwakadai se u64 woo[8]) Muchirongwa "xdp/simple" isu tinowana ikozvino processor nhamba mune inoshanduka key uyezve kushandisa mubatsiri basa bpf_map_lookup_element tinowana chinongedzo kune chinopindirana chinopinda muhurongwa, iyo yatinowedzera neimwe. Yakaturikirwa muchiRussian: isu tinoverenga nhamba iyo CPU yakagadziridza mapaketi anouya. Ngatiedze kumhanyisa chirongwa:

$ clang -O2 -g -c -target bpf -I libbpf/src/root/usr/include xdp-simple.bpf.c -o xdp-simple.bpf.o
$ bpftool gen skeleton xdp-simple.bpf.o > xdp-simple.skel.h
$ clang -O2 -g -I ./libbpf/src/root/usr/include/ -o xdp-simple xdp-simple.c ./libbpf/src/root/usr/lib64/libbpf.a -lelf -lz
$ sudo ./xdp-simple

Ngatitarisei kuti abatanidzwa here lo uye tumira mamwe mapaketi:

$ ip l show dev lo
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 xdpgeneric qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    prog/xdp id 108

$ for s in `seq 234`; do sudo ping -f -c 100 127.0.0.1 >/dev/null 2>&1; done

Zvino ngatitarisei zviri mukati meiyo array:

$ sudo bpftool map dump name woo
[
    { "key": 0, "value": 0 },
    { "key": 1, "value": 400 },
    { "key": 2, "value": 0 },
    { "key": 3, "value": 0 },
    { "key": 4, "value": 0 },
    { "key": 5, "value": 0 },
    { "key": 6, "value": 0 },
    { "key": 7, "value": 46400 }
]

Anenge ese maitiro akagadziriswa paCPU7. Izvi hazvina kukosha kwatiri, chinhu chikuru ndechekuti chirongwa chinoshanda uye tinonzwisisa nzira yekuwana mamepu kubva kuBPF zvirongwa - tichishandisa Ρ…Π΅Π»ΠΏΠ΅Ρ€ΠΎΠ² bpf_mp_*.

Mystical index

Saka, isu tinokwanisa kuwana mepu kubva kuchirongwa cheBPF tichishandisa mafoni senge

val = bpf_map_lookup_elem(&woo, &key);

uko basa rekubatsira rinotaridzika

void *bpf_map_lookup_elem(struct bpf_map *map, const void *key)

asi tiri kupfuura chinongedzo &woo kune chimiro chisina zita struct { ... }...

Kana tikatarisa purogiramu assembler, tinoona kuti kukosha &woo haina kunyatsotsanangurwa (mutsara 4):

llvm-objdump -D --section xdp/simple xdp-simple.bpf.o

xdp-simple.bpf.o:       file format elf64-bpf

Disassembly of section xdp/simple:

0000000000000000 <simple>:
       0:       85 00 00 00 08 00 00 00 call 8
       1:       63 0a fc ff 00 00 00 00 *(u32 *)(r10 - 4) = r0
       2:       bf a2 00 00 00 00 00 00 r2 = r10
       3:       07 02 00 00 fc ff ff ff r2 += -4
       4:       18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0 ll
       6:       85 00 00 00 01 00 00 00 call 1
...

uye inowanikwa mukutamiswa:

$ llvm-readelf -r xdp-simple.bpf.o | head -4

Relocation section '.relxdp/simple' at offset 0xe18 contains 1 entries:
    Offset             Info             Type               Symbol's Value  Symbol's Name
0000000000000020  0000002700000001 R_BPF_64_64            0000000000000000 woo

Asi kana tikatarisa purogiramu yakatotakura, tinoona chinongedzo kumepu chaiyo (mutsara 4):

$ sudo bpftool prog dump x name simple
int simple(void *ctx):
   0: (85) call bpf_get_smp_processor_id#114128
   1: (63) *(u32 *)(r10 -4) = r0
   2: (bf) r2 = r10
   3: (07) r2 += -4
   4: (18) r1 = map[id:64]
...

Nekudaro, isu tinogona kugumisa kuti panguva yekutangisa yedu loader chirongwa, chinongedzo ku &woo chakatsiviwa nechimwe chinhu chine raibhurari libbpf. Kutanga tichatarisa zvakabuda strace:

$ sudo strace -e bpf ./xdp-simple
...
bpf(BPF_MAP_CREATE, {map_type=BPF_MAP_TYPE_ARRAY, key_size=4, value_size=8, max_entries=8, map_name="woo", ...}, 120) = 4
bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_XDP, prog_name="simple", ...}, 120) = 5

Tinozviona izvozvo libbpf akagadzira mepu woo uye ndokudhawunirodha chirongwa chedu simple. Ngatitarisei zvakanyanya kuti tinoisa sei chirongwa:

  • call xdp_simple_bpf__open_and_load kubva faira xdp-simple.skel.h
  • zvinokonzeresa xdp_simple_bpf__load kubva faira xdp-simple.skel.h
  • zvinokonzeresa bpf_object__load_skeleton kubva faira libbpf/src/libbpf.c
  • zvinokonzeresa bpf_object__load_xattr kubva libbpf/src/libbpf.c

Basa rekupedzisira, pakati pezvimwe zvinhu, richadana bpf_object__create_maps, iyo inogadzira kana kuvhura mamepu aripo, ichiashandura kuita faira descriptors. (Apa ndipo patinoona BPF_MAP_CREATE mune zvabuda strace.) Tevere basa racho rinodanwa bpf_object__relocate uye ndiye anotida, sezvo tichirangarira zvatakaona woo mutafura yekutamisa. Kuzviongorora, tinopedzisira tazviwana tiri mubasa bpf_program__relocate, izvo inobata nekutamiswa kwemepu:

case RELO_LD64:
    insn[0].src_reg = BPF_PSEUDO_MAP_FD;
    insn[0].imm = obj->maps[relo->map_idx].fd;
    break;

Saka tinotora mirairo yedu

18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0 ll

uye shandura iyo rejista yezvinyorwa mairi nayo BPF_PSEUDO_MAP_FD, uye yekutanga IMM kune faira tsananguro yemepu yedu uye, kana yakaenzana, semuenzaniso, 0xdeadbeef, zvino somugumisiro tichawana murayiridzo

18 11 00 00 ef eb ad de 00 00 00 00 00 00 00 00 r1 = 0 ll

Aya ndiwo mafambisirwo anoitwa ruzivo rwemepu kune yakatarwa chirongwa cheBPF. Muchiitiko ichi, mepu inogona kugadzirwa uchishandisa BPF_MAP_CREATE, uye yakavhurwa neID uchishandisa BPF_MAP_GET_FD_BY_ID.

Total, pakushandisa libbpf iyo algorithm yakaita seiyi:

  • panguva yekubatanidza, zvinyorwa zvinogadzirwa mutafura yekutamisa kune zvinongedzo kumepu
  • libbpf inovhura bhuku rezvinhu zveELF, inowana mamepu ese akashandiswa uye inogadzira zvinotsanangura faira kwavari
  • faira tsananguro dzinoiswa mu kernel sechikamu chekuraira LD64

Sezvaungafungidzira, kune zvakawanda zvinouya uye isu tichafanirwa kutarisa mukati mepakati. Sezvineiwo, isu tine ruzivo - isu takanyora pasi zvazvinoreva BPF_PSEUDO_MAP_FD mune rejista yezvinyorwa uye tinogona kuiviga, iyo ichatitungamirira kune tsvene yevatsvene vose - kernel/bpf/verifier.c, apo basa rine zita rakasiyana rinotsiva descriptor yefaira nekero yechimiro chemhando struct bpf_map:

static int replace_map_fd_with_map_ptr(struct bpf_verifier_env *env) {
    ...

    f = fdget(insn[0].imm);
    map = __bpf_map_get(f);
    if (insn->src_reg == BPF_PSEUDO_MAP_FD) {
        addr = (unsigned long)map;
    }
    insn[0].imm = (u32)addr;
    insn[1].imm = addr >> 32;

(kodhi yakazara inogona kuwanikwa batanidzo) Saka isu tinogona kuwedzera algorithm yedu:

  • panguva yekurodha purogiramu, verifier inotarisa kushandiswa kwakakodzera kwemepu uye inonyora kero yechimiro chinoenderana struct bpf_map

Paunenge uchirodha iyo ELF binary uchishandisa libbpf Pane zvakawanda zviri kuitika, asi tichazvikurukura mune zvimwe zvinyorwa.

Kurodha zvirongwa nemamepu pasina libbpf

Sezvakavimbiswa, heino muenzaniso wevaverengi vanoda kuziva kugadzira uye kurodha chirongwa chinoshandisa mepu, pasina rubatsiro. libbpf. Izvi zvinogona kubatsira kana uchinge uchishanda munzvimbo yausingakwanise kuvaka zvinomirirwa, kana kuchengetedza zvese zvishoma, kana kunyora chirongwa senge. ply, iyo inogadzira BPF binary code panhunzi.

Kuita kuti zvive nyore kutevedzera pfungwa, isu tichanyora zvakare muenzaniso wedu kune izvi zvinangwa xdp-simple. Iyo yakazara uye yakawedzera zvishoma kodhi yepurogiramu inokurukurwa mumuenzaniso uyu inogona kuwanikwa mune izvi pfungwa.

Iyo logic yemashandisirwo edu ndeiyi inotevera:

  • gadzira mhando yemepu BPF_MAP_TYPE_ARRAY kushandisa murairo BPF_MAP_CREATE,
  • gadzira chirongwa chinoshandisa mepu iyi,
  • batanidza purogiramu kune interface lo,

izvo zvinoturikira mumunhu se

int main(void)
{
    int map_fd, prog_fd;

    map_fd = map_create();
    if (map_fd < 0)
        err(1, "bpf: BPF_MAP_CREATE");

    prog_fd = prog_load(map_fd);
    if (prog_fd < 0)
        err(1, "bpf: BPF_PROG_LOAD");

    xdp_attach(1, prog_fd);
}

zviri map_create inogadzira mepu nenzira imwechete sezvatakaita mumuenzaniso wekutanga nezve system call bpf - "kernel, ndapota ndigadzirire mepu nyowani muchimiro chemhando yezvikamu zvisere senge __u64 uye ndidzosere iyo faira descriptor":

static int map_create()
{
    union bpf_attr attr;

    memset(&attr, 0, sizeof(attr));
    attr.map_type = BPF_MAP_TYPE_ARRAY,
    attr.key_size = sizeof(__u32),
    attr.value_size = sizeof(__u64),
    attr.max_entries = 8,
    strncpy(attr.map_name, "woo", sizeof(attr.map_name));
    return syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
}

Iyo purogiramu zvakare iri nyore kurodha:

static int prog_load(int map_fd)
{
    union bpf_attr attr;
    struct bpf_insn insns[] = {
        ...
    };

    memset(&attr, 0, sizeof(attr));
    attr.prog_type = BPF_PROG_TYPE_XDP;
    attr.insns     = ptr_to_u64(insns);
    attr.insn_cnt  = sizeof(insns)/sizeof(insns[0]);
    attr.license   = ptr_to_u64("GPL");
    strncpy(attr.prog_name, "woo", sizeof(attr.prog_name));
    return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
}

Chikamu chinonyengera prog_load ndiyo tsananguro yechirongwa chedu cheBPF sehurongwa hwezvimiro struct bpf_insn insns[]. Asi sezvo tiri kushandisa chirongwa chatiinacho muC, tinogona kubiridzira zvishoma:

$ llvm-objdump -D --section xdp/simple xdp-simple.bpf.o

0000000000000000 <simple>:
       0:       85 00 00 00 08 00 00 00 call 8
       1:       63 0a fc ff 00 00 00 00 *(u32 *)(r10 - 4) = r0
       2:       bf a2 00 00 00 00 00 00 r2 = r10
       3:       07 02 00 00 fc ff ff ff r2 += -4
       4:       18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0 ll
       6:       85 00 00 00 01 00 00 00 call 1
       7:       b7 01 00 00 00 00 00 00 r1 = 0
       8:       15 00 04 00 00 00 00 00 if r0 == 0 goto +4 <LBB0_2>
       9:       61 01 00 00 00 00 00 00 r1 = *(u32 *)(r0 + 0)
      10:       07 01 00 00 01 00 00 00 r1 += 1
      11:       63 10 00 00 00 00 00 00 *(u32 *)(r0 + 0) = r1
      12:       b7 01 00 00 02 00 00 00 r1 = 2

0000000000000068 <LBB0_2>:
      13:       bf 10 00 00 00 00 00 00 r0 = r1
      14:       95 00 00 00 00 00 00 00 exit

Pakazara, isu tinofanirwa kunyora mirairo gumi nemana muchimiro chezvimiro senge struct bpf_insn (zano: tora dump kubva kumusoro, verenga zvakare chikamu chemirayiridzo, vhura linux/bpf.h ΠΈ linux/bpf_common.h uye edza kuziva struct bpf_insn insns[] wega):

struct bpf_insn insns[] = {
    /* 85 00 00 00 08 00 00 00 call 8 */
    {
        .code = BPF_JMP | BPF_CALL,
        .imm = 8,
    },

    /* 63 0a fc ff 00 00 00 00 *(u32 *)(r10 - 4) = r0 */
    {
        .code = BPF_MEM | BPF_STX,
        .off = -4,
        .src_reg = BPF_REG_0,
        .dst_reg = BPF_REG_10,
    },

    /* bf a2 00 00 00 00 00 00 r2 = r10 */
    {
        .code = BPF_ALU64 | BPF_MOV | BPF_X,
        .src_reg = BPF_REG_10,
        .dst_reg = BPF_REG_2,
    },

    /* 07 02 00 00 fc ff ff ff r2 += -4 */
    {
        .code = BPF_ALU64 | BPF_ADD | BPF_K,
        .dst_reg = BPF_REG_2,
        .imm = -4,
    },

    /* 18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0 ll */
    {
        .code = BPF_LD | BPF_DW | BPF_IMM,
        .src_reg = BPF_PSEUDO_MAP_FD,
        .dst_reg = BPF_REG_1,
        .imm = map_fd,
    },
    { }, /* placeholder */

    /* 85 00 00 00 01 00 00 00 call 1 */
    {
        .code = BPF_JMP | BPF_CALL,
        .imm = 1,
    },

    /* b7 01 00 00 00 00 00 00 r1 = 0 */
    {
        .code = BPF_ALU64 | BPF_MOV | BPF_K,
        .dst_reg = BPF_REG_1,
        .imm = 0,
    },

    /* 15 00 04 00 00 00 00 00 if r0 == 0 goto +4 <LBB0_2> */
    {
        .code = BPF_JMP | BPF_JEQ | BPF_K,
        .off = 4,
        .src_reg = BPF_REG_0,
        .imm = 0,
    },

    /* 61 01 00 00 00 00 00 00 r1 = *(u32 *)(r0 + 0) */
    {
        .code = BPF_MEM | BPF_LDX,
        .off = 0,
        .src_reg = BPF_REG_0,
        .dst_reg = BPF_REG_1,
    },

    /* 07 01 00 00 01 00 00 00 r1 += 1 */
    {
        .code = BPF_ALU64 | BPF_ADD | BPF_K,
        .dst_reg = BPF_REG_1,
        .imm = 1,
    },

    /* 63 10 00 00 00 00 00 00 *(u32 *)(r0 + 0) = r1 */
    {
        .code = BPF_MEM | BPF_STX,
        .src_reg = BPF_REG_1,
        .dst_reg = BPF_REG_0,
    },

    /* b7 01 00 00 02 00 00 00 r1 = 2 */
    {
        .code = BPF_ALU64 | BPF_MOV | BPF_K,
        .dst_reg = BPF_REG_1,
        .imm = 2,
    },

    /* <LBB0_2>: bf 10 00 00 00 00 00 00 r0 = r1 */
    {
        .code = BPF_ALU64 | BPF_MOV | BPF_X,
        .src_reg = BPF_REG_1,
        .dst_reg = BPF_REG_0,
    },

    /* 95 00 00 00 00 00 00 00 exit */
    {
        .code = BPF_JMP | BPF_EXIT
    },
};

Chiitiko cheavo vasina kunyora izvi ivo pachavo - tsvaga map_fd.

Pane chimwezve chikamu chisina kuziviswa chasara muchirongwa chedu - xdp_attach. Nehurombo, zvirongwa zvakaita seXDP hazvigone kubatana uchishandisa kufona system bpf. Vanhu vakagadzira BPF neXDP vaibva kunharaunda yeLinux yepamhepo, zvinoreva kuti vakashandisa yavanoziva (asi kwete normal people) interface yekudyidzana nekernel: netlink sockets, onawo RFC3549. Nzira iri nyore yekushandisa xdp_attach ari kukopa kodhi kubva libbpf, kureva, kubva mufaira netlink.c, ndizvo zvatakaita, kupfupisa zvishoma:

Tikugashirei kune nyika yenetlink sockets

Vhura netlink socket mhando NETLINK_ROUTE:

int netlink_open(__u32 *nl_pid)
{
    struct sockaddr_nl sa;
    socklen_t addrlen;
    int one = 1, ret;
    int sock;

    memset(&sa, 0, sizeof(sa));
    sa.nl_family = AF_NETLINK;

    sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    if (sock < 0)
        err(1, "socket");

    if (setsockopt(sock, SOL_NETLINK, NETLINK_EXT_ACK, &one, sizeof(one)) < 0)
        warnx("netlink error reporting not supported");

    if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0)
        err(1, "bind");

    addrlen = sizeof(sa);
    if (getsockname(sock, (struct sockaddr *)&sa, &addrlen) < 0)
        err(1, "getsockname");

    *nl_pid = sa.nl_pid;
    return sock;
}

Tinoverenga kubva pane iyi socket:

static int bpf_netlink_recv(int sock, __u32 nl_pid, int seq)
{
    bool multipart = true;
    struct nlmsgerr *errm;
    struct nlmsghdr *nh;
    char buf[4096];
    int len, ret;

    while (multipart) {
        multipart = false;
        len = recv(sock, buf, sizeof(buf), 0);
        if (len < 0)
            err(1, "recv");

        if (len == 0)
            break;

        for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len);
                nh = NLMSG_NEXT(nh, len)) {
            if (nh->nlmsg_pid != nl_pid)
                errx(1, "wrong pid");
            if (nh->nlmsg_seq != seq)
                errx(1, "INVSEQ");
            if (nh->nlmsg_flags & NLM_F_MULTI)
                multipart = true;
            switch (nh->nlmsg_type) {
                case NLMSG_ERROR:
                    errm = (struct nlmsgerr *)NLMSG_DATA(nh);
                    if (!errm->error)
                        continue;
                    ret = errm->error;
                    // libbpf_nla_dump_errormsg(nh); too many code to copy...
                    goto done;
                case NLMSG_DONE:
                    return 0;
                default:
                    break;
            }
        }
    }
    ret = 0;
done:
    return ret;
}

Chekupedzisira, heino basa redu rinovhura socket uye kutumira yakakosha meseji kwairi ine faira descriptor:

static int xdp_attach(int ifindex, int prog_fd)
{
    int sock, seq = 0, ret;
    struct nlattr *nla, *nla_xdp;
    struct {
        struct nlmsghdr  nh;
        struct ifinfomsg ifinfo;
        char             attrbuf[64];
    } req;
    __u32 nl_pid = 0;

    sock = netlink_open(&nl_pid);
    if (sock < 0)
        return sock;

    memset(&req, 0, sizeof(req));
    req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
    req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
    req.nh.nlmsg_type = RTM_SETLINK;
    req.nh.nlmsg_pid = 0;
    req.nh.nlmsg_seq = ++seq;
    req.ifinfo.ifi_family = AF_UNSPEC;
    req.ifinfo.ifi_index = ifindex;

    /* started nested attribute for XDP */
    nla = (struct nlattr *)(((char *)&req)
            + NLMSG_ALIGN(req.nh.nlmsg_len));
    nla->nla_type = NLA_F_NESTED | IFLA_XDP;
    nla->nla_len = NLA_HDRLEN;

    /* add XDP fd */
    nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
    nla_xdp->nla_type = IFLA_XDP_FD;
    nla_xdp->nla_len = NLA_HDRLEN + sizeof(int);
    memcpy((char *)nla_xdp + NLA_HDRLEN, &prog_fd, sizeof(prog_fd));
    nla->nla_len += nla_xdp->nla_len;

    /* if user passed in any flags, add those too */
    __u32 flags = XDP_FLAGS_SKB_MODE;
    nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
    nla_xdp->nla_type = IFLA_XDP_FLAGS;
    nla_xdp->nla_len = NLA_HDRLEN + sizeof(flags);
    memcpy((char *)nla_xdp + NLA_HDRLEN, &flags, sizeof(flags));
    nla->nla_len += nla_xdp->nla_len;

    req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len);

    if (send(sock, &req, req.nh.nlmsg_len, 0) < 0)
        err(1, "send");
    ret = bpf_netlink_recv(sock, nl_pid, seq);

cleanup:
    close(sock);
    return ret;
}

Saka, zvese zvakagadzirira kuyedzwa:

$ cc nolibbpf.c -o nolibbpf
$ sudo strace -e bpf ./nolibbpf
bpf(BPF_MAP_CREATE, {map_type=BPF_MAP_TYPE_ARRAY, map_name="woo", ...}, 72) = 3
bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_XDP, insn_cnt=15, prog_name="woo", ...}, 72) = 4
+++ exited with 0 +++

Ngationei kana chirongwa chedu chakabatana lo:

$ ip l show dev lo
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 xdpgeneric qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    prog/xdp id 160

Ngatitumire pings uye titarise pamepu:

$ for s in `seq 234`; do sudo ping -f -c 100 127.0.0.1 >/dev/null 2>&1; done
$ sudo bpftool m dump name woo
key: 00 00 00 00  value: 90 01 00 00 00 00 00 00
key: 01 00 00 00  value: 00 00 00 00 00 00 00 00
key: 02 00 00 00  value: 00 00 00 00 00 00 00 00
key: 03 00 00 00  value: 00 00 00 00 00 00 00 00
key: 04 00 00 00  value: 00 00 00 00 00 00 00 00
key: 05 00 00 00  value: 00 00 00 00 00 00 00 00
key: 06 00 00 00  value: 40 b5 00 00 00 00 00 00
key: 07 00 00 00  value: 00 00 00 00 00 00 00 00
Found 8 elements

Hurray, zvese zvinoshanda. Ziva, nenzira, kuti mepu yedu inoratidzwa zvakare nenzira yemabhaiti. Izvi zvinokonzerwa nekuti, zvakasiyana libbpf isu hatina kurodha ruzivo rwemhando (BTF). Asi tichazotaura zvakawanda nezvazvo nguva inotevera.

Zvishandiso zvekuvandudza

Muchikamu chino, isu tichatarisa iyo shoma BPF developer toolkit.

Kazhinji kutaura, haudi chero chinhu chakakosha kugadzira zvirongwa zveBPF - BPF inomhanya pane chero yakanaka yekugovera kernel, uye zvirongwa zvinovakwa zvichishandiswa. clang, iyo inogona kupihwa kubva pasuru. Nekudaro, nekuda kwekuti BPF iri pasi pekuvandudzwa, kernel uye maturusi ari kuramba achichinja, kana iwe usingade kunyora zvirongwa zveBPF uchishandisa nzira dzechinyakare kubva 2019, ipapo uchafanirwa kuunganidza.

  • llvm/clang
  • pahole
  • musimboti wayo
  • bpftool

(Kureva, chikamu ichi nemienzaniso yese iri muchinyorwa ichi yakamhanyiswa paDebian 10.)

llvm/clang

BPF inoshamwaridzana neLLVM uye, kunyangwe zvirongwa zveBPF zvichangoburwa zvichigona kuunganidzwa uchishandisa gcc, zvese zviri kuitika zvinoitirwa LLVM. Naizvozvo, chekutanga pane zvese, isu tichavaka iyo yazvino vhezheni clang kubva git:

$ sudo apt install ninja-build
$ git clone --depth 1 https://github.com/llvm/llvm-project.git
$ mkdir -p llvm-project/llvm/build/install
$ cd llvm-project/llvm/build
$ cmake .. -G "Ninja" -DLLVM_TARGETS_TO_BUILD="BPF;X86" 
                      -DLLVM_ENABLE_PROJECTS="clang" 
                      -DBUILD_SHARED_LIBS=OFF 
                      -DCMAKE_BUILD_TYPE=Release 
                      -DLLVM_BUILD_RUNTIME=OFF
$ time ninja
... ΠΌΠ½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ спустя
$

Iye zvino tinogona kutarisa kana zvese zvakasangana nemazvo:

$ ./bin/llc --version
LLVM (http://llvm.org/):
  LLVM version 11.0.0git
  Optimized build.
  Default target: x86_64-unknown-linux-gnu
  Host CPU: znver1

  Registered Targets:
    bpf    - BPF (host endian)
    bpfeb  - BPF (big endian)
    bpfel  - BPF (little endian)
    x86    - 32-bit X86: Pentium-Pro and above
    x86-64 - 64-bit X86: EM64T and AMD64

(Mirairo yegungano clang kutorwa neni kubva bpf_devel_QA.)

Hatisi kuzoisa zvirongwa zvatichangobva kuvaka, asi panzvimbo pezvo tongozviwedzera kwazviri PATH, somuenzaniso:

export PATH="`pwd`/bin:$PATH"

(Izvi zvinogona kuwedzerwa kune .bashrc kana kune imwe faira. Ini pachangu, ndinowedzera zvinhu zvakadai ~/bin/activate-llvm.sh uye kana zvakakodzera ndinozviita . activate-llvm.sh.)

Pahole uye BTF

Zvinobatsira pahole inoshandiswa pakuvaka kernel kugadzira ruzivo rwekugadzirisa muBTF fomati. Hatisi kuzoenda mune zvakadzama muchinyorwa chino nezve ruzivo rweBTF tekinoroji, kunze kwekuti iri nyore uye tinoda kuishandisa. Saka kana iwe uchizovaka kernel yako, tanga kuvaka pahole (pasina pahole haugone kuvaka kernel nesarudzo CONFIG_DEBUG_INFO_BTF:

$ git clone https://git.kernel.org/pub/scm/devel/pahole/pahole.git
$ cd pahole/
$ sudo apt install cmake
$ mkdir build
$ cd build/
$ cmake -D__LIB=lib ..
$ make
$ sudo make install
$ which pahole
/usr/local/bin/pahole

Kernels yekuyedza neBPF

Kana ndichiongorora mikana yeBPF, ini ndinoda kuunganidza yangu chaiyo musimboti. Izvi, kazhinji kutaura, hazvidiwi, sezvo uchizokwanisa kuunganidza uye kurodha zvirongwa zveBPF pane kernel yekugovera, zvisinei, kuva nekernel yako kunobvumidza iwe kushandisa yazvino BPF maficha, ayo achaonekwa mukugovera kwako mumwedzi yakanyanya kunaka. , kana, sezvazvakaita kune mamwe maturusi ekugadzirisa haasungirwe zvachose mune ramangwana rinoonekwa. Zvakare, iyo musimboti wayo inoita kuti inzwe yakakosha kuyedza iyo kodhi.

Kuti ugadzire kernel yaunoda, chekutanga, iyo kernel pachayo, uye chechipiri, kernel yekumisikidza faira. Kuedza neBPF tinogona kushandisa zvakajairwa vanilla kernel kana imwe yembeu dzekusimudzira. Nhoroondo, BPF budiriro inoitika mukati meLinux networking nharaunda uye nekudaro zvese zvinoshanduka nekukurumidza kana gare gare kuenda kuburikidza naDavid Miller, iyo Linux networking muchengeti. Zvichienderana nehunhu hwavo - edits kana nyowani maficha - network shanduko inowira mune imwe yemacores maviri - net kana net-next. Shanduko dzeBPF dzinogoverwa nenzira imwechete pakati bpf ΠΈ bpf-next, izvo zvinobva zvabatanidzwa mumambure uye net-inotevera, zvichiteerana. Kuti uwane rumwe ruzivo, ona bpf_devel_QA ΠΈ netdev-FAQ. Saka sarudza kernel zvichienderana nekuravira kwako uye nekugadzikana kwezvinodiwa zve system yauri kuyedza pairi (*-next kernels ndidzo dzisina kugadzikana pane dzakanyorwa).

Zviri kunze kwechikamu chechinyorwa ichi kutaura nezve maitiro ekugadzirisa kernel mafaera - zvinofungidzirwa kuti iwe unotoziva kuita izvi, kana vakagadzirira kudzidza pachezvake. Zvisinei, mirairo inotevera inofanira kuva yakawanda kana shoma zvakakwana kuti ikupe inoshanda BPF-enabled system.

Dhaunirodha imwe kernels dziri pamusoro:

$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git
$ cd bpf-next

Vaka idiki yekushanda kernel config:

$ cp /boot/config-`uname -r` .config
$ make localmodconfig

Gonesa BPF sarudzo mufaira .config yezvisarudzo zvako (kazhinji CONFIG_BPF ichave yatogoneswa kubvira systemd inoishandisa). Heino rondedzero yesarudzo kubva kune kernel inoshandiswa pachinyorwa ichi:

CONFIG_CGROUP_BPF=y
CONFIG_BPF=y
CONFIG_BPF_LSM=y
CONFIG_BPF_SYSCALL=y
CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y
CONFIG_BPF_JIT_ALWAYS_ON=y
CONFIG_BPF_JIT_DEFAULT_ON=y
CONFIG_IPV6_SEG6_BPF=y
# CONFIG_NETFILTER_XT_MATCH_BPF is not set
# CONFIG_BPFILTER is not set
CONFIG_NET_CLS_BPF=y
CONFIG_NET_ACT_BPF=y
CONFIG_BPF_JIT=y
CONFIG_BPF_STREAM_PARSER=y
CONFIG_LWTUNNEL_BPF=y
CONFIG_HAVE_EBPF_JIT=y
CONFIG_BPF_EVENTS=y
CONFIG_BPF_KPROBE_OVERRIDE=y
CONFIG_DEBUG_INFO_BTF=y

Ipapo isu tinokwanisa kuunganidza nyore uye kuisa mamodule uye kernel (nenzira, unogona kuunganidza kernel uchishandisa ichangobva kuunganidzwa. clangnekuwedzera CC=clang):

$ make -s -j $(getconf _NPROCESSORS_ONLN)
$ sudo make modules_install
$ sudo make install

uye tangazve neiyo kernel itsva (ini ndinoshandisa iyi kexec kubva pasuru kexec-tools):

v=5.8.0-rc6+ # Ссли Π²Ρ‹ пСрСсобираСтС Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ ядро, Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ Π΄Π΅Π»Π°Ρ‚ΡŒ v=`uname -r`
sudo kexec -l -t bzImage /boot/vmlinuz-$v --initrd=/boot/initrd.img-$v --reuse-cmdline &&
sudo kexec -e

bpftool

Chinonyanya kushandiswa chinoshandiswa munyaya yacho chichava chekushandisa bpftool, yakapihwa sechikamu cheLinux kernel. Yakanyorwa uye inochengetwa nevagadziri veBPF yevagadziri veBPF uye inogona kushandiswa kubata ese marudzi ezvinhu zveBPF - kurodha zvirongwa, kugadzira uye kugadzirisa mamepu, kuongorora hupenyu hweBPF ecosystem, nezvimwe. Zvinyorwa mumhando yemasource codes emapeji emunhu anogona kuwanikwa mukatikati kana, yakatounganidzwa, pamambure.

Panguva yekunyora uku bpftool inouya yakagadzirira-yakagadzirirwa chete RHEL, Fedora uye Ubuntu (ona, semuenzaniso, thread iyi, iyo inotaura nyaya isina kupera yekurongedza bpftool muDebian). Asi kana watovaka kernel yako, wobva wavaka bpftool zviri nyore sepai:

$ cd ${linux}/tools/bpf/bpftool
# ... ΠΏΡ€ΠΎΠΏΠΈΡˆΠΈΡ‚Π΅ ΠΏΡƒΡ‚ΠΈ ΠΊ послСднСму clang, ΠΊΠ°ΠΊ рассказано Π²Ρ‹ΡˆΠ΅
$ make -s

Auto-detecting system features:
...                        libbfd: [ on  ]
...        disassembler-four-args: [ on  ]
...                          zlib: [ on  ]
...                        libcap: [ on  ]
...               clang-bpf-co-re: [ on  ]

Auto-detecting system features:
...                        libelf: [ on  ]
...                          zlib: [ on  ]
...                           bpf: [ on  ]

$

(Hona ${linux} - iyi ndiyo kernel directory yako.) Mushure mekuita mirairo iyi bpftool ichaunganidzwa mudhairekitori ${linux}/tools/bpf/bpftool uye inogona kuwedzerwa kunzira (kutanga kune mushandisi root) kana kungokopa ku /usr/local/sbin.

Unganidza bpftool zviri nani kushandisa yekupedzisira clang, yakaunganidzwa sezvakatsanangurwa pamusoro, uye tarisa kana yakaunganidzwa zvakarurama - kushandisa, somuenzaniso, murairo

$ sudo bpftool feature probe kernel
Scanning system configuration...
bpf() syscall for unprivileged users is enabled
JIT compiler is enabled
JIT compiler hardening is disabled
JIT compiler kallsyms exports are enabled for root
...

iyo inoratidza kuti ndeapi maficha eBPF anogoneswa mukernel yako.

Nenzira, iyo yapfuura rairo inogona kumhanya se

# bpftool f p k

Izvi zvinoitwa nekuenzanisa nezvinoshandiswa kubva pasuru iproute2, kwatinogona, somuenzaniso, kutaura ip a s eth0 panzvimbo ye ip addr show dev eth0.

mhedziso

BPF inokutendera kuti upfeke shangu nhata kuti unyatso kuyera uye pa-iyo-inobhururuka shandura mashandiro epakati. Iyo sisitimu yakave yakabudirira kwazvo, mutsika dzakanakisa dzeUNIX: nzira yakapusa inobvumidza iwe (re) kuronga kernel yakabvumira huwandu hukuru hwevanhu nemasangano kuedza. Uye, kunyangwe zviedzo, pamwe nekuvandudzwa kweiyo BPF zvivakwa pachayo, zviri kure nekupedzwa, iyo sisitimu yatova neyakagadzika ABI inobvumidza iwe kuvaka yakavimbika, uye inonyanya kukosha, inoshanda bhizinesi logic.

Ndinoda kuziva kuti, mumaonero angu, tekinoroji yave yakakurumbira nekuti, kune rumwe rutivi, inogona ΠΈΠ³Ρ€Π°Ρ‚ΡŒ (mavakirwo emuchina anogona kunzwisiswa zvakanyanya kana zvishoma mune imwe manheru), uye kune rumwe rutivi, kugadzirisa matambudziko aisagona kugadziriswa (zvakanaka) isati yaonekwa. Zvikamu zviviri izvi pamwe chete zvinomanikidza vanhu kuti vaedze uye varote, izvo zvinotungamira mukubuda kwemamwe magadzirirwo emhinduro.

Ichi chinyorwa, kunyange chisina kunyanya kupfupika, ingori sumo kune nyika yeBPF uye haitsananguri "yepamusoro" maficha uye akakosha zvikamu zvezvivakwa. Urongwa hwekuenda kumberi hwakafanana neichi: chinyorwa chinotevera chichava mhedziso yemhando dzehurongwa hweBPF (kune marudzi ezvirongwa makumi matatu anotsigirwa mu5.8 kernel), tozopedzisira tatarisa manyorerwo echokwadi eBPF tichishandisa kernel yekutsvaga zvirongwa. semuenzaniso, yave nguva yekosi yakadzama pane BPF architecture, inoteverwa nemienzaniso yeBPF networking uye kuchengetedza zvikumbiro.

Nyaya dzakapfuura munhevedzano ino

  1. BPF yevadiki, chikamu zero: classic BPF

Links

  1. BPF uye XDP Reference Guide - zvinyorwa paBPF kubva kucilium, kana kunyanya kubva kunaDaniel Borkman, mumwe wevagadziri uye vanochengeta BPF. Iyi ndiyo imwe yetsanangudzo dzakakomba dzokutanga, dzakasiana nedzimwe mukuti Dhanieri anonyatsoziva zvaari kunyora uye hapana mhosho imomo. Kunyanya, gwaro iri rinotsanangura maitiro ekushanda neBPF zvirongwa zveXDP neTC mhando uchishandisa inozivikanwa utility. ip kubva pasuru iproute2.

  2. Documentation/networking/filter.txt - faira rekutanga rine zvinyorwa zvekirasi uyezve BPF yakawedzerwa. Kuverenga kwakanaka kana iwe uchida kunyura mumutauro wegungano uye tekinoroji yekuvaka ruzivo.

  3. Blog nezve BPF kubva kufacebook. Inovandudzwa kashoma, asi zvakakodzera, saAlexei Starovoitov (munyori weBPF) naAndrii Nakryiko - (muchengeti) vanonyora ipapo. libbpf).

  4. Zvakavanzika zve bpftool. Iyo inovaraidza twitter tambo kubva kuQuentin Monnet ine mienzaniso uye zvakavanzika zvekushandisa bpftool.

  5. Dive muBPF: rondedzero yekuverenga zvinyorwa. Hofori (uye ichiri kuchengetwa) runyorwa rwezvinongedzo kune BPF zvinyorwa kubva kuQuentin Monnet.

Source: www.habr.com

Voeg