Nan kòmansman an te gen yon teknoloji epi li te rele BPF. Nou te gade li anvan yo, Ansyen Testaman atik nan seri sa a. Nan 2013, atravè efò yo nan Alexei Starovoitov ak Daniel Borkman, yon vèsyon amelyore nan li, optimize pou machin modèn 64-bit, te devlope ak enkli nan nwayo a Linux. Nouvo teknoloji sa a te rele yon ti tan BPF Entèn, Lè sa a, chanje non BPF pwolonje, epi kounye a, apre plizyè ane, tout moun tou senpleman rele li BPF.
Apeprè pale, BPF pèmèt ou kouri kòd abitrè itilizatè-apwovizyone nan espas nwayo Linux la, ak nouvo achitekti a te vin tèlman reyisi ke nou pral bezwen yon douzèn atik plis dekri tout aplikasyon li yo. (Sèl bagay devlopè yo pa t 'fè byen, jan ou ka wè nan kòd pèfòmans ki anba a, se te kreye yon logo desan.)
Atik sa a dekri estrikti machin vityèl BPF, koòdone nwayo pou travay ak BPF, zouti devlopman, ansanm ak yon apèsi tou kout, trè kout sou kapasite ki egziste deja, i.e. tout sa nou pral bezwen nan tan kap vini an pou yon etid pi fon nan aplikasyon yo pratik nan BPF.
Jere objè lè l sèvi avèk apèl sistèm bpf la. Avèk kèk konpreyansyon sou sistèm nan deja an plas, nou pral finalman gade nan ki jan yo kreye ak manipile objè ki soti nan espas itilizatè lè l sèvi avèk yon apèl sistèm espesyal - bpf(2).
Пишем программы BPF с помощью libbpf. Natirèlman, ou ka ekri pwogram lè l sèvi avèk yon apèl sistèm. Men, li difisil. Pou yon senaryo ki pi reyalis, pwogramasyon nikleyè devlope yon bibliyotèk libbpf. Nou pral kreye yon eskèlèt aplikasyon BPF debaz ke nou pral itilize nan egzanp ki vin apre yo.
Èd Kernel. La a nou pral aprann kijan pwogram BPF ka jwenn aksè nan fonksyon asistan nwayo a - yon zouti ki, ansanm ak kat, fondamantalman elaji kapasite nouvo BPF la konpare ak youn klasik la.
Aksè nan kat nan pwogram BPF. Nan pwen sa a, nou pral konnen ase yo konprann egzakteman ki jan nou ka kreye pwogram ki sèvi ak kat. Epi ann menm pran yon ti gade vit nan verifikatè a gwo ak vanyan sòlda.
Zouti devlopman. Ede seksyon sou kòman yo rasanble sèvis piblik ki nesesè yo ak nwayo pou eksperyans.
Konklizyon an. Nan fen atik la, moun ki li sa yo pral jwenn mo ki motive ak yon deskripsyon tou kout sou sa ki pral rive nan atik ki vin apre yo. Nou pral lis tou yon kantite lyen pou etid pwòp tèt ou pou moun ki pa gen dezi a oswa kapasite yo rete tann pou kontinyasyon an.
Entwodiksyon nan BPF Achitekti
Anvan nou kòmanse konsidere achitekti BPF a, nou pral refere yon dènye fwa (oh). BPF klasik, ki te devlope kòm yon repons a avènement de machin RISC ak rezoud pwoblèm nan nan filtraj pake efikas. Achitekti a te vin tèlman siksè ke, li te fèt nan katreventèn yo bèl nan Berkeley UNIX, li te pote nan pifò sistèm opere ki egziste deja, siviv nan ven yo fou epi li toujou jwenn nouvo aplikasyon.
Nouvo BPF a te devlope kòm yon repons a omniprésente nan machin 64-bit, sèvis nwaj ak bezwen an ogmante pou zouti pou kreye SDN (Sofisyel-ddefini ntravay). Devlope pa enjenyè rezo nwayo kòm yon ranplasman amelyore pou BPF klasik la, nouvo BPF la literalman sis mwa pita te jwenn aplikasyon nan travay la difisil nan trase sistèm Linux, epi kounye a, sis ane apre aparans li, nou pral bezwen yon atik antye pwochen jis pou lis diferan kalite pwogram yo.
Foto komik
Nan nwayo li yo, BPF se yon machin vityèl sandbox ki pèmèt ou kouri kòd "abitrè" nan espas nwayo san yo pa konpwomèt sekirite. Pwogram BPF yo kreye nan espas itilizatè, chaje nan nwayo a, epi konekte ak kèk sous evènman. Yon evènman ta ka, pou egzanp, livrezon yon pake nan yon koòdone rezo, lansman kèk fonksyon nwayo, elatriye. Nan ka yon pake, pwogram BPF a pral gen aksè a done yo ak metadata nan pake a (pou lekti ak, pètèt, ekri, tou depann de kalite pwogram nan); nan ka a nan kouri yon fonksyon nwayo, agiman yo nan fonksyon an, ki gen ladan konsèy sou memwa nwayo, elatriye.
Ann pran yon gade pi pre nan pwosesis sa a. Pou kòmanse, ann pale sou premye diferans ak BPF klasik, pwogram yo te ekri nan asanblaj. Nan nouvo vèsyon an, achitekti a te elaji pou pwogram yo te kapab ekri nan lang wo nivo, prensipalman, nan kou, nan C. Pou sa, yo te devlope yon backend pou llvm, ki pèmèt ou jenere bytecode pou achitekti BPF la.
Achitekti BPF te fèt, an pati, pou kouri avèk efikasite sou machin modèn yo. Pou fè sa a travay an pratik, BPF bytecode a, yon fwa chaje nan nwayo a, yo tradui nan kòd natif natal lè l sèvi avèk yon eleman ki rele yon du JIT (JUST In Time). Apre sa, si ou sonje, nan klasik BPF pwogram nan te chaje nan nwayo a ak tache ak sous evènman an atomik - nan yon kontèks yon apèl sistèm sèl. Nan nouvo achitekti a, sa rive nan de etap - premye, kòd la chaje nan nwayo a lè l sèvi avèk yon apèl sistèm. bpf(2)epi apre, pita, atravè lòt mekanis ki varye selon kalite pwogram nan, pwogram nan tache ak sous evènman an.
Isit la lektè a ka gen yon kesyon: èske li posib? Ki jan sekirite egzekisyon kòd sa a garanti? Sekirite egzekisyon garanti pou nou pa etap nan chaje pwogram BPF yo rele verifier (an angle etap sa a rele verifier epi mwen pral kontinye sèvi ak mo angle a):
Verifier se yon analizè estatik ki asire ke yon pwogram pa deranje operasyon nòmal nwayo a. Sa a, nan chemen an, pa vle di ke pwogram nan pa ka entèfere ak operasyon an nan sistèm nan - pwogram BPF, tou depann de kalite a, ka li ak reekri seksyon nan memwa nwayo, retounen valè nan fonksyon, taye, ajoute, reekri. e menm voye pakè rezo yo. Verifier garanti ke kouri yon pwogram BPF pa pral fè aksidan nwayo a epi ke yon pwogram ki, dapre règleman yo, gen aksè ekri, pou egzanp, done yo nan yon pake sortan, pa pral kapab ranplase memwa nwayo a deyò pake a. Nou pral gade nan verifikatè nan yon ti kras plis detay nan seksyon ki koresponn lan, apre nou fin fè konesans ak tout lòt eleman yo nan BPF.
Kidonk, kisa nou aprann jiskaprezan? Itilizatè a ekri yon pwogram nan C, chaje li nan nwayo a lè l sèvi avèk yon apèl sistèm bpf(2), kote li tcheke pa yon verifikatè ak tradui nan bytecode natif natal. Lè sa a, menm itilizatè a oswa yon lòt konekte pwogram nan sous evènman an epi li kòmanse egzekite. Separe bòt ak koneksyon nesesè pou plizyè rezon. Premyèman, kouri yon verifikatè se relativman chè epi lè w telechaje menm pwogram nan plizyè fwa nou gaspiye tan òdinatè. Dezyèmman, egzakteman ki jan yon pwogram konekte depann sou kalite li yo, ak yon sèl "inivèsèl" koòdone devlope yon ane de sa ka pa apwopriye pou nouvo kalite pwogram. (Malgre ke kounye a ke achitekti a ap vin pi matirite, gen yon lide inifye koòdone sa a nan nivo a. libbpf.)
Lektè atantif la ka remake ke nou poko fini ak foto yo. Vreman vre, tout sa ki anwo yo pa eksplike poukisa BPF fondamantalman chanje foto a konpare ak BPF klasik. De inovasyon ki elaji siyifikativman sijè ki abòde lan aplikab yo se kapasite pou itilize memwa pataje ak fonksyon asistan nwayo. Nan BPF, pataje memwa aplike lè l sèvi avèk sa yo rele kat - estrikti done pataje ak yon API espesifik. Yo pwobableman te resevwa non sa a paske premye kalite kat ki parèt se te yon tab hash. Lè sa a, etalaj te parèt, lokal (pa CPU) tab hash ak etalaj lokal yo, pye bwa rechèch, kat ki gen konsèy sou pwogram BPF ak plis ankò. Ki sa ki enteresan pou nou kounye a se ke pwogram BPF kounye a gen kapasite nan pèsiste eta ant apèl yo epi pataje li ak lòt pwogram ak espas itilizatè.
Maps jwenn aksè nan pwosesis itilizatè yo lè l sèvi avèk yon apèl sistèm bpf(2), ak nan pwogram BPF ki kouri nan nwayo a lè l sèvi avèk fonksyon asistan. Anplis, moun k ap ede yo egziste pa sèlman pou travay ak kat, men tou pou jwenn aksè nan lòt kapasite nwayo. Pa egzanp, pwogram BPF yo ka sèvi ak fonksyon asistan pou voye pakè yo nan lòt koòdone, jenere evènman perf, jwenn aksè nan estrikti nwayo, ak sou sa.
An rezime, BPF bay kapasite pou chaje kòd itilizatè abitrè, sa vle di, verifye-teste, nan espas nwayo. Kòd sa a ka sove eta ant apèl yo ak echanj done ak espas itilizatè, epi tou li gen aksè a subsistèm nwayo ki pèmèt sa a kalite pwogram.
Sa a se deja menm jan ak kapasite yo bay nan modil nwayo, konpare ak ki BPF gen kèk avantaj (nan kou, ou ka sèlman konpare aplikasyon ki sanble, pou egzanp, trase sistèm - ou pa ka ekri yon chofè abitrè ak BPF). Ou ka sonje yon papòt antre pi ba (kèk sèvis piblik ki sèvi ak BPF pa mande pou itilizatè a gen ladrès pwogram nwayo, oswa konpetans nan pwogramasyon an jeneral), sekirite nan kouri (leve men ou nan kòmantè yo pou moun ki pa t 'kraze sistèm nan lè ekri. oswa modil tès), atomite - gen tan D 'lè rechaje modil yo, ak subsistèm BPF asire ke pa gen okenn evènman yo rate (yo dwe jis, sa a se pa vre pou tout kalite pwogram BPF).
Prezans nan kapasite sa yo fè BPF yon zouti inivèsèl pou elaji nwayo a, ki se konfime nan pratik: pi plis ak plis nouvo kalite pwogram yo ajoute nan BPF, pi plis ak plis gwo konpayi itilize BPF sou sèvè konba 24 × 7, pi plis ak plis. startups bati biznis yo sou solisyon ki baze sou ki baze sou BPF. BPF yo itilize toupatou: nan pwoteje kont atak DDoS, kreye SDN (pa egzanp, mete ann aplikasyon rezo pou kubernetes), kòm zouti prensipal trase sistèm ak pèseptè estatistik, nan sistèm deteksyon entrizyon ak sistèm sandbox, elatriye.
Ann fini pati apèsi atik la isit la epi gade machin vityèl la ak ekosistèm BPF an plis detay.
Digression: sèvis piblik
Pou kapab kouri egzanp yo nan seksyon sa yo, ou ka bezwen yon kantite sèvis piblik, omwen llvm/clang ak sipò bpf ak bpftool... Nan chapit la Zouti Devlopman Ou ka li enstriksyon yo pou rasanble sèvis piblik yo, osi byen ke nwayo ou a. Seksyon sa a mete anba a pou pa deranje amoni nan prezantasyon nou an.
BPF Virtual Machine Enskri ak Sistèm Enstriksyon
Yo te devlope achitekti ak sistèm lòd BPF pran an kont lefèt ke pwogram yo pral ekri nan lang C a epi, apre yo fin chaje nan nwayo a, yo pral tradui nan kòd natif natal. Se poutèt sa, kantite rejis ak seri kòmandman yo te chwazi ak yon je nan entèseksyon an, nan sans matematik, nan kapasite yo nan machin modèn. Anplis de sa, divès kalite restriksyon yo te enpoze sou pwogram yo, pou egzanp, jiska dènyèman li pa t posib yo ekri bouk ak souroutines, ak kantite enstriksyon yo te limite a 4096 (kounye a pwogram privilejye yo ka chaje jiska yon milyon enstriksyon).
BPF gen onz rejis 64-bit aksesib pou itilizatè r0-r10 ak yon kontwa pwogram. Enskri r10 gen yon konsèy ankadreman epi li sèlman pou li. Pwogram yo gen aksè a yon pil 512-byte nan ègzekutabl ak yon kantite san limit memwa pataje sou fòm kat yo.
Pwogram BPF yo gen dwa kouri yon seri espesifik nan asistan nwayo ki kalite pwogram ak, pi resamman, fonksyon regilye. Chak fonksyon rele ka pran jiska senk agiman, pase nan rejis r1-r5, epi yo pase valè retounen nan r0. Li garanti ke apre retounen soti nan fonksyon an, sa ki nan enskri yo r6-r9 Pa pral chanje.
Pou tradiksyon pwogram efikas, anrejistre r0-r11 pou tout achitekti sipòte yo inikman trase nan rejis reyèl, pran an kont karakteristik yo ABI nan achitekti aktyèl la. Pou egzanp, pou x86_64 anrejistre r1-r5, yo itilize pou pase paramèt fonksyon, yo parèt sou rdi, rsi, rdx, rcx, r8, ki itilize pou pase paramèt fonksyon yo x86_64. Pou egzanp, kòd ki sou bò gòch la tradui nan kòd ki sou bò dwat la tankou sa a:
Rejis la r0 tou itilize yo retounen rezilta a nan ekzekisyon pwogram, ak nan rejis la r1 se pwogram nan pase yon pwent nan kontèks la - depann sou kalite a nan pwogram, sa a ta ka, pou egzanp, yon estrikti. struct xdp_md (pou XDP) oswa estrikti struct __sk_buff (pou diferan pwogram rezo) oswa estrikti struct pt_regs (pou diferan kalite pwogram tras), elatriye.
Se konsa, nou te gen yon seri rejis, asistan nwayo, yon pil, yon konsèy kontèks ak memwa pataje sou fòm kat. Se pa ke tout bagay sa yo se absoliman nesesè nan vwayaj la, men ...
Ann kontinye deskripsyon an epi pale sou sistèm lòd pou travay ak objè sa yo. Tout (Prèske tout) Enstriksyon BPF yo gen yon gwosè fiks 64-bit. Si ou gade nan yon enstriksyon sou yon machin Big Endian 64-bit ou pral wè
Isit la Code - sa a se kodaj enstriksyon an, Dst/Src se kodaj reseptè a ak sous, respektivman, Off - 16-bit siyen endentasyon, ak Imm se yon nonb antye relatif ki siyen 32-bit yo itilize nan kèk enstriksyon (menm jan ak konstan cBPF K). Kodaj Code gen youn nan de kalite:
Klas enstriksyon 0, 1, 2, 3 defini kòmandman pou travay ak memwa. Yo yo rele yo, BPF_LD, BPF_LDX, BPF_ST, BPF_STX, respektivman. Klas 4, 7 (BPF_ALU, BPF_ALU64) konstitye yon seri enstriksyon ALU. Klas 5, 6 (BPF_JMP, BPF_JMP32) genyen enstriksyon so.
Pli lwen plan pou etidye sistèm ansèyman BPF a se jan sa a: olye pou nou mete yon lis tout enstriksyon yo ak paramèt yo, nou pral gade yon koup nan egzanp nan seksyon sa a epi nan men yo li pral vin klè ki jan enstriksyon yo aktyèlman ap travay ak ki jan yo. manyèlman demonte nenpòt dosye binè pou BPF. Pou konsolide materyèl la pita nan atik la, nou pral rankontre tou ak enstriksyon endividyèl nan seksyon yo sou Verifier, JIT du, tradiksyon BPF klasik, osi byen ke lè etidye kat, apèl fonksyon, elatriye.
Ann gade nan yon egzanp kote nou konpile yon pwogram readelf-example.c epi gade nan binè ki kapab lakòz. Nou pral revele kontni orijinal la readelf-example.c anba a, apre nou retabli lojik li nan kòd binè:
Kòd kòmand yo egal b7, 15, b7 и 95. Sonje byen ke twa ti pi piti enpòtan yo se klas enstriksyon an. Nan ka nou an, katriyèm ti moso nan tout enstriksyon yo vid, kidonk klas enstriksyon yo se 7, 5, 7, 5, respektivman. BPF_ALU64, ak 5 se BPF_JMP. Pou tou de klas yo, fòma ansèyman an se menm (gade pi wo a) epi nou ka reekri pwogram nou an konsa (an menm tan an nou pral reekri kolòn ki rete yo nan fòm imen):
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
Operasyon b klas ALU64 - Eske BPF_MOV. Li bay yon valè nan rejis destinasyon an. Si bit la mete s (sous), Lè sa a, valè a pran nan rejis sous la, epi si, tankou nan ka nou an, li pa mete, Lè sa a, valè a pran nan jaden an. Imm. Se konsa, nan premye ak twazyèm enstriksyon yo nou fè operasyon an r0 = Imm. Pli lwen, JMP klas 1 operasyon se BPF_JEQ (sote si egal). Nan ka nou an, depi ti jan an S se zewo, li konpare valè rejis sous la ak jaden an Imm. Si valè yo kowenside, Lè sa a, tranzisyon an rive PC + Offkote PC, kòm dabitid, gen adrès pwochen ansèyman an. Finalman, JMP Klas 9 Operasyon se BPF_EXIT. Enstriksyon sa a mete fen nan pwogram nan, retounen nan nwayo a r0. Ann ajoute yon nouvo kolòn nan tablo nou an:
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
Nou ka reekri sa a nan yon fòm ki pi pratik:
r0 = 1
if (r1 == 0) goto END
r0 = 2
END:
exit
Si nou sonje sa ki nan rejis la r1 se pwogram nan pase yon konsèy nan kontèks la soti nan nwayo a, ak nan rejis la r0 valè a retounen nan nwayo a, Lè sa a, nou ka wè ke si konsèy la nan kontèks la se zewo, Lè sa a, nou retounen 1, epi otreman - 2. Ann tcheke si nou gen rezon lè nou gade sous la:
Wi, se yon pwogram san sans, men li tradwi nan sèlman kat enstriksyon senp.
Eksepsyon egzanp: 16-byte enstriksyon
Nou mansyone pi bonè ke kèk enstriksyon pran plis pase 64 Bits. Sa a aplike, pou egzanp, nan enstriksyon yo lddw (Kòd = 0x18 = BPF_LD | BPF_DW | BPF_IMM) - chaje yon mo doub soti nan jaden yo nan rejis la Imm... Reyalite a se sa Imm gen yon gwosè 32, ak yon mo doub se 64 bit, kidonk chaje yon valè imedya 64-bit nan yon rejis nan yon enstriksyon 64-bit pa pral travay. Pou fè sa, de enstriksyon adjasan yo itilize pou estoke dezyèm pati valè 64-bit la nan jaden an Imm... Egzanp:
Nou pral rankontre ankò ak enstriksyon yo lddw, lè nou pale sou demenajman ak travay ak kat.
Egzanp: demonte BPF lè l sèvi avèk zouti estanda
Se konsa, nou te aprann li kòd binè BPF epi nou pare pou analize nenpòt enstriksyon si sa nesesè. Sepandan, li vo di ke nan pratik li pi pratik ak pi vit demonte pwogram lè l sèvi avèk zouti estanda, pou egzanp:
(Mwen te premye aprann kèk nan detay ki dekri nan sou-seksyon sa a nan poste Alexei Starovoitov nan BPF Blog.)
Objè BPF - pwogram ak kat - yo kreye nan espas itilizatè lè l sèvi avèk kòmandman BPF_PROG_LOAD и BPF_MAP_CREATE apèl sistèm bpf(2), nou pral pale sou egzakteman ki jan sa rive nan pwochen seksyon an. Sa a kreye estrikti done nwayo ak pou chak nan yo refcount (referans konte) mete sou youn, epi yon deskriptè fichye ki montre objè a retounen bay itilizatè a. Apre manch lan fèmen refcount objè a redwi pa youn, epi lè li rive nan zewo, objè a detwi.
Si pwogram nan itilize kat, lè sa a refcount kat sa yo ogmante pa youn apre yo fin chaje pwogram nan, sa vle di. deskriptè dosye yo ka fèmen nan pwosesis itilizatè a epi toujou refcount p ap vin zewo:
Apre w fin chaje yon pwogram avèk siksè, anjeneral nou tache li nan kèk kalite dèlko evènman. Pou egzanp, nou ka mete l 'sou yon koòdone rezo a trete pake fèk ap rantre oswa konekte li nan kèk tracepoint nan nwayo a. Nan pwen sa a, kontwa referans lan ap ogmante tou pa youn epi nou pral kapab fèmen deskriptè dosye a nan pwogram loader a.
Kisa k ap pase si kounye a nou fèmen bootloader la? Sa depann de ki kalite dèlko evènman (kwòk). Tout kwòk rezo ap egziste apre loader a fini, sa yo se sa yo rele kwòk mondyal yo. Epi, pou egzanp, pwogram tras yo pral lage apre pwosesis ki te kreye yo fini (ak Se poutèt sa yo rele lokal, soti nan "lokal nan pwosesis la"). Teknikman, kwòk lokal yo toujou gen yon deskriptè fichye ki koresponn nan espas itilizatè yo e se poutèt sa fèmen lè pwosesis la fèmen, men kwòk mondyal yo pa fè sa. Nan figi sa a, lè l sèvi avèk kwa wouj, mwen eseye montre ki jan revokasyon an nan pwogram nan loader afekte lavi a nan objè nan ka kwòk lokal ak mondyal.
Poukisa gen yon distenksyon ant kwòk lokal ak mondyal? Kouri kèk kalite pwogram rezo fè sans san yon espas itilizatè, pou egzanp, imajine pwoteksyon DDoS - bootloader a ekri règ yo epi konekte pwogram BPF a nan koòdone rezo a, apre sa bootloader a ka ale epi touye tèt li. Nan lòt men an, imajine yon pwogram tras debogaj ke ou te ekri sou jenou ou nan dis minit - lè li fini, ou ta renmen pa gen okenn fatra kite nan sistèm nan, ak zen lokal yo pral asire sa.
Nan lòt men an, imajine ke ou vle konekte ak yon tracepoint nan nwayo a epi kolekte estatistik sou plizyè ane. Nan ka sa a, ou ta vle ranpli pati itilizatè a epi retounen nan estatistik yo de tan zan tan. Sistèm fichye bpf bay opòtinite sa a. Li se yon sistèm pseudo-fichye ki nan memwa sèlman ki pèmèt kreyasyon fichye ki fè referans ak objè BPF epi kidonk ogmante. refcount objè yo. Apre sa, loader a ka sòti, ak objè yo li te kreye yo ap rete vivan.
Kreye fichye nan bpffs ki fè referans a objè BPF yo rele "pinning" (tankou nan fraz sa a: "pwosesis ka pin yon pwogram BPF oswa kat"). Kreye objè fichye pou objè BPF fè sans non sèlman pou pwolonje lavi objè lokal yo, men tou pou itilizasyon objè mondyal yo - retounen nan egzanp lan ak pwogram pwoteksyon DDoS mondyal la, nou vle kapab vin gade estatistik. de tanzantan.
Se sistèm nan dosye BPF anjeneral monte nan /sys/fs/bpf, men li kapab tou monte lokalman, pou egzanp, tankou sa a:
$ mkdir bpf-mountpoint
$ sudo mount -t bpf none bpf-mountpoint
Non sistèm dosye yo kreye lè l sèvi avèk kòmandman an BPF_OBJ_PIN Rele sistèm BPF. Pou ilistre, ann pran yon pwogram, konpile li, telechaje li, epi pin li nan bpffs. Pwogram nou an pa fè anyen ki itil, nou sèlman prezante kòd la pou ou ka repwodui egzanp lan:
Koulye a, ann telechaje pwogram nou an lè l sèvi avèk sèvis piblik la bpftool epi gade apèl sistèm ki akonpaye yo bpf(2) (kèk liy petinan retire nan pwodiksyon strace):
Isit la nou te chaje pwogram nan lè l sèvi avèk BPF_PROG_LOAD, te resevwa yon deskriptè fichye ki soti nan nwayo a 3 epi itilize kòmandman an BPF_OBJ_PIN fikse deskriptè fichye sa a kòm yon fichye "bpf-mountpoint/test". Apre sa, pwogram bootloader la bpftool fini travay, men pwogram nou an rete nan nwayo a, byenke nou pa tache li nan okenn koòdone rezo:
$ 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
Nou ka efase objè a fichye nòmalman unlink(2) epi apre sa yo pral efase pwogram ki koresponn lan:
$ sudo rm ./bpf-mountpoint/test
$ sudo bpftool prog show id 783
Error: get by id (783): No such file or directory
Efase objè yo
Pale sou efase objè, li nesesè klarifye ke apre nou te dekonekte pwogram nan nan zen an (dèlko evènman), pa yon sèl nouvo evènman pral deklanche lansman li yo, sepandan, tout sikonstans aktyèl nan pwogram nan pral fini nan lòd nòmal la. .
Gen kèk kalite pwogram BPF pèmèt ou ranplase pwogram nan sou vole, i.e. bay atomite sekans replace = detach old program, attach new program. Nan ka sa a, tout sikonstans aktif nan vèsyon an ansyen nan pwogram nan pral fini travay yo, ak nouvo moun kap okipe evènman yo pral kreye nan nouvo pwogram nan, ak "atomisite" isit la vle di ke pa pral yon sèl evènman rate.
Tache pwogram nan sous evènman yo
Nan atik sa a, nou pa pral dekri separeman konekte pwogram ak sous evènman, paske li fè sans pou etidye sa a nan yon kontèks yon kalite pwogram espesifik. Cm. egzanp anba a, kote nou montre kouman pwogram tankou XDP yo konekte.
Manipile objè lè l sèvi avèk apèl sistèm bpf la
Pwogram BPF
Tout objè BPF yo kreye ak jere nan espas itilizatè lè l sèvi avèk yon apèl sistèm bpf, ki gen pwototip sa a:
#include <linux/bpf.h>
int bpf(int cmd, union bpf_attr *attr, unsigned int size);
Men ekip la cmd se youn nan valè yo nan kalite enum bpf_cmd, attr — yon konsèy sou paramèt pou yon pwogram espesifik ak size - gwosè objè dapre konsèy la, i.e. anjeneral sa a sizeof(*attr). Nan du 5.8 apèl sistèm lan bpf sipòte 34 kòmandman diferan, ak definisyonunion bpf_attr okipe 200 liy. Men, nou pa ta dwe entimide pa sa a, depi nou pral familyarize tèt nou ak kòmandman yo ak paramèt sou kou a nan plizyè atik.
Ann kòmanse ak ekip la BPF_PROG_LOAD, ki kreye pwogram BPF - pran yon seri enstriksyon BPF epi chaje li nan nwayo a. Nan moman sa a nan loading, verifikatè a te lanse, ak Lè sa a, konpilatè JIT la epi, apre ekzekisyon siksè, deskriptè dosye pwogram nan retounen bay itilizatè a. Nou te wè sa k ap pase l apre nan seksyon anvan an sou sik lavi objè BPF yo.
Nou pral kounye a ekri yon pwogram koutim ki pral chaje yon pwogram BPF senp, men anvan nou bezwen deside ki kalite pwogram nou vle chaje - nou pral oblije chwazi di ki kalite ak nan kad sa a kalite, ekri yon pwogram ki pral pase tès la verifye. Sepandan, yo nan lòd yo pa konplike pwosesis la, isit la se yon solisyon pare-fè: nou pral pran yon pwogram tankou BPF_PROG_TYPE_XDP, ki pral retounen valè a XDP_PASS (sote tout pakè). Nan BPF assembler li sanble trè senp:
r0 = 2
exit
Apre nou te deside sou ki nou pral telechaje, nou ka di ou ki jan nou pral fè li:
Evènman enteresan nan yon pwogram kòmanse ak definisyon yon etalaj insns - pwogram BPF nou an nan kòd machin. Nan ka sa a, chak enstriksyon nan pwogram BPF chaje nan estrikti a bpf_insn. Premye eleman insns konfòme ak enstriksyon yo r0 = 2, dezyèm lan - exit.
Retrè. Kernel la defini makro ki pi pratik pou ekri kòd machin yo, epi itilize dosye header nwayo a tools/include/linux/filter.h nou te kapab ekri
Men, depi ekri pwogram BPF nan kòd natif natal sèlman nesesè pou ekri tès nan nwayo a ak atik sou BPF, absans makro sa yo pa vrèman konplike lavi pwomotè a.
Apre nou fin defini pwogram BPF a, nou ale nan chaje li nan nwayo a. Seri minimalist nou an nan paramèt attr gen ladan kalite pwogram, seri ak kantite enstriksyon, lisans obligatwa, ak non "woo", ke nou itilize pou jwenn pwogram nou an sou sistèm nan apre telechaje. Pwogram nan, jan yo te pwomèt la, chaje nan sistèm nan lè l sèvi avèk yon apèl sistèm bpf.
Nan fen pwogram nan nou fini nan yon bouk enfini ki simulation chaj la. San li, pwogram nan pral touye pa nwayo a lè deskriptè fichye ke apèl sistèm lan retounen ba nou fèmen. bpf, epi nou pa pral wè li nan sistèm nan.
Oke, nou pare pou tès la. Ann rasanble epi kouri pwogram nan anba stracepou tcheke si tout bagay ap fonksyone jan li ta dwe:
Tout bagay anfòm, bpf(2) te retounen manch 3 pou nou epi nou te antre nan yon bouk enfini ak pause(). Ann eseye jwenn pwogram nou an nan sistèm nan. Pou fè sa, nou pral ale nan yon lòt tèminal epi sèvi ak sèvis piblik la bpftool:
Nou wè ke gen yon pwogram chaje sou sistèm nan woo ki gen idantite mondyal se 390 epi li se kounye a nan pwogrè simple-prog gen yon deskriptè dosye louvri ki montre pwogram nan (e si simple-prog pral fini travay la, lè sa a woo pral disparèt). Kòm espere, pwogram nan woo pran 16 bytes - de enstriksyon - nan kòd binè nan achitekti BPF a, men nan fòm natif natal li (x86_64) li deja 40 bytes. Ann gade pwogram nou an nan fòm orijinal li:
pa gen sipriz. Koulye a, ann gade nan kòd ki te pwodwi pa du JIT la:
# 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
pa trè efikas pou exit(2), men ann jistis, pwogram nou an twò senp, epi pou pwogram ki pa trivial, prològ ak epilòg ki te ajoute pa du JIT la, nan kou, nesesè.
Kat
Pwogram BPF ka itilize zòn memwa estriktire ki aksesib tou de lòt pwogram BPF ak pwogram nan espas itilizatè. Objè sa yo rele kat epi nan seksyon sa a nou pral montre kijan pou manipile yo lè l sèvi avèk yon apèl sistèm bpf.
Ann di touswit ke kapasite kat yo pa limite sèlman ak aksè nan memwa pataje. Gen kat objektif espesyal ki genyen, pou egzanp, konsèy sou pwogram BPF oswa endikasyon sou koòdone rezo, kat pou travay ak evènman perf, elatriye. Nou pa pral pale sou yo isit la, pou yo pa konfonn lektè a. Apa de sa, nou inyore pwoblèm senkronizasyon, paske sa a pa enpòtan pou egzanp nou yo. Ou ka jwenn yon lis konplè kalite kat ki disponib nan <linux/bpf.h>, ak nan seksyon sa a nou pral pran kòm yon egzanp istorikman premye kalite a, tab la hash BPF_MAP_TYPE_HASH.
Si ou kreye yon tab hash nan, di, C++, ou ta di unordered_map<int,long> woo, ki nan Ris vle di "Mwen bezwen yon tab woo gwosè san limit, ki gen kle yo nan kalite int, ak valè yo se kalite a long" Yo nan lòd yo kreye yon tab hash BPF, nou bezwen fè anpil menm bagay la, eksepte ke nou dwe presize gwosè maksimòm tab la, epi olye pou yo presize kalite kle ak valè, nou bezwen presize gwosè yo an byte. . Pou kreye kat itilize kòmandman an BPF_MAP_CREATE apèl sistèm bpf. Ann gade yon pwogram plis oswa mwens minim ki kreye yon kat. Apre pwogram anvan an ki chaje pwogram BPF, sa a ta dwe sanble senp pou ou:
Isit la nou defini yon seri paramèt attr, nan ki nou di "Mwen bezwen yon tab hash ak kle ak valè gwosè sizeof(int), nan ki mwen ka mete yon maksimòm de kat eleman." Lè w ap kreye kat BPF, ou ka presize lòt paramèt, pou egzanp, nan menm fason an kòm nan egzanp lan ak pwogram nan, nou espesifye non an nan objè a kòm "woo".
Men apèl sistèm lan bpf(2) te retounen nou nimewo kat deskriptè a 3 ak Lè sa a, pwogram nan, jan yo espere, ap tann pou plis enstriksyon nan apèl la sistèm pause(2).
Koulye a, ann voye pwogram nou an nan background nan oswa louvri yon lòt tèminal epi gade nan objè nou an lè l sèvi avèk sèvis piblik la bpftool (nou ka distenge kat nou an de lòt moun pa non li):
$ sudo bpftool map
...
114: hash name woo flags 0x0
key 4B value 4B max_entries 4 memlock 4096B
...
Nimewo 114 se ID mondyal objè nou an. Nenpòt pwogram sou sistèm nan ka itilize ID sa a pou ouvri yon kat ki deja egziste lè l sèvi avèk kòmandman an BPF_MAP_GET_FD_BY_ID apèl sistèm bpf.
Koulye a, nou ka jwe ak tab hash nou an. Ann gade nan kontni li yo:
$ sudo bpftool map dump id 114
Found 0 elements
Vide. Ann mete yon valè ladan l hash[1] = 1:
$ sudo bpftool map update id 114 key 1 0 0 0 value 1 0 0 0
Ann gade tab la ankò:
$ sudo bpftool map dump id 114
key: 01 00 00 00 value: 01 00 00 00
Found 1 element
Houra! Nou jere ajoute yon sèl eleman. Remake byen ke nou dwe travay nan nivo byte pou fè sa, depi bptftool pa konnen ki kalite valè yo nan tablo hash la. (Konesans sa a ka transfere ba li lè l sèvi avèk BTF, men plis sou sa kounye a.)
Ki jan egzakteman bpftool li epi ajoute eleman? Ann pran yon gade anba kapo a:
Premye nou te louvri kat la pa ID mondyal li yo lè l sèvi avèk kòmandman an BPF_MAP_GET_FD_BY_ID и bpf(2) te retounen nou deskriptè 3. Plis itilize kòmandman an BPF_MAP_GET_NEXT_KEY nou jwenn premye kle nan tablo a pa pase NULL kòm yon konsèy sou "previous" kle a. Si nou gen kle a nou ka fè BPF_MAP_LOOKUP_ELEMki retounen yon valè nan yon konsèy value. Pwochen etap la se nou eseye jwenn pwochen eleman nan pase yon konsèy sou kle aktyèl la, men tab nou an gen sèlman yon eleman ak kòmandman an. BPF_MAP_GET_NEXT_KEY retounen ENOENT.
Oke, ann chanje valè a pa kle 1, ann di lojik biznis nou an mande pou enskri. hash[1] = 2:
Kòm espere, li trè senp: lòd la BPF_MAP_GET_FD_BY_ID ouvè kat nou an pa ID, ak lòd la BPF_MAP_UPDATE_ELEM ranplase eleman an.
Se konsa, apre yo fin kreye yon tab hash soti nan yon pwogram, nou ka li ak ekri sa ki nan yon lòt. Remake byen ke si nou te kapab fè sa nan liy lòd la, Lè sa a, nenpòt lòt pwogram sou sistèm nan ka fè li. Anplis kòmandman ki dekri pi wo a, pou travay ak kat ki soti nan espas itilizatè, Sa ki anba la:
BPF_MAP_LOOKUP_ELEM: jwenn valè pa kle
BPF_MAP_UPDATE_ELEM: mete ajou/kreye valè
BPF_MAP_DELETE_ELEM: retire kle
BPF_MAP_GET_NEXT_KEY: jwenn pwochen (oswa premye) kle a
BPF_MAP_GET_NEXT_ID: pèmèt ou ale nan tout kat ki egziste deja, se konsa li fonksyone bpftool map
BPF_MAP_GET_FD_BY_ID: louvri yon kat ki deja egziste pa ID mondyal li yo
BPF_MAP_LOOKUP_AND_DELETE_ELEM: atomik mete ajou valè yon objè epi retounen ansyen an
BPF_MAP_FREEZE: fè kat la imuiabl nan espas itilizatè (operasyon sa a pa ka defèt)
BPF_MAP_LOOKUP_BATCH, BPF_MAP_LOOKUP_AND_DELETE_BATCH, BPF_MAP_UPDATE_BATCH, BPF_MAP_DELETE_BATCH: operasyon an mas. Pa egzanp, BPF_MAP_LOOKUP_AND_DELETE_BATCH - sa a se sèl fason serye pou li ak Reyajiste tout valè nan kat la
Se pa tout kòmandman sa yo travay pou tout kalite kat, men an jeneral travay ak lòt kalite kat ki soti nan espas itilizatè sanble egzakteman menm jan ak travay ak tab hash.
Pou dedomajman pou lòd, an n fini eksperyans tab hash nou yo. Sonje ke nou te kreye yon tab ki ka genyen jiska kat kle? Ann ajoute kèk eleman plis:
$ 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
$ sudo bpftool map update id 114 key 5 0 0 0 value 1 0 0 0
Error: update failed: Argument list too long
Kòm espere, nou pa t reyisi. Ann gade erè a an plis detay:
$ 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 +++
Tout bagay anfòm: jan yo espere, ekip la BPF_MAP_UPDATE_ELEM eseye kreye yon nouvo, senkyèm, kle, men aksidan E2BIG.
Se konsa, nou ka kreye ak chaje pwogram BPF, osi byen ke kreye ak jere kat soti nan espas itilizatè. Koulye a, li lojik gade nan ki jan nou ka itilize kat nan pwogram yo BPF tèt yo. Nou ta ka pale sou sa a nan lang pwogram ki difisil pou li nan kòd makro machin, men an reyalite lè a rive pou montre kouman pwogram BPF yo aktyèlman ekri ak konsève - lè l sèvi avèk libbpf.
(Pou lektè ki pa satisfè ak mank de yon egzanp ki ba: nou pral analize an detay pwogram ki sèvi ak kat ak fonksyon asistan ki kreye lè l sèvi avèk libbpf epi di w sa k ap pase nan nivo enstriksyon an. Pou lektè ki pa satisfè anpil, nou te ajoute egzanp nan plas ki apwopriye nan atik la.)
Ekri pwogram BPF lè l sèvi avèk libbpf
Ekri pwogram BPF lè l sèvi avèk kòd machin yo ka enteresan sèlman premye fwa a, ak Lè sa a, sasyete mete nan. Nan moman sa a ou bezwen vire atansyon ou a llvm, ki gen yon backend pou jenere kòd pou achitekti BPF, osi byen ke yon bibliyotèk libbpf, ki pèmèt ou ekri bò itilizatè aplikasyon BPF epi chaje kòd pwogram BPF ki te pwodwi lè l sèvi avèk yo llvm/clang.
An reyalite, jan nou pral wè nan atik sa a ak atik ki vin apre yo, libbpf fè anpil travay san li (oswa zouti menm jan an - iproute2, libbcc, libbpf-go, elatriye) li enposib pou viv. Youn nan karakteristik yo ki asasen nan pwojè a libbpf se BPF CO-RE (Konpile yon fwa, kouri toupatou) - yon pwojè ki pèmèt ou ekri pwogram BPF ki pòtab soti nan yon nwayo nan yon lòt, ak kapasite nan kouri sou diferan APIs (pa egzanp, lè estrikti nwayo a chanje soti nan vèsyon an). nan vèsyon). Pou kapab travay ak CO-RE, nwayo ou a dwe konpile ak sipò BTF (nou dekri kijan pou fè sa nan seksyon an. Zouti Devlopman. Ou ka tcheke si nwayo ou a bati ak BTF oswa ou pa trè tou senpleman - pa prezans nan dosye sa a:
Fichye sa a estoke enfòmasyon sou tout kalite done yo itilize nan nwayo a epi yo itilize nan tout egzanp nou yo lè l sèvi avèk yo libbpf. Nou pral pale an detay sou CO-RE nan pwochen atik la, men nan yon sèl sa a - jis bati tèt ou yon nwayo ak CONFIG_DEBUG_INFO_BTF.
bibliyotèk libbpf ap viv dwat nan anyè a tools/lib/bpf Kernel ak devlopman li fèt atravè lis adrès la [email protected]. Sepandan, yo kenbe yon depo separe pou bezwen aplikasyon k ap viv deyò nwayo a https://github.com/libbpf/libbpf nan ki bibliyotèk nwayo a reflete pou aksè li plis oswa mwens jan li ye.
Nan seksyon sa a nou pral gade ki jan ou ka kreye yon pwojè ki itilize libbpf, ann ekri plizyè pwogram tès (plis oswa mwens san sans) epi analize an detay kijan tout bagay mache. Sa a pral pèmèt nou pi fasil eksplike nan seksyon sa yo egzakteman ki jan pwogram BPF kominike avèk kat, asistan nwayo, BTF, elatriye.
Tipikman pwojè lè l sèvi avèk libbpf ajoute yon depo GitHub kòm yon submodule git, nou pral fè menm bagay la:
Pwochen plan nou an nan seksyon sa a se jan sa a: nou pral ekri yon pwogram BPF tankou BPF_PROG_TYPE_XDP, menm jan ak nan egzanp anvan an, men nan C, nou konpile li lè l sèvi avèk clang, epi ekri yon pwogram asistan ki pral chaje li nan nwayo a. Nan seksyon sa yo nou pral elaji kapasite pwogram BPF ak pwogram asistan an.
Egzanp: kreye yon aplikasyon konplè lè l sèvi avèk libbpf
Pou kòmanse, nou itilize dosye a /sys/kernel/btf/vmlinux, ki te mansyone pi wo a, epi kreye ekivalan li yo nan fòm yon dosye header:
$ bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h
Fichye sa a pral estoke tout estrikti done ki disponib nan nwayo nou an, pou egzanp, men ki jan header IPv4 la defini nan nwayo a:
Malgre ke pwogram nou an te tounen trè senp, nou toujou bezwen peye atansyon sou anpil detay. Premyèman, premye dosye header nou enkli se vmlinux.h, ke nou jis pwodwi lè l sèvi avèk bpftool btf dump - kounye a nou pa bezwen enstale pake kernel-headers pou chèche konnen ki jan estrikti nwayo yo sanble. Fichye header sa a vin jwenn nou nan bibliyotèk la libbpf. Koulye a, nou sèlman bezwen li defini makro a SEC, ki voye karaktè a nan seksyon apwopriye nan fichye objè ELF la. Pwogram nou an genyen nan seksyon an xdp/simple, kote anvan koupe a nou defini kalite pwogram BPF - sa a se konvansyon yo itilize nan libbpf, ki baze sou non an seksyon li pral ranplase kalite ki kòrèk la nan demaraj bpf(2). Pwogram BPF nan tèt li se C - trè senp epi li konsiste de yon liy return XDP_PASS. Finalman, yon seksyon separe "license" gen non lisans lan.
Nou ka konpile pwogram nou an lè l sèvi avèk llvm/clang, vèsyon >= 10.0.0, oswa pi bon toujou, pi gwo (gade seksyon Zouti Devlopman):
Pami karakteristik yo ki enteresan: nou endike achitekti sib la -target bpf ak chemen an nan tèt yo libbpf, ke nou fèk enstale. Epitou, pa bliye sou -O2, san opsyon sa a ou ka nan pou sipriz nan tan kap vini an. Ann gade kòd nou an, èske nou te rive ekri pwogram nou te vle a?
Wi, li te travay! Koulye a, nou gen yon dosye binè ak pwogram nan, epi nou vle kreye yon aplikasyon ki pral chaje li nan nwayo a. Pou rezon sa a bibliyotèk la libbpf ofri nou de opsyon - sèvi ak yon API ki pi ba oswa yon API ki pi wo. Nou pral ale nan dezyèm wout la, depi nou vle aprann ki jan yo ekri, chaje ak konekte pwogram BPF ak efò minim pou etid ki vin apre yo.
Premyèman, nou bezwen jenere "skelèt" pwogram nou an soti nan binè li yo lè l sèvi avèk menm sèvis piblik la bpftool - kouto Swis nan mond BPF (ki ka pran literalman, depi Daniel Borkman, youn nan kreyatè ak mentnitè BPF, se Swis):
$ bpftool gen skeleton xdp-simple.bpf.o > xdp-simple.skel.h
Nan dosye xdp-simple.skel.h gen kòd binè pwogram nou an ak fonksyon pou jere - chaje, atache, efase objè nou an. Nan ka senp nou an, sa sanble twòp, men li travay tou nan ka kote fichye objè a gen anpil pwogram BPF ak kat epi pou chaje ELF jeyan sa a nou jis bezwen jenere kilè eskèlèt la epi rele youn oubyen de fonksyon nan aplikasyon koutim nou an. ap ekri Ann avanse kounye a.
Fè egzateman pale, pwogram loader nou an se trivial:
#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);
}
Isit la struct xdp_simple_bpf defini nan dosye a xdp-simple.skel.h epi dekri dosye objè nou an:
Nou ka wè tras nan yon API ba-nivo isit la: estrikti a struct bpf_program *simple и struct bpf_link *simple. Premye estrikti a espesyalman dekri pwogram nou an, ki ekri nan seksyon an xdp/simple, ak dezyèm lan dekri kijan pwogram nan konekte ak sous evènman an.
Fonksyon xdp_simple_bpf__open_and_load, ouvri yon objè ELF, analize li, kreye tout estrikti ak substruktur yo (anplis pwogram nan, ELF gen ladan tou lòt seksyon - done, done lekti sèlman, enfòmasyon debogaj, lisans, elatriye), ak Lè sa a, chaje li nan nwayo a lè l sèvi avèk yon sistèm. rele bpf, ke nou ka tcheke nan konpile ak kouri pwogram nan:
Ann gade kounye a nan pwogram nou an lè l sèvi avèk bpftool. Ann jwenn idantite li:
# 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)
ak pil fatra (nou itilize yon fòm ki pi kout nan lòd la bpftool prog dump xlated):
# bpftool p d x id 463
int simple(void *ctx):
; return XDP_PASS;
0: (b7) r0 = 2
1: (95) exit
Yon bagay nouvo! Pwogram nan enprime moso nan fichye sous C nou an. Se bibliyotèk la ki te fè sa libbpf, ki te jwenn seksyon debug la nan binè a, konpile li nan yon objè BTF, chaje li nan nwayo a lè l sèvi avèk BPF_BTF_LOAD, ak Lè sa a, espesifye deskriptè dosye a ki kapab lakòz lè w ap chaje pwogram nan ak lòd la BPG_PROG_LOAD.
Èd Kernel
Pwogram BPF ka kouri fonksyon "ekstèn" - kernel helpers. Fonksyon asistan sa yo pèmèt pwogram BPF jwenn aksè nan estrikti nwayo, jere kat, epi tou kominike ak "monn reyèl" - kreye evènman perf, kontwole pyès ki nan konpitè (pa egzanp, redireksyon pake), elatriye.
Egzanp: bpf_get_smp_processor_id
Nan kad paradigm "aprann pa egzanp", ann konsidere youn nan fonksyon èd yo, bpf_get_smp_processor_id(), sèten nan dosye kernel/bpf/helpers.c. Li retounen nimewo processeur kote pwogram BPF ki rele l ap kouri. Men, nou pa menm enterese nan semantik li yo tankou nan lefèt ke aplikasyon li pran yon liy:
Definisyon fonksyon asistan BPF yo sanble ak definisyon apèl sistèm Linux yo. Isit la, pou egzanp, yo defini yon fonksyon ki pa gen okenn agiman. (Yon fonksyon ki pran, di, twa agiman defini lè l sèvi avèk makro a BPF_CALL_3. Kantite maksimòm agiman se senk.) Sepandan, sa a se sèlman premye pati nan definisyon an. Dezyèm pati a se defini estrikti nan kalite struct bpf_func_proto, ki gen yon deskripsyon fonksyon asistan ke verifikatè konprann:
Pou pwogram BPF nan yon kalite patikilye yo sèvi ak fonksyon sa a, yo dwe anrejistre li, pou egzanp pou kalite a BPF_PROG_TYPE_XDP se yon fonksyon defini nan nwayo a xdp_func_proto, ki detèmine nan ID fonksyon asistan si XDP sipòte fonksyon sa a oswa ou pa. Fonksyon nou se sipò:
Nouvo kalite pwogram BPF yo "defini" nan dosye a include/linux/bpf_types.h lè l sèvi avèk yon macro BPF_PROG_TYPE. Defini nan quotes paske li se yon definisyon lojik, ak nan tèm lang C definisyon an nan yon seri antye nan estrikti konkrè rive nan lòt kote. An patikilye, nan dosye a kernel/bpf/verifier.c tout definisyon nan dosye bpf_types.h yo itilize pou kreye yon seri estrikti bpf_verifier_ops[]:
Sa vle di, pou chak kalite pwogram BPF, yo defini yon konsèy sou yon estrikti done nan kalite a struct bpf_verifier_ops, ki inisyalize ak valè a _name ## _verifier_ops, sa vle di, xdp_verifier_ops pou xdp. Estrikti xdp_verifier_opsdetèmine pa nan dosye net/core/filter.c jan sa a:
Isit la nou wè fonksyon abitye nou an xdp_func_proto, ki pral kouri verifikatè a chak fwa li rankontre yon defi kèk fonksyon andedan yon pwogram BPF, gade verifier.c.
Ann gade kijan yon pwogram BPF ipotetik itilize fonksyon an bpf_get_smp_processor_id. Pou fè sa, nou reekri pwogram nan nan seksyon anvan nou an jan sa a:
sa vle di bpf_get_smp_processor_id se yon pwent fonksyon ki gen valè 8, kote 8 se valè a BPF_FUNC_get_smp_processor_id kalite enum bpf_fun_id, ki defini pou nou nan dosye a vmlinux.h (dosye bpf_helper_defs.h nan nwayo a se yon script ki te pwodwi, kidonk nimewo "majik" yo ok). Fonksyon sa a pa pran okenn agiman epi li retounen yon valè kalite __u32. Lè nou kouri li nan pwogram nou an, clang jenere yon enstriksyon BPF_CALL "bon kalite" Ann konpile pwogram nan epi gade seksyon an xdp/simple:
Nan premye liy lan nou wè enstriksyon yo call, paramèt IMM ki egal a 8, epi SRC_REG - zewo. Dapre akò ABI ki itilize pa verifikatè a, sa a se yon apèl pou fonksyon asistan nimewo uit. Yon fwa li te lanse, lojik la se senp. Retounen valè nan enskri r0 kopye nan r1 epi sou liy 2,3 li konvèti an tip u32 - 32 bit yo anwo yo otorize. Sou liy 4,5,6,7 nou retounen 2 (XDP_PASS) oswa 1 (XDP_DROP) selon si fonksyon asistan ki soti nan liy 0 a te retounen yon valè zewo oswa ki pa zewo.
Ann teste tèt nou: chaje pwogram nan epi gade pwodiksyon an 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
Oke, verifikatè te jwenn kernel-helper ki kòrèk la.
Tout fonksyon asistan nan nivo kouri gen yon pwototip
u64 fn(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
Paramèt nan fonksyon asistan yo pase nan rejis r1-r5, epi valè a retounen nan rejis la r0. Pa gen okenn fonksyon ki pran plis pase senk agiman, epi sipò pou yo pa espere ajoute nan lavni.
Ann pran yon gade nan nouvo asistan nwayo a ak fason BPF pase paramèt yo. Ann reekri xdp-simple.bpf.c jan sa a (rès liy yo pa chanje):
SEC("xdp/simple")
int simple(void *ctx)
{
bpf_printk("running on CPU%un", bpf_get_smp_processor_id());
return XDP_PASS;
}
Pwogram nou an enprime nimewo CPU sou kote li ap kouri. Ann konpile li epi gade kòd la:
Nan liy 0-7 nou ekri fisèl la running on CPU%un, ak Lè sa a, sou liy 8 nou kouri youn nan abitye bpf_get_smp_processor_id. Sou liy 9-12 nou prepare agiman k ap ede yo bpf_printk - anrejistre r1, r2, r3. Poukisa gen twa nan yo epi yo pa de? Paske bpf_printk - sa a se yon anbalaj macro alantou vrè èd la bpf_trace_printk, ki bezwen pase gwosè fisèl fòma a.
Koulye a, an n ajoute yon koup nan liy yo xdp-simple.cse konsa ke pwogram nou an konekte ak koòdone la lo ak reyèlman te kòmanse!
Isit la nou itilize fonksyon an bpf_set_link_xdp_fd, ki konekte pwogram XDP-tip BPF nan koòdone rezo. Nou kode nimewo koòdone a lo, ki se toujou 1. Nou kouri fonksyon an de fwa nan premye detache ansyen pwogram nan si li te tache. Remake ke kounye a nou pa bezwen yon defi pause oswa yon bouk enfini: pwogram loader nou an pral sòti, men pwogram BPF la pa pral touye paske li konekte ak sous evènman an. Apre download siksè ak koneksyon, pwogram nan pral lanse pou chak pake rezo rive nan lo.
Ann telechaje pwogram nan epi gade koòdone a 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
Pwogram nou telechaje a gen ID 669 epi nou wè menm ID sou koòdone a lo. Nou pral voye yon koup de pakè nan 127.0.0.1 (demann + repons):
$ ping -c1 localhost
e kounye a, ann gade sa ki nan fichye vityèl debug la /sys/kernel/debug/tracing/trace_pipe, nan ki bpf_printk ekri mesaj li yo:
# 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
De pakè yo te takte sou lo epi trete sou CPU0 - premye pwogram BPF ki pa gen okenn sans konplè nou an te travay!
Li se vo anyen sa bpf_printk Se pa pou anyen ke li ekri nan dosye debug la: sa a se pa èd ki gen plis siksè pou itilize nan pwodiksyon, men objektif nou se te montre yon bagay ki senp.
Aksè kat nan pwogram BPF
Egzanp: lè l sèvi avèk yon kat ki soti nan pwogram BPF la
Nan seksyon anvan yo, nou te aprann kijan pou kreye epi sèvi ak kat nan espas itilizatè, epi kounye a ann gade pati nwayo a. Ann kòmanse, kòm dabitid, ak yon egzanp. Ann reekri pwogram nou an xdp-simple.bpf.c jan sa a:
Nan kòmansman pwogram nan nou te ajoute yon definisyon kat woo: Sa a se yon etalaj 8-eleman ki estoke valè tankou u64 (nan C nou ta defini tankou yon etalaj tankou u64 woo[8]). Nan yon pwogram "xdp/simple" nou jwenn nimewo processeur aktyèl la nan yon varyab key ak Lè sa a, sèvi ak fonksyon an èd bpf_map_lookup_element nou jwenn yon konsèy sou antre ki koresponn lan nan etalaj la, ke nou ogmante pa youn. Tradui an Ris: nou kalkile estatistik sou ki CPU trete pake fèk ap rantre. Ann eseye kouri pwogram nan:
$ 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
Prèske tout pwosesis yo te trete sou CPU7. Sa a pa enpòtan pou nou, bagay prensipal la se ke pwogram nan travay epi nou konprann ki jan jwenn aksè nan kat nan pwogram BPF - lè l sèvi avèk хелперов bpf_mp_*.
Endèks mistik
Se konsa, nou ka jwenn aksè nan kat la nan pwogram nan BPF lè l sèvi avèk apèl tankou
$ 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
Men, si nou gade pwogram ki deja chaje a, nou wè yon konsèy sou kat ki kòrèk la (liy 4):
Kidonk, nou ka konkli ke nan moman an nan lanse pwogram loader nou an, lyen ki mennen nan &woo te ranplase pa yon bagay ki gen yon bibliyotèk libbpf. Premye nou pral gade pwodiksyon an strace:
Nou wè sa libbpf te kreye yon kat woo ak Lè sa a, telechaje pwogram nou an simple. Ann pran yon gade pi pre nan ki jan nou chaje pwogram nan:
rele xdp_simple_bpf__open_and_load soti nan dosye xdp-simple.skel.h
ki lakòz xdp_simple_bpf__load soti nan dosye xdp-simple.skel.h
ki lakòz bpf_object__load_skeleton soti nan dosye libbpf/src/libbpf.c
ki lakòz bpf_object__load_xattr nan libbpf/src/libbpf.c
Dènye fonksyon an, pami lòt bagay, pral rele bpf_object__create_maps, ki kreye oswa ouvè kat ki deja egziste, ki fè yo tounen deskriptè dosye. (Sa a se kote nou wè BPF_MAP_CREATE nan pwodiksyon an strace.) Apre yo rele fonksyon an bpf_object__relocate epi se li ki enterese nou, paske nou sonje sa nou te wè a woo nan tablo demenajman an. Eksplore li, nou finalman jwenn tèt nou nan fonksyon an bpf_program__relocate, ki fè fas ak demenajman kat jeyografik:
case RELO_LD64:
insn[0].src_reg = BPF_PSEUDO_MAP_FD;
insn[0].imm = obj->maps[relo->map_idx].fd;
break;
epi ranplase enskri sous la nan li ak BPF_PSEUDO_MAP_FD, ak premye IMM nan deskriptè fichye kat nou an epi, si li egal a, pou egzanp, 0xdeadbeef, Lè sa a, kòm yon rezilta nou pral resevwa enstriksyon an
18 11 00 00 ef eb ad de 00 00 00 00 00 00 00 00 r1 = 0 ll
Sa a se ki jan enfòmasyon kat yo transfere nan yon pwogram BPF espesifik chaje. Nan ka sa a, kat la ka kreye lè l sèvi avèk BPF_MAP_CREATE, ak louvri pa ID lè l sèvi avèk BPF_MAP_GET_FD_BY_ID.
Total, lè w ap itilize libbpf algorithm la se jan sa a:
pandan konpilasyon, dosye yo kreye nan tablo demenajman an pou lyen ki mennen nan kat yo
libbpf ouvri liv objè ELF, jwenn tout kat yo itilize epi kreye deskriptè fichye pou yo
deskriptè dosye yo chaje nan nwayo a kòm yon pati nan enstriksyon an LD64
Kòm ou ka imajine, gen plis k ap vini epi nou pral oblije gade nan nwayo a. Erezman, nou gen yon siy - nou te ekri siyifikasyon an BPF_PSEUDO_MAP_FD nan rejis sous la epi nou ka antere li, ki pral mennen nou nan sen pou tout sen yo - kernel/bpf/verifier.c, kote yon fonksyon ki gen yon non diferan ranplase yon deskriptè fichye ak adrès yon estrikti nan kalite struct bpf_map:
(Ou ka jwenn tout kòd по ссылке). Se konsa, nou ka elaji algorithm nou an:
pandan y ap chaje pwogram nan, verifikatè tcheke itilizasyon kòrèk kat la epi ekri adrès estrikti ki koresponn lan struct bpf_map
Lè w ap telechaje binè ELF la lè l sèvi avèk libbpf Gen anpil plis pase, men nou pral diskite sou sa nan lòt atik.
Chaje pwogram ak kat san libbpf
Jan yo te pwomèt la, isit la se yon egzanp pou lektè ki vle konnen ki jan yo kreye ak chaje yon pwogram ki sèvi ak kat, san èd. libbpf. Sa a ka itil lè w ap travay nan yon anviwònman kote ou pa ka bati depandans, oswa sove chak ti jan, oswa ekri yon pwogram tankou ply, ki jenere kòd binè BPF sou vole.
Pou fè li pi fasil pou swiv lojik la, nou pral reekri egzanp nou an pou rezon sa yo xdp-simple. Kòd konplè ak yon ti kras elaji nan pwogram nan diskite nan egzanp sa a ka jwenn nan sa a esansyèl.
Lojik aplikasyon nou an se jan sa a:
kreye yon kat kalite BPF_MAP_TYPE_ARRAY lè l sèvi avèk kòmandman an BPF_MAP_CREATE,
kreye yon pwogram ki sèvi ak kat sa a,
konekte pwogram nan koòdone lo,
ki tradui nan moun kòm
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);
}
Isit la map_create kreye yon kat jeyografik menm jan ak nou te fè nan premye egzanp sou apèl sistèm lan bpf - "kernel, tanpri fè m 'yon nouvo kat jeyografik nan fòm lan nan yon etalaj de 8 eleman tankou __u64 epi remèt mwen deskriptè fichye a":
Pati nan difisil prog_load se definisyon pwogram BPF nou an kòm yon seri estrikti struct bpf_insn insns[]. Men, depi nou ap itilize yon pwogram ke nou genyen nan C, nou ka tronpe yon ti kras:
An total, nou bezwen ekri 14 enstriksyon nan fòm estrikti tankou struct bpf_insn (konsèy: pran pil fatra a soti nan pi wo a, re-li seksyon an enstriksyon, louvri linux/bpf.h и linux/bpf_common.h epi eseye detèmine struct bpf_insn insns[] pou kont li):
Yon egzèsis pou moun ki pa t 'ekri sa a tèt yo - jwenn map_fd.
Gen yon lòt pati ki pa divilge ki rete nan pwogram nou an - xdp_attach. Malerezman, pwogram tankou XDP pa ka konekte lè l sèvi avèk yon apèl sistèm bpf. Moun ki te kreye BPF ak XDP yo te soti nan kominote Linux sou entènèt la, ki vle di yo te itilize youn ki pi abitye pou yo (men pa nòmal moun) koòdone pou kominike avèk nwayo a: priz netlink, Gade tou RFC3549. Fason ki pi senp pou aplike xdp_attach ap kopye kòd nan libbpf, sètadi, soti nan dosye a netlink.c, ki se sa nou te fè, diminye li yon ti kras:
Byenveni nan mond lan nan sipò netlink
Louvri yon kalite priz netlink 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;
}
Nou li nan priz sa a:
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;
}
Finalman, isit la se fonksyon nou an ki louvri yon priz epi voye yon mesaj espesyal ba li ki gen yon deskriptè dosye:
$ 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
Hurray, tout bagay ap mache. Remake byen ke kat jeyografik nou an parèt ankò nan fòm bytes. Sa a se akòz lefèt ke, kontrèman ak libbpf nou pa t chaje enfòmasyon tip (BTF). Men, nou pral pale plis sou sa a pwochen fwa.
Zouti Devlopman
Nan seksyon sa a, nou pral gade twous zouti pou pwomotè BPF minimòm lan.
An jeneral, ou pa bezwen anyen espesyal pou devlope pwogram BPF - BPF kouri sou nenpòt nwayo distribisyon desan, epi pwogram yo bati lè l sèvi avèk clang, ki ka apwovizyone nan pake a. Sepandan, akòz lefèt ke BPF se sou devlopman, nwayo a ak zouti yo toujou ap chanje, si ou pa vle ekri pwogram BPF lè l sèvi avèk metòd ansyen alamòd soti nan 2019, Lè sa a, ou pral gen konpile.
llvm/clang
pahole
nwayo li yo
bpftool
(Pou referans, seksyon sa a ak tout egzanp nan atik la te kouri sou Debian 10.)
llvm/clang
BPF se zanmitay ak LLVM epi, byenke dènyèman pwogram pou BPF ka konpile lè l sèvi avèk gcc, tout devlopman aktyèl fèt pou LLVM. Se poutèt sa, anvan tout bagay, nou pral bati vèsyon aktyèl la clang soti nan 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
... много времени спустя
$
Koulye a, nou ka tcheke si tout bagay te ansanm kòrèkteman:
(Enstriksyon asanble clang pran pa mwen nan bpf_devel_QA.)
Nou p ap enstale pwogram nou fèk konstwi yo, men pito jis ajoute yo PATHpa egzanp:
export PATH="`pwd`/bin:$PATH"
(Sa a ka ajoute nan .bashrc oswa nan yon dosye separe. Pèsonèlman, mwen ajoute bagay sa yo nan ~/bin/activate-llvm.sh epi lè sa nesesè mwen fè li . activate-llvm.sh.)
Pahole ak BTF
Sèvis piblik pahole itilize lè bati nwayo a pou kreye enfòmasyon debogaj nan fòma BTF. Nou pa pral antre nan detay nan atik sa a sou detay yo nan teknoloji BTF, lòt pase lefèt ke li se pratik epi nou vle sèvi ak li. Se konsa, si ou pral bati nwayo ou a, bati premye pahole (san yo pa pahole ou pa pral kapab bati nwayo a ak opsyon an 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 pou fè eksperyans ak BPF
Lè m ap eksplore posiblite BPF yo, mwen vle rasanble nwayo pwòp mwen an. Sa a, jeneralman pale, pa nesesè, paske ou pral kapab konpile ak chaje pwogram BPF sou nwayo distribisyon an, sepandan, gen pwòp nwayo ou a pèmèt ou sèvi ak dènye karakteristik BPF yo, ki pral parèt nan distribisyon ou nan mwa nan pi bon. , oswa, tankou nan ka a nan kèk zouti debogaj pa pral pake nan tout nan fiti prévisible. Epitou, nwayo pwòp li yo fè li santi li enpòtan pou fè eksperyans ak kòd la.
Yo nan lòd yo bati yon nwayo ou bezwen, premyèman, nwayo a li menm, ak dezyèmman, yon dosye konfigirasyon nwayo. Pou fè eksperyans ak BPF nou ka itilize nòmal la vaniy nwayo oswa youn nan nwayo devlopman yo. Istorikman, devlopman BPF pran plas nan kominote a rezo Linux ak Se poutèt sa, tout chanjman pi bonè oswa pita ale nan David Miller, mentenan rezo Linux la. Tou depan de nati yo - modifye oswa nouvo karakteristik - chanjman rezo tonbe nan youn nan de nwayo - net oswa net-next. Chanjman pou BPF yo distribye nan menm fason an ant bpf и bpf-next, ki Lè sa a, pisin nan net ak net-next, respektivman. Pou plis detay, gade bpf_devel_QA и netdev-FAQ. Se konsa, chwazi yon nwayo ki baze sou gou ou ak bezwen estabilite nan sistèm w ap teste sou la (*-next nwayo yo se pi enstab nan sa yo ki nan lis la).
Li pi lwen pase sijè ki abòde lan atik sa a pou pale sou ki jan yo jere fichye konfigirasyon nwayo - li sipoze ke ou swa deja konnen ki jan fè sa, oswa pare pou aprann pou kont li. Sepandan, enstriksyon sa yo ta dwe plis oswa mwens ase pou ba ou yon sistèm travay BPF ki pèmèt.
Telechaje youn nan nwayo ki anwo yo:
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git
$ cd bpf-next
Bati yon konfigirasyon minim k ap travay:
$ cp /boot/config-`uname -r` .config
$ make localmodconfig
Pèmèt opsyon BPF nan dosye a .config nan pwòp chwa ou (gen plis chans CONFIG_BPF pral deja aktive depi systemd sèvi ak li). Men yon lis opsyon ki soti nan nwayo yo itilize pou atik sa a:
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
Lè sa a, nou ka fasilman rasanble ak enstale modil yo ak nwayo a (nan chemen an, ou ka rasanble nwayo a lè l sèvi avèk nouvo rasanbleman an. clangpa ajoute CC=clang):
$ make -s -j $(getconf _NPROCESSORS_ONLN)
$ sudo make modules_install
$ sudo make install
ak rdemare ak nouvo nwayo a (mwen itilize pou sa a kexec soti nan pake a 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
Sèvis piblik ki pi souvan itilize nan atik la pral sèvis piblik la bpftool, apwovizyone kòm yon pati nan nwayo Linux la. Devlopè BPF ekri epi kenbe l pou devlopè BPF epi yo ka itilize pou jere tout kalite objè BPF - chaje pwogram, kreye ak edite kat, eksplore lavi ekosistèm BPF, elatriye. Ou ka jwenn dokimantasyon nan fòm kòd sous pou paj man nan nwayo a oswa, deja konpile, sou nèt la.
Nan moman sa a ekri bpftool vini pare-fè sèlman pou RHEL, Fedora ak Ubuntu (gade, pou egzanp, fil sa a, ki rakonte istwa a fini nan anbalaj bpftool nan Debian). Men, si ou te deja bati nwayo ou a, Lè sa a, bati bpftool fasil tankou tat:
$ 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 ]
$
(Isit la ${linux} - sa a se anyè nwayo ou a.) Apre egzekite kòmandman sa yo bpftool yo pral kolekte nan yon anyè ${linux}/tools/bpf/bpftool epi li ka ajoute nan chemen an (premye nan itilizatè a root) oswa jis kopye nan /usr/local/sbin.
Kolekte bpftool li pi bon yo sèvi ak lèt la clang, reyini jan sa dekri pi wo a, epi tcheke si li reyini kòrèkteman - lè l sèvi avèk, pou egzanp, lòd la
$ 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
...
ki pral montre ki karakteristik BPF yo aktive nan nwayo ou a.
By wout la, lòd anvan an ka kouri kòm
# bpftool f p k
Sa a se fè pa analoji ak sèvis piblik ki soti nan pake a iproute2, kote nou ka, pou egzanp, di ip a s eth0 olye pou yo ip addr show dev eth0.
Konklizyon
BPF pèmèt ou soulye yon pis efektivman mezire ak sou-a-vole chanje fonksyonalite a nan nwayo a. Sistèm nan te vin gen anpil siksè, nan pi bon tradisyon yo nan UNIX: yon mekanis senp ki pèmèt ou (re)pwogram nwayo a pèmèt yon gwo kantite moun ak òganizasyon fè eksperyans. Epi, byenke eksperyans yo, osi byen ke devlopman nan enfrastrikti BPF nan tèt li, yo byen lwen soti nan fini, sistèm nan deja gen yon ABI ki estab ki pèmèt ou bati serye, ak pi enpòtan, lojik biznis efikas.
Mwen ta renmen remake ke, nan opinyon mwen, teknoloji a te vin tèlman popilè paske, sou yon bò, li kapab jwe (ka achitekti a nan yon machin dwe konprann plis oswa mwens nan yon aswè), ak nan lòt men an, yo rezoud pwoblèm ki pa t 'kapab rezoud (bèl) anvan aparans li. De eleman sa yo ansanm fòse moun yo fè eksperyans ak rèv, ki mennen nan Aparisyon nan pi plis ak plis solisyon inovatè.
Atik sa a, byenke pa patikilyèman kout, se sèlman yon entwodiksyon nan mond lan nan BPF epi li pa dekri karakteristik "avanse" ak pati enpòtan nan achitekti a. Plan pou pi devan se yon bagay tankou sa a: pwochen atik la pral yon apèsi sou kalite pwogram BPF (gen 5.8 kalite pwogram sipòte nan nwayo 30 la), Lè sa a, nou pral finalman gade nan ki jan yo ekri aplikasyon BPF reyèl lè l sèvi avèk pwogram trase nwayo. kòm yon egzanp, Lè sa a, li lè pou yon kou plis pwofondè sou achitekti BPF, ki te swiv pa egzanp sou rezo BPF ak aplikasyon pou sekirite.
Gid referans BPF ak XDP — dokiman sou BPF soti nan Cilium, oswa plis jisteman soti nan Daniel Borkman, youn nan kreyatè yo ak moun ki kenbe BPF. Sa a se youn nan premye deskripsyon serye yo, ki diferan de lòt yo nan ke Danyèl konnen egzakteman ki sa l ap ekri sou epi pa gen okenn erè la. An patikilye, dokiman sa a dekri kijan pou travay ak pwogram BPF nan kalite XDP ak TC lè l sèvi avèk sèvis piblik byen li te ye. ip soti nan pake a iproute2.
Dokimantasyon/rezo/filter.txt — fichye orijinal ak dokimantasyon pou BPF klasik ak Lè sa a, pwolonje. Yon bon lekti si ou vle fouye nan lang asanble ak detay teknik achitekti.
Blog sou BPF soti nan facebook. Li se mete ajou raman, men byen, kòm Alexei Starovoitov (otè eBPF) ak Andrii Nakryiko - (mentè) ekri la. libbpf).
Sekrè bpftool. Yon fil twitter amizan soti nan Quentin Monnet ak egzanp ak sekrè nan lè l sèvi avèk bpftool.