ProHoster > Блог > Maamulka > BPF ee kuwa yaryar, qaybta koowaad: BPF oo la dheereeyey
BPF ee kuwa yaryar, qaybta koowaad: BPF oo la dheereeyey
Bilowgii waxaa jiray tignoolajiyada waxaana la odhan jiray BPF. Waanu eegnay iyada hore, Maqaalka Axdiga Hore ee taxanahan. 2013, iyada oo loo marayo dadaalka Alexei Starovoitov iyo Daniel Borkman, version la hagaajiyay, oo loogu talagalay mashiinnada casriga ah ee 64-bit, ayaa la sameeyay oo lagu daray kernel Linux. Tignoolajiyadan cusub ayaa si kooban loogu magacaabay BPF gudaha, ka dibna loo beddelay BPF Extended, oo hadda, dhowr sano ka dib, qof kastaa wuxuu si fudud ugu yeeraa BPF.
Ku dhawaad hadalka, BPF wuxuu kuu oggolaanayaa inaad ku socodsiiso koodka isticmaale-bixiye-ku-sheegga ah ee booska Linux, iyo qaab dhismeedka cusub wuxuu noqday mid aad u guulaystay oo aan u baahan doono daraasiin maqaallo dheeraad ah si aan u qeexno dhammaan codsiyadiisa. (Waxa kaliya ee horumariyayaashu aysan si fiican u qaban, sida aad ku arki karto xeerka waxqabadka ee hoose, waxay abuureen calaamad wanaagsan.)
Maqaalkani waxa uu qeexayaa qaab-dhismeedka mashiinka farsamada ee BPF, isdhexgalka kernel ee la shaqeynta BPF, qalabka horumarinta, iyo sidoo kale dulmar kooban, aad u kooban oo ku saabsan awoodaha jira, i.e. Wax kasta oo aan u baahan doono mustaqbalka si aan u baarno qoto dheer ee codsiyada la taaban karo ee BPF.
Maareynta walxaha iyadoo la isticmaalayo nidaamka bpf call. Iyada oo la fahmi karo nidaamka horeba u jiray, waxaanu ugu dambeyntii eegi doonaa sida loo abuuro oo looga maareeyo walxaha meel bannaan oo adeegsadaha annagoo adeegsanayna nidaam gaar ah oo wac - bpf(2).
Пишем программы BPF с помощью libbpf. Dabcan, waxaad ku qori kartaa barnaamijyada adigoo isticmaalaya nidaamka wicitaanka. Laakiin way adagtahay. Si loo helo xaalad waaqici ah, barnaamijyada nukliyeerka ayaa sameeyay maktabad libbpf. Waxaan abuuri doonaa qalfoofka codsiga BPF ee aasaasiga ah kaas oo aan u isticmaali doono tusaalooyinka xiga.
Caawinta Kernel. Halkan waxaan ku baran doonaa sida barnaamijyada BPF ay u heli karaan hawlaha caawiye kernel - qalab kaas oo ay weheliyaan khariidado, aasaas ahaan balaadhinaya awoodaha BPF cusub marka loo eego kan caadiga ah.
Helitaanka maabyada barnaamijyada BPF. Halkaa marka ay marayso, waxaan ogaan doonaa in ku filan si aan u fahanno sida saxda ah ee aan u abuuri karno barnaamijyo isticmaalaya maab. Oo aan xitaa si degdeg ah u eegno xaqiijiyaha weyn ee xoogga leh.
Qalabka horumarinta. Qaybta caawinta ee ku saabsan sida loo ururiyo tamarta loo baahan yahay iyo kernel ee tijaabooyinka.
Gabagabada. Gabagabada maqaalka, dadka ilaa hadda akhriya waxay ka heli doonaan ereyo dhiirigelin ah iyo sharraxaad kooban oo ku saabsan waxa dhici doona maqaallada soo socda. Waxaan sidoo kale liis gareyn doonaa dhowr xiriiriye oo loogu talagalay is-barashada kuwa aan haysan rabitaan ama awood ay ku sugaan sii wadida.
Hordhac Dhismaha BPF
Kahor intaanan bilaabin inaan tixgelinno qaab-dhismeedka BPF, waxaan tixraaci doonaa markii ugu dambeysay (oh) caadiga ah BPF, kaas oo loo sameeyay sidii looga jawaabi lahaa imaatinka mashiinnada RISC oo xalliyey dhibaatada shaandhaynta baakadaha hufan. Nashqadani waxa ay noqotay mid aad loogu guulaystay oo markii uu ku dhashay sagaashamaadkii ee Berkeley UNIX, waxa la geeyay inta badan nidaamyada hawlgalka ee jira, waxa ay ka badbaaday labaatankii waalan oo wali waxa ay helaysaa codsiyo cusub.
BPF-da cusub waxaa loo sameeyay iyadoo looga jawaabayo joogitaanka mashiinnada 64-bit, adeegyada daruuraha iyo baahida kordhaysa ee aaladaha abuurista SDN (Sqalab-dcadeeyay neworking). Waxaa soo saaray injineerada shabakada kernel si ay u noqdaan beddelka BPF-ga caadiga ah, BPF cusub macno ahaan lix bilood ka dib waxay heleen codsiyo ku jira hawsha adag ee raadinta nidaamyada Linux, iyo hadda, lix sano ka dib muuqaalkeeda, waxaan u baahan doonaa maqaal dhan oo soo socda kaliya qor noocyada kala duwan ee barnaamijyada.
Sawiro qosol badan
Asal ahaan, BPF waa mashiinka farsamada gacanta kaas oo kuu ogolaanaya inaad ku socodsiiso koodka "aan macnayn" meel kernel ah adigoon wax u dhimayn amniga. Barnaamijyada BPF waxaa lagu abuuray booska isticmaalaha, waxaa lagu shubaa kernel-ka, waxaana lagu xiraa ilaha dhacdada qaarkood. Dhacdo waxay noqon kartaa, tusaale ahaan, gaarsiinta baakidh is-dhexgal shabakadeed, bilaabida hawl kernel qaarkeed, iwm. Xaaladda xirmo, barnaamijka BPF wuxuu heli doonaa xogta iyo xogta badan ee xirmada (akhrinta iyo, suurtogalnimada, qorista, iyadoo ku xiran nooca barnaamijka); Xaaladda socodsiinta shaqada kernel, doodaha shaqada, oo ay ku jiraan tilmaamayaasha xusuusta kernel, iwm.
Aynu si qoto dheer u eegno habkan. Si aan u bilowno, aan ka hadalno farqiga ugu horreeya ee BPF-ga caadiga ah, barnaamijyada kuwaas oo lagu qoray isu-ururinta. Nooca cusub, qaab dhismeedka ayaa la balaariyay si barnaamijyada lagu qoro luqado heer sare ah, ugu horrayn, dabcan, C. Taas awgeed, dhabarka dambe ee llvm ayaa la sameeyay, kaas oo kuu ogolaanaya inaad soo saarto bytecode ee naqshadaha BPF.
Nashqada BPF waxaa loo nashqadeeyay, qayb ahaan, si ay si hufan ugu shaqeeyaan mishiinada casriga ah. Si tan looga dhigo ficil ahaan, BPF bytecode, mar lagu shubo kernel-ka, ayaa loo turjumay koodka asalka ah iyadoo la adeegsanayo qayb la yiraahdo kombuyuutar JIT (Just In Time). Marka xigta, haddii aad xasuusato, BPF-ga caadiga ah barnaamijka waxaa lagu shubay kernel-ka waxaana lagu lifaaqay isha dhacdada atomically - marka la eego hal wicitaan oo nidaam ah. Dhismaha cusub, tani waxay ku dhacdaa laba marxaladood - marka hore, koodhka ayaa lagu shubaa kernel-ka iyadoo la adeegsanayo wicitaanka nidaamka bpf(2)ka dibna, ka dib, iyada oo loo marayo habab kale oo kala duwan oo ku xiran nooca barnaamijka, barnaamijku wuxuu ku xiran yahay isha dhacdada.
Halkan waxaa laga yaabaa in akhristuhu uu su'aal ku weydiiyo: suurtagal ma ahayd? Sidee loo dammaanad qaaday badbaadada fulinta xeerkan? Badbaadada fulinta waxaa noo dammaanad qaadaya heerka rarida barnaamijyada BPF ee loo yaqaan verifier (Ingiriisiga marxaladan waxaa loo yaqaan verifier waxaanan sii wadi doonaa isticmaalka ereyga Ingiriisiga):
Xaqiijiye waa falanqeeye taagan oo hubiya in barnaamijku aanu carqaladayn shaqada caadiga ah ee kernel-ka. Tani, habka, macnaheedu maaha in barnaamijku aanu faragelin karin hawlgalka nidaamka - Barnaamijyada BPF, iyadoo ku xiran nooca, waxay akhrin karaan oo dib u qori karaan qaybaha xusuusta kernel, soo celinta qiyamka hawlaha, jar, dheji, dib u qori iyo xitaa baakadaha shabakada u sii gudbi. Xaqiijiye wuxuu dammaanad qaadayaa in socodsiinta barnaamijka BPF uusan burburi doonin kernel-ka iyo in barnaamijka, sida sharcigu qabo, uu leeyahay gelitaan qoris, tusaale ahaan, xogta xirmo baxaysa, ma awoodi doono inuu ku beddelo xusuusta kernel-ka ka baxsan xirmada. Waxaan si faahfaahsan u eegi doonaa xaqiijiyaha qaybta u dhiganta, ka dib marka aan barano dhammaan qaybaha kale ee BPF.
Haddaba maxaan ka baranay ilaa hadda? Isticmaaluhu wuxuu ku qoraa barnaamijka C, wuxuu ku shubayaa kernel-ka isagoo isticmaalaya nidaamka wicida bpf(2), halkaasoo uu hubiyay hubiyaha oo loo turjumay bytecode hooyo. Kadib isticmaale isku mid ah ama mid kale ayaa ku xiraya barnaamijka isha dhacdada wuxuuna bilaabayaa inuu fuliyo. Kala saarida kabaha iyo isku xirka ayaa lagama maarmaan u ah dhowr sababood. Marka hore, socodsiinta hubinta waa mid aad qaali u ah marka la soo dejiyo isla barnaamijka dhowr jeer waxaan luminaa waqtiga kombayutarka. Marka labaad, sida saxda ah ee barnaamijku isugu xidhan yahay waxay ku xidhan tahay nooca uu yahay, iyo hal “universal” interface oo la sameeyay sannad ka hor waxa laga yaabaa inaanay ku habboonayn noocyada cusub ee barnaamijyada. (Inkasta oo hadda qaab-dhismeedku uu noqonayo mid qaan-gaar ah, waxaa jira fikrad lagu mideynayo interface-ka heerka libbpf.)
Akhristaha fiiro gaar ah ayaa laga yaabaa inuu ogaado inaanan weli dhammayn sawirada. Runtii, dhammaan kuwan kor ku xusan ma sharraxayaan sababta BPF ay u beddesho sawirka marka la barbar dhigo BPF-ga caadiga ah. Laba hal-abuurnimo oo si weyn u balaadhinaya baaxadda ku habboonaanta ayaa ah awoodda isticmaalka xusuusta la wadaago iyo hawlaha caawiyaha kernel-ka. Gudaha BPF, xusuusta la wadaago waxaa lagu fuliyaa iyadoo la adeegsanayo waxa loogu yeero khariidado - qaabdhismeedka xogta la wadaago oo leh API gaar ah. Waxay u badan tahay inay heleen magacan sababtoo ah nooca ugu horreeya ee khariidad ee soo muuqda wuxuu ahaa miiska xashiishka. Kadibna waxaa soo baxay arraysyo, miisaska xashiishka ee maxalli ah (per-CPU) iyo arrays maxalli ah, geedo raadin, maab ay ku jiraan tilmaamayaasha barnaamijyada BPF iyo wax ka badan. Waxa hadda xiiso noo leh ayaa ah in barnaamijyada BPF ay hadda awood u leeyihiin in ay sii wadaan xaaladda inta u dhaxaysa wicitaannada oo ay la wadaagaan barnaamijyada kale iyo booska isticmaalaha.
Khariidadaha waxaa laga galaa hababka isticmaalaha iyadoo la isticmaalayo nidaamka wicitaanka bpf(2), iyo barnaamijyada BPF ee ku dhex jira kernel-ka iyadoo la isticmaalayo hawlaha caawiyaha. Intaa waxaa dheer, caawiyayaasha ma jiraan oo kaliya inay ku shaqeeyaan maab, laakiin sidoo kale si ay u helaan awoodaha kale ee kernel. Tusaale ahaan, barnaamijyada BPF waxay isticmaali karaan hawlaha caawiye si ay ugu gudbiyaan baakadaha is-dhexgalka kale, abuuraan dhacdooyinka perf, helitaanka qaababka kernel, iyo wixii la mid ah.
Marka la soo koobo, BPF waxa ay bixisa awoodda ay ku shuban karto sabab la'aan, tusaale ahaan, xaqiijiye-la tijaabiyay, koodka isticmaale ee booska kernel-ka. Koodhkani waxa uu kaydin karaa xaalada u dhaxaysa wicitaanada iyo xogta isdhaafsiga booska isticmaalaha, sidoo kale waxa uu marin u leeyahay nidaamka hoosaadka kernel-ka ee uu ogolyahay barnaamijka noocan ah.
Tani waxay mar hore la mid tahay awoodaha ay bixiyaan modules kernel, marka la barbardhigo BPF waxay leedahay faa'iidooyin qaar (dabcan, waxaad kaliya barbar dhigi kartaa codsiyada la midka ah, tusaale ahaan, nidaamka raadinta - ma qori kartid darawal aan sabab lahayn oo leh BPF). Waxaad ogaan kartaa heerka gelitaanka hoose (qaar ka mid ah yutiilitida adeegsata BPF uma baahna adeegsadaha inuu yeesho xirfadaha barnaamijka kernel, ama xirfadaha barnaamijka guud ahaan), badqabka runtime (gacanta u taag faallooyinka kuwa aan jebin nidaamka marka wax la qorayo ama modules tijaabinta), atomicity - waxaa jira waqti hoos u dhac marka dib loo soo dajiyo modules, iyo nidaamka hoose ee BPF hubisaa in aan dhacdooyinka la seegay (si cadaalad ah, tani run maaha dhammaan noocyada barnaamijyada BPF).
Joogitaanka awoodaha noocan oo kale ah waxay ka dhigaysaa BPF qalab caalami ah oo loogu talagalay ballaarinta kernel-ka, taas oo lagu xaqiijiyay ficil ahaan: noocyo badan oo cusub oo barnaamijyo ah ayaa lagu daraa BPF, shirkado badan oo waaweyn ayaa isticmaala BPF ee server-yada dagaalka 24 × 7, in ka badan iyo in ka badan. bilaabayaashu waxay ganacsigooda ku dhistaan xalal ku salaysan BPF. BPF waxaa loo isticmaalaa meel kasta: ka ilaalinta weerarrada DDoS, abuurista SDN (tusaale ahaan, hirgelinta shabakadaha kubernetes), sida qalabka ugu muhiimsan ee nidaamka raadinta iyo ururiyaha tirakoobka, hababka ogaanshaha soo gelitaanka iyo nidaamyada sanduuqyada, iwm.
Aynu halkan ku dhamayno dulmarka qaybta maqaalka oo aynu si faahfaahsan u eegno mishiinka farsamada iyo nidaamka deegaanka BPF.
Digression: utilities
Si aad awood ugu yeelatid inaad ku socodsiiso tusaalooyinka qaybaha soo socda, waxaa laga yaabaa inaad u baahato tiro agab ah, ugu yaraan. llvm/clang oo leh taageero bpf iyo bpftool. Qeybta Qalabka Horumarinta Waxaad akhrin kartaa tilmaamaha loogu talagalay isu-ururinta yutiilitida, iyo sidoo kale kernel-kaaga. Qaybtan hoos ayaa la dhigayaa si aanay u carqaladayn is-waafajinta soo jeedinteena.
Nidaamyada Diiwaangelinta Mashiinka Farshaxanka ee BPF iyo Tilmaamaha
Qaab dhismeedka iyo nidaamka taliska ee BPF ayaa la sameeyay iyada oo la tixgelinayo in barnaamijyada lagu qori doono luqadda C iyo, ka dib markii la geliyo kernel-ka, loo turjumay koodka hooyo. Sidaa darteed, tirada diiwaanka iyo amarrada amarrada ayaa lagu doortay iyadoo isha lagu hayo isgoyska, macnaha xisaabta, awoodda mashiinnada casriga ah. Intaa waxaa dheer, xannibaadyo kala duwan ayaa lagu soo rogay barnaamijyada, tusaale ahaan, ilaa dhowaan ma suurtagalin in la qoro wareegyada iyo subroutines, tirada tilmaamuhuna waxay ku koobnaayeen 4096 (hadda barnaamijyada mudnaanta leh waxay ku shuban karaan ilaa hal milyan oo tilmaamo ah).
BPF waxay leedahay kow iyo toban isticmaale-heli kara diiwaan 64-bit ah r0-r10 iyo miiska barnaamijka. Is diwaangeli r10 ka kooban yahay tilmaame jir waana akhrin-kaliya. Barnaamijyadu waxay marin u helayaan xidhmooyin 512-byte ah wakhtiga runtime-ka iyo qadar aan xadidnayn oo xusuusta la wadaago oo qaab khariidado ah.
Barnaamijyada BPF waxaa loo oggol yahay inay socodsiiyaan qayb gaar ah oo ah caawiyayaasha kernel-ka nooca barnaamijka ah iyo, dhawaanahan, hawlo joogto ah. Hawl kasta oo loo yaqaan waxay qaadan kartaa ilaa shan doodood, oo lagu gudbiyo diiwaannada r1-r5, qiimaha soo laabashadana waa loo gudbiyaa r0. Waxaa la dammaanad qaaday in ka dib marka laga soo laabto shaqada, waxa ku jira diiwaanka r6-r9 Ma beddeli doono.
Si loo helo turjumaada barnaamijka hufan, diiwaan gelinta r0-r11 Dhammaan dhismayaasha la taageeray waxaa si gaar ah loogu habeeyey diiwaannada dhabta ah, iyadoo la tixgelinayo sifooyinka ABI ee dhismaha hadda jira. Tusaale ahaan, loogu talagalay x86_64 diiwaan gelinta r1-r5, loo isticmaalo in lagu gudbiyo xuduudaha shaqada, ayaa lagu soo bandhigay rdi, rsi, rdx, rcx, r8, kuwaas oo loo isticmaalo in lagu gudbiyo qiyaasaha si ay u shaqeeyaan x86_64. Tusaale ahaan, koodka bidix wuxuu u turjumayaa koodka dhanka midig sida tan:
Is diwaangeli r0 sidoo kale loo isticmaalo in lagu soo celiyo natiijada fulinta barnaamijka, iyo in diiwaanka r1 barnaamijka waxaa loo gudbiyaa tilmaame macnaha guud - iyadoo ku xiran nooca barnaamijka, tani waxay noqon kartaa, tusaale ahaan, qaab dhismeed struct xdp_md (XDP) ama qaab-dhismeedka struct __sk_buff (Barnaamijyada shabakadaha kala duwan) ama qaab-dhismeedka struct pt_regs (oo loogu talagalay noocyada kala duwan ee barnaamijyada raadinta), iwm.
Markaa, waxaanu haysanay tiro diiwaan-galin ah, caawiyayaasha kernel-ka, xidhmooyin, tilmaame guud iyo xusuusta la wadaago oo qaab khariidado ah. Ma aha in waxaas oo dhami ay lagama maarmaan u yihiin safarka, laakiin ...
Aynu sii wadno sharraxaadda oo aynu ka hadalno nidaamka taliska ee ku shaqeeya walxahan. Dhammaan (Ku dhawaad dhammaanTilmaamaha BPF waxay leeyihiin cabbir go'an oo 64-bit ah. Haddii aad eegto hal tilmaamo mashiinka 64-bit Big Endian waad arki doontaa
waa Code - kani waa codaynta tilmaamaha, Dst/Src waa cod-bixinaha soo-dhoweeyaha iyo isha, siday u kala horreeyaan, Off - 16-bit soo gelid saxeexan, iyo Imm waa 32-bit isteeger saxeexan oo loo isticmaalo tilmaamaha qaar (oo la mid ah cBPF joogta ah K). Codaynta Code wuxuu leeyahay laba nooc midkood:
Casharrada 0, 1, 2, 3 waxay qeexaan amarrada lagu shaqeynayo xusuusta. Iyaga ayaa loo yaqaan, BPF_LD, BPF_LDX, BPF_ST, BPF_STX, siday u kala horreeyaan. Fasalada 4, 7 (BPF_ALU, BPF_ALU64) oo ka kooban tilmaamo ALU ah. Fasalada 5, 6 (BPF_JMP, BPF_JMP32) ka kooban tilmaanta boodada.
Qorshaha mustaqbalka ee lagu baranayo habka wax-barid ee BPF waa sida soo socota: Halkii si taxadar leh loo qori lahaa dhammaan tilmaamaha iyo cabbiradooda, waxaan eegi doonaa dhowr tusaale oo qaybtan ah waxaana iyaga ka muuqan doona sida habraaca dhab ahaantii u shaqeeyaan iyo sida loo sameeyo. gacanta u kala qaad fayl kasta oo laba-jibaaran ah oo loogu talagalay BPF. Si loo xoojiyo maaddada dambe ee maqaalka, waxaan sidoo kale la kulmi doonaa tilmaamo gaar ah oo ku saabsan qaybaha ku saabsan Verifier, compiler JIT, tarjumaadda BPF-ga caadiga ah, iyo sidoo kale marka la baranayo khariidadaha, wicitaanka hawlaha, iwm.
Bal aynu eegno tusaale aynu barnaamij ku ururinayno readelf-example.c oo eeg binary-ga ka dhashay. Waxaan daaha ka qaadi doonaa nuxurka asalka ah readelf-example.c hoose, ka dib markii aan ka soo celinay caqligooda codes binary:
Xeerarka amarku waa siman yihiin b7, 15, b7 и 95. Xusuusnow in saddexda qaybood ee ugu yar ay yihiin fasalka waxbarida. Xaaladeena, qaybta afraad ee dhammaan tilmaamuhu way madhan yihiin, markaa fasallada waxbarashadu waa 7, 5, 7, 5, siday u kala horreeyaan. BPF_ALU64iyo 5 waa BPF_JMP. Labada fasalba, qaabka wax-barashadu waa isku mid (eeg xagga sare) waxaana dib u qori karnaa barnaamijkeena sidan oo kale (isla markaasna waxaan dib u qori doonaa tiirarka soo haray ee qaabka aadanaha):
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
Hawlgalka b fasalka ALU64 Waa BPF_MOV. Waxay qiimeeyaa diiwaanka goobta. Haddii xoogaa la dhigo s (source), ka dibna qiimaha ayaa laga soo qaatay diiwaanka isha, iyo haddii, sida kiiskeena, aan la dejin, ka dibna qiimaha ayaa laga soo qaaday goobta. Imm. Markaa tilmaamaha koowaad iyo saddexaad waxaanu samaynaa qaliinka r0 = Imm. Intaa waxaa dheer, hawlgalka JMP fasalka 1 waa BPF_JEQ (bood hadday siman yihiin). Xaaladeena, tan iyo xoogaa S waa eber, waxay barbar dhigaysaa qiimaha diiwaanka isha iyo goobta Imm. Haddii qiyamku isku mid yihiin, markaa kala-guurka ayaa dhacaya PC + Offhalkaas oo PC, sida caadiga ah, ka kooban ciwaanka tilmaamaha soo socda. Ugu dambeyntii, JMP Class 9 Hawlgalku waa BPF_EXIT. Tilmaantaani waxay joojinaysaa barnaamijka, kuna soo laabanaysa kernel-ka r0. Aan ku darno tiir cusub miiskayaga:
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
Waxaan tan dib ugu qori karnaa qaab ka habboon:
r0 = 1
if (r1 == 0) goto END
r0 = 2
END:
exit
Haddii aan xasuusano waxa ku jira diiwaanka r1 barnaamijka waxaa loo gudbiyaa tilmaame macnaha guud laga soo bilaabo kernel, iyo diiwaanka r0 qiimihiisu waxa lagu soo celiyaa kernel-ka, markaas waxaan arki karnaa in haddii tilmaanta macnaha guud ay eber tahay, markaas waxaan ku celineynaa 1, haddii kale - 2. Aan hubinno inaan saxan nahay annaga oo eegayna isha:
Haa, waa barnaamij aan macno lahayn, laakiin waxa uu u turjumayaa afar tilmaamood oo fudud.
Tusaale ka baxsan: 16-byte tilmaamaha
Waxaan horay u soo sheegnay in tilmaamaha qaarkood ay qaataan in ka badan 64 bits. Tani waxay khusaysaa, tusaale ahaan, tilmaamaha lddw (Cod = 0x18 = BPF_LD | BPF_DW | BPF_IMM) - kelmad laba jibaaran ka soo rog goobaha diiwaanka Imm. Xaqiiqdu waxay tahay Imm cabbirkiisu waa 32, erey labanlaabana waa 64-bits, markaa ku shubida 64-bit qiimaha degdega ah ee diiwaanka hal 64-bit waxbarid ma shaqayn doonto. Si tan loo sameeyo, laba tilmaamood oo isku xiga ayaa loo isticmaalaa in lagu kaydiyo qaybta labaad ee qiimaha 64-bit ee goobta Imm. Tusaale:
Waxaan mar kale la kulmi doonaa tilmaamo lddw, marka aan ka hadalno raritaan iyo ku shaqaynta maab.
Tusaale: kala dirida BPF iyadoo la isticmaalayo qalabka caadiga ah
Marka, waxaan baranay inaan akhrino koodka binary code ee BPF waxaanan diyaar u nahay inaan kala saarno tilmaam kasta haddii loo baahdo. Si kastaba ha ahaatee, waxaa habboon in la sheego in ficil ahaan ay ku habboon tahay oo dhaqso badan tahay in la kala saaro barnaamijyada iyadoo la adeegsanayo qalabka caadiga ah, tusaale ahaan:
Meertada nololeed ee walxaha BPF, nidaamka faylka bpffs
(Waxaan markii hore ka bartay qaar ka mid ah faahfaahinta lagu qeexay qaybtan hoose boostada Alexei Starovoitov BPF Blog.)
Walxaha BPF-barnaamijyada iyo khariidadaha-waxaa laga sameeyay meel bannaan oo adeegsadaha ah iyadoo la isticmaalayo amarro BPF_PROG_LOAD и BPF_MAP_CREATE nidaamka call bpf(2), waxaan uga hadli doonaa sida saxda ah ee tani u dhacdo qaybta xigta. Tani waxay abuurtaa qaababka xogta kernel iyo mid kasta oo iyaga ka mid ah refcount (Tirinta tixraaca) ayaa loo dejiyay mid, iyo sharraxaha faylka tilmaamaya shayga ayaa lagu soo celinayaa isticmaalaha. Ka dib marka gacanta la xiro refcount walaxda hal baa lagu dhimayaa, marka uu eber gaadho, shaygu waa baabba'aa.
Haddii barnaamijku isticmaalo maab, markaa refcount Khariidadahaan waxaa lagu kordhiyaa hal mar kadib marka la shubo barnaamijka, i.e. Sharaxayaashooda faylka waa laga xiri karaa nidaamka isticmaalaha iyo weli refcount ma noqon doonto eber:
Ka dib marka si guul leh loo soo dejiyo barnaamijka, waxaan inta badan ku dhejinnaa nooc ka mid ah dhacdooyinka dhaliyaha. Tusaale ahaan, waxaan ku dhejin karnaa isku xirka shabakada si aan uga baaraandegno xirmooyinka soo socda ama aan ugu xirno qaar tracepoint xudunta u ah. Halkaa marka ay marayso, miiska tixraaca ayaa sidoo kale kor u qaadi doona mid waxaanan awood u yeelan doonaa in aan xidhno sharraxaadda faylka ee barnaamijka xamuulka.
Maxaa dhacaya haddii aan hadda xirno bootloader-ka? Waxay kuxirantahay nooca dhaliyaha dhacdada (hook). Dhammaan xirmooyinka shabakadu waxay jiri doonaan ka dib marka la dhammeeyo rarka, kuwani waa waxa loogu yeero xirmooyinka caalamiga ah. Iyo, tusaale ahaan, barnaamijyada raadraaca ayaa la sii dayn doonaa ka dib marka habka abuuray uu dhammaado (oo sidaas darteed waxaa loogu yeeraa mid gudaha, laga bilaabo "maxali ilaa habka"). Farsamo ahaan, jillaabyada maxalliga ah ayaa had iyo jeer leh sharraxa faylka u dhigma ee booska isticmaalaha oo sidaas darteed xira marka habka la xiro, laakiin jillaabyada caalamiga ah ma sameeyaan. Jaantuskan soo socda, adoo isticmaalaya iskutallaabyada cas, waxaan isku dayaa inaan muujiyo sida joojinta barnaamijka loader-ka ay u saameynayso nolosha walxaha ee kiiska gudaha iyo caalamiga ah.
Waa maxay sababta ay u kala duwan yihiin qabsashada gudaha iyo kuwa caalamiga ah? Ku shaqeynta qaar ka mid ah noocyada barnaamijyada shabakada waxay macno samaynayaan iyada oo aan la isticmaalin, tusaale ahaan, qiyaas ilaalinta DDoS - bootloader ayaa qoraya sharciyada oo ku xiraya barnaamijka BPF ee shabakada shabakada, ka dib markaa bootloader-ku wuu tagi karaa oo is dili karaa. Dhanka kale, qiyaas barnaamijka raadraaca qaladka ah oo aad ku qortay jilbahaaga toban daqiiqo gudahood - marka ay dhamaato, waxaad jeclaan lahayd inaysan jirin wax qashin ah oo ku haray nidaamka, iyo qabsatooyinka maxalliga ah ayaa xaqiijin doona taas.
Dhanka kale, ka fikir inaad rabto inaad ku xidho barta raadraaca ee kernel-ka oo aad ururiso tirakoob sanado badan. Xaaladdan oo kale, waxaad rabi lahayd inaad buuxiso qaybta isticmaalaha oo aad ku soo celiso tirakoobka waqti ka waqti. Nidaamka faylka bpf wuxuu bixiyaa fursadan. Waa nidaamka faylka been abuurka ah ee xusuusta-kaliya kaas oo u oggolaanaya abuurista faylasha tixraacaya walxaha BPF oo markaa kordhiya refcount walxaha. Taas ka dib, xamuulku wuu bixi karaa, walxaha uu abuurayna way sii noolaan doonaan.
Abuuritaanka faylasha bpffs ee tixraacaya walxaha BPF waxaa loo yaqaan "pinning" (sida weedha soo socota: "Nidaamku wuxuu dhejin karaa barnaamijka BPF ama khariidad"). Abuuritaanka walxaha feylasha ee walxaha BPF macno ma aha oo kaliya kordhinta nolosha walxaha maxalliga ah, laakiin sidoo kale isticmaalka walxaha caalamiga ah - dib ugu noqoshada tusaalaha barnaamijka ilaalinta caalamiga ah ee DDoS, waxaan rabnaa inaan awoodno inaan imaado oo aan eegno tirakoobka. marba mar.
Nidaamka faylka BPF badanaa waa lagu rakibaa /sys/fs/bpf, laakiin sidoo kale waxaa lagu dhejin karaa gudaha, tusaale ahaan, sidan:
$ mkdir bpf-mountpoint
$ sudo mount -t bpf none bpf-mountpoint
Magacyada nidaamka faylka ayaa la abuuray iyadoo la adeegsanayo amarka BPF_OBJ_PIN nidaamka BPF wac. Tusaale ahaan, aan soo qaadanno barnaamij, soo ururinno, dhejinno, oo ku dhejinno bpffs. Barnaamijkayagu ma sameeyo wax faa'iido leh, waxaan kaliya soo bandhigaynaa koodka si aad u soo saari karto tusaalaha:
Hadda aan soo dejinno barnaamijkeena anagoo adeegsanayna utility bpftool oo fiiri wicitaanada nidaamka la socda bpf(2) (qaar xariiqo aan khusayn oo laga saaray wax soo saarka xargaha):
Halkan waxaanu ku shubnay barnaamijka anagoo adeegsanayna BPF_PROG_LOAD, helay sharraxaadda faylka kernel-ka 3 iyo adeegsiga amarka BPF_OBJ_PIN ku dhejiyay sharraxaaha faylkan sidii fayl ahaan "bpf-mountpoint/test". Taas ka dib barnaamijka bootloader bpftool wuu dhammeeyay shaqada, laakiin barnaamijkayagu wuxuu ku hadhay kernel-ka, in kasta oo aynaan ku xidhin wax shabakad isku xidhan:
$ 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
Waxaan si caadi ah u tirtiri karnaa shayga faylka unlink(2) ka dibna barnaamijka u dhigma waa la tirtiri doonaa:
$ sudo rm ./bpf-mountpoint/test
$ sudo bpftool prog show id 783
Error: get by id (783): No such file or directory
Tirtirka walxaha
Marka laga hadlayo tirtiridda walxaha, waxaa lagama maarmaan ah in la caddeeyo in ka dib markii aan ka saarno barnaamijka jilbaha (dhaliyaha dhacdada), ma dhacdo dhacdo cusub oo kicinaysa bilawgeeda, si kastaba ha ahaatee, dhammaan dhacdooyinka hadda ee barnaamijka ayaa loo dhamaystiri doonaa sida caadiga ah. .
Qaar ka mid ah noocyada barnaamijyada BPF waxay kuu oggolaanayaan inaad bedesho barnaamijka duulista, i.e. siin atomiga isku xigxiga replace = detach old program, attach new program. Xaaladdan oo kale, dhammaan dhacdooyinka firfircoon ee noocii hore ee barnaamijka ayaa dhammayn doona shaqadooda, iyo maamulayaal cusub ayaa laga abuuri doonaa barnaamijka cusub, iyo "atomicity" halkan macnaheedu waa in aan hal dhacdo la seegi doonin.
Ku lifaaqida barnaamijyada ilaha dhacdada
Maqaalkan, si gooni ah uma qeexi doono ku xidhida barnaamijyada ilaha dhacdooyinka, maadaama ay macno samaynayso in tan lagu barto macnaha nooc gaar ah oo barnaamij ah. Cm. Tusaale hoos, kaas oo aan ku muujineyno sida barnaamijyada sida XDP ay isugu xiran yihiin.
Dhammaan walxaha BPF waxaa laga sameeyay oo laga maamulaa meel bannaan oo adeegsadaha iyadoo la adeegsanayo wicitaanka nidaamka bpf, isagoo leh tusaalaha soo socda:
#include <linux/bpf.h>
int bpf(int cmd, union bpf_attr *attr, unsigned int size);
Waa kan kooxda cmd waa mid ka mid ah qiyamka nooca enum bpf_cmd, attr - tilmaame tilmaamayaasha barnaamij gaar ah iyo size - cabbirka shayga marka loo eego tilmaamuhu, i.e. inta badan tan sizeof(*attr). Kernel 5.8 nidaamka wac bpf waxay taageertaa 34 amarro kala duwan, iyo qeexitaanunion bpf_attr ku fadhiya 200 oo sadar. Laakiin ma aha in ay na cabsi geliyaan tan, maadaama aan baran doono amarrada iyo cabbirrada inta lagu guda jiro maqaallo dhowr ah.
Aan ku bilowno kooxda BPF_PROG_LOAD, kaas oo abuura barnaamijyada BPF - wuxuu qaataa tilmaamo BPF ah wuxuuna ku shubaa kernel-ka. Xilliga rarka, xaqiijiyaha ayaa la bilaabay, ka dibna isku-duwaha JIT iyo, ka dib fulinta guuleysiga, sharaxaadaha faylka barnaamijka ayaa lagu soo celiyaa isticmaalaha. Waxaan ku aragnay wixii isaga ku dhacay ee ku xiga qaybta hore ku saabsan wareegga nolosha ee walxaha BPF.
Hadda waxaan qori doonaa barnaamij gaar ah oo ku shubi doona barnaamij fudud oo BPF ah, laakiin marka hore waxaan u baahanahay inaan go'aansano nooca barnaamijka aan rabno inaan ku shubno - waa inaan dooranaa nooca oo gudaha qaabka noocaan ah, ku qor barnaamij ka gudbi doona imtixaanka xaqiijinta. Si kastaba ha noqotee, si aan loo adkeyn geeddi-socodka, halkan waa xal diyaar ah: waxaan qaadan doonaa barnaamij sida BPF_PROG_TYPE_XDP, kaas oo soo celin doona qiimaha XDP_PASS (ka bood dhammaan baakadaha). Isku-duwaha BPF waxay u egtahay mid aad u fudud:
r0 = 2
exit
Ka dib markii aan go'aansanay in waan soo gelin doonaa, waxaan kuu sheegi karnaa sida aan u sameyn doono:
Laakiin maadaama ku qorista barnaamijyada BPF ee koodka asalka ah ay lagama maarmaan u tahay oo keliya qorista imtixaannada kernel-ka iyo maqaallada ku saabsan BPF, maqnaanshaha makrosyadani dhab ahaantii ma dhibayso nolosha horumariyaha.
Ka dib markii aan qeexno barnaamijka BPF, waxaan u dhaqaaqnaa si aan ugu shubno kernel-ka. Halbeegyadayada ugu yar attr waxaa ku jira nooca barnaamijka, habaynta iyo tirada tilmaamaha, shatiga loo baahan yahay, iyo magaca "woo", kaas oo aan isticmaalno si aan u helno barnaamijkayaga nidaamka ka dib marka la soo dejiyo. Barnaamijka, sidii ballanku ahaa, waxaa lagu shubaa nidaamka iyadoo la adeegsanayo wicitaanka nidaamka bpf.
Dhamaadka barnaamijka waxaan ku dhamaaneynaa wareeg aan xadidneyn oo u dhiganta culeyska. La'aanteed, barnaamijka waxaa dili doona kernel marka sharraxaadda feylka ee nidaamka wicitaanka nagu soo celiyay la xiro bpf, mana ku arki doono nidaamka.
Hagaag, waxaan diyaar u nahay tijaabinta. Aan isku soo uruurino oo aan barnaamijka hoos ka wadno stracesi loo hubiyo in wax walba ay u shaqeeyaan sidii la rabay:
Wax walba waa fiican yihiin, bpf(2) gacanta 3 ayaa nagu soo celiyay waxaanu galnay wareeg aan xad lahayn pause(). Aan isku dayno inaan ka helno barnaamijkayaga nidaamka. Si tan loo sameeyo waxaan aadi doonaa terminal kale oo aan isticmaalno utility bpftool:
la yaab ma leh. Hadda aan eegno koodka uu sameeyay isu-duwaha JIT:
# 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
aan aad waxtar u leh exit(2), laakiin si caddaalad ah, barnaamijkeenu aad buu u fudud yahay, iyo barnaamijyada aan fudfudud ahayn hordhaca iyo hal-abuurka ay ku dartay ururiyaha JIT, dabcan, ayaa loo baahan yahay.
Maps
Barnaamijyada BPF waxay isticmaali karaan meelaha xusuusta habaysan ee laga heli karo barnaamijyada kale ee BPF iyo barnaamijyada goobta isticmaalaha. Walxahaan waxaa lagu magacaabaa maab, qeybtaan waxaan ku tusi doonaa sida loo maamulo iyaga oo isticmaalaya nidaamka wicitaanka bpf.
Aynu isla markiiba nidhaahno in awoodaha maabku aanay ku xaddidnayn oo keliya helitaanka xusuusta la wadaago. Waxa jira khariidado ujeedo gaar ah ka kooban, tusaale ahaan, tilmaamayaasha barnaamijyada BPF ama tilmaamayaasha isku xidhka shabakadaha, maabyada la shaqaynta dhacdooyinka perf, iwm. Ka hadli mayno halkan, si aan loo jahawareerin akhristaha. Marka laga reebo tan, waan iska indho-tiraa arrimaha isku-dhafka, maadaama aysan tani muhiim u ahayn tusaalayaashayada. Liis dhamaystiran oo ah noocyada khariidadaha la heli karo ayaa laga heli karaa <linux/bpf.h>, qaybtan waxaynu tusaale u soo qaadan doonaa nooca kowaad ee taariikh ahaan, miiska xashiishka BPF_MAP_TYPE_HASH.
Haddii aad ku dhex abuurto miiska xashiishka, dheh, C++, waxaad odhan lahayd unordered_map<int,long> woo, oo Ruushku macneheedu yahay "waxaan u baahanahay miis woo cabbir aan xadidnayn, kuwaas oo furayaashu ay yihiin nooca int, iyo qiyamku waa nooca long" Si loo abuuro miiska xashiishka BPF, waxaan u baahanahay inaan sameyno wax badan oo isku mid ah, marka laga reebo inay tahay inaan qeexno cabbirka ugu sarreeya ee miiska, iyo halkii aan caddayn lahayn noocyada furayaasha iyo qiimaha, waxaan u baahannahay inaan ku qeexno cabbirkooda bytes. . Si aad u abuurto maab isticmaal amarka BPF_MAP_CREATE nidaamka call bpf. Aynu eegno in ka badan ama ka yar barnaamijka ugu yar ee abuuraya khariidad. Ka dib barnaamijkii hore ee ku raran barnaamijyada BPF, kani waa inuu kuugula ekaado mid fudud:
Waa kan nidaamka wicitaanka bpf(2) ayaa noo soo celisay nambarkii khariidadda sharraxaha 3 ka dibna barnaamijku, sida la filayo, wuxuu sugayaa tilmaamo dheeraad ah oo ku saabsan wicitaanka nidaamka pause(2).
Hadda aan u dirno barnaamijkayaga xagga dambe ama fur terminal kale oo aan eegno shaygayaga adoo isticmaalaya utility bpftool (magaceeda waxaan ka sooci karnaa khariidadeena kuwa kale):
$ sudo bpftool map
...
114: hash name woo flags 0x0
key 4B value 4B max_entries 4 memlock 4096B
...
Lambarka 114 waa aqoonsiga caalamiga ah ee shaygayaga. Barnaamij kasta oo nidaamka ku jira wuxuu isticmaali karaa aqoonsigan si uu u furo khariidad jira isagoo isticmaalaya amarka BPF_MAP_GET_FD_BY_ID nidaamka call bpf.
Hadda waxaan ku ciyaari karnaa miiska xashiishka. Aynu eegno waxa ku jira:
$ sudo bpftool map dump id 114
Found 0 elements
Madhan Aynu ku darno qiime hash[1] = 1:
$ sudo bpftool map update id 114 key 1 0 0 0 value 1 0 0 0
Aan markale eegno miiska:
$ sudo bpftool map dump id 114
key: 01 00 00 00 value: 01 00 00 00
Found 1 element
Hooray! Waxaan ku guuleysanay inaan ku darno hal shay. Ogsoonow in aan ka shaqeyno heerka byte si tan loo sameeyo, tan iyo bptftool ma garanayo nooca ay yihiin qiyamka miiska xashiishka. (Aqoontan waxaa lagu wareejin karaa iyada iyadoo la adeegsanayo BTF, laakiin in ka badan hadda.)
Sidee saxda ah ee bpftool u akhridaa oo ugu daraa walxaha? Bal aan eegno daboolka hoostiisa:
Marka hore waxaan ku furnay khariidadda aqoonsigeeda caalamiga ah anagoo adeegsanayna amarka BPF_MAP_GET_FD_BY_ID и bpf(2) noo soo celi tilmaanta 3. Si dheeraad ah u isticmaalaya amarka BPF_MAP_GET_NEXT_KEY Waxaan ka helnay furihii ugu horreeyay miiska annaga oo dhaafnay NULL sida tilmaanta furaha "kii hore". Haddii aan furaha haysano waan sameyn karnaa BPF_MAP_LOOKUP_ELEMKaas oo qiimihii ku soo celinaya tilmaame value. Talaabada xigta waa in aan isku dayno in aan helno cunsurka ku xiga anagoo u gudbinayna tilmaame furaha hadda jira, laakiin miiskayagu waxa uu ka kooban yahay hal shay iyo amarka BPF_MAP_GET_NEXT_KEY soo noqda ENOENT.
Hagaag, aynu ku beddelno qiimaha furaha 1, aynu nidhaahno caqli-galkeena ganacsigu wuxuu u baahan yahay diiwaangelin hash[1] = 2:
Sida la filayo, waa mid aad u fudud: amarka BPF_MAP_GET_FD_BY_ID wuxuu khariidadeena ku furaa aqoonsi, iyo amarka BPF_MAP_UPDATE_ELEM dib u qoraa curiyaha.
Markaa, ka dib markii aan samayno miiska xashiishka hal barnaamij, waxaan akhrin karnaa oo qori karnaa waxa ku jira mid kale. Ogsoonow in haddii aan awoodnay inaan tan ka sameyno khadka taliska, markaa barnaamij kasta oo kale oo nidaamka ayaa sameyn kara. Marka lagu daro amarada kor lagu sifeeyay, ee ku shaqaynta khariidadaha goobta isticmaalaha, soo socda:
BPF_MAP_LOOKUP_ELEM: qiimaha ku raadso furaha
BPF_MAP_UPDATE_ELEM: update/abuur qiimaha
BPF_MAP_DELETE_ELEM: furaha saar
BPF_MAP_GET_NEXT_KEYHel furaha ku xiga (ama kan ugu horreeya).
BPF_MAP_GET_NEXT_ID: waxay kuu ogolaanaysaa inaad dhex marto dhammaan khariidadaha jira, taasi waa sida ay u shaqeyso bpftool map
BPF_MAP_GET_FD_BY_ID: ku fur khariidad jira aqoonsigeeda caalamiga ah
BPF_MAP_LOOKUP_AND_DELETE_ELEM: atomically u cusboonaysii qiimaha shay oo soo celi kii hore
BPF_MAP_FREEZEKa dhig khariidadda mid aan laga beddeli karin goobta isticmaale (hawlgalkan lama celin karo)
BPF_MAP_LOOKUP_BATCH, BPF_MAP_LOOKUP_AND_DELETE_BATCH, BPF_MAP_UPDATE_BATCH, BPF_MAP_DELETE_BATCH: hawlgallada tirada badan. Tusaale ahaan, BPF_MAP_LOOKUP_AND_DELETE_BATCH - kani waa habka kaliya ee lagu kalsoonaan karo ee lagu akhriyo oo dib loogu dejiyo dhammaan qiyamka khariidada
Dhammaan amarradan uma shaqeeyaan dhammaan noocyada khariidadaha, laakiin guud ahaan la shaqeynta noocyada kale ee khariidadaha ee booska isticmaalaha waxay si sax ah ula mid yihiin ku shaqeynta miisaska xashiishka.
Si loo kala danbeeyo, aan dhameyno tijaabooyinka miiska xashiishka. Xusuusnow inaan abuurnay miis ka koobnaan kara ilaa afar fure? Aynu ku darno dhawr waxyaalood oo kale:
$ 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
Markaa, waxaanu samayn karnaa oo aanu ku shubi karnaa barnaamijyada BPF, sidoo kale waxaanu ka samayn karnaa oo aanu maamuli karnaa maabyada goobta isticmaalaha. Hadda waa macquul in la eego sida aan u isticmaali karno maabyada barnaamijyada BPF laftooda. Tan waxaan kaga hadli karnaa luqadda ay adag tahay in la akhriyo barnaamijyada mashiinka macro codes, laakiin dhab ahaantii waxaa la gaaray waqtigii lagu muujin lahaa sida barnaamijyada BPF dhab ahaan loo qoro loona ilaaliyo - iyadoo la adeegsanayo libbpf.
(Akhristayaasha aan ku qanacsanayn la'aanta tusaalaha hoose: waxaan si faahfaahsan u falanqeyn doonaa barnaamijyada adeegsada khariidadaha iyo hawlaha caawiye ee la abuuray iyadoo la isticmaalayo libbpf oo kuu sheego waxa ka dhacaya heerka tilmaamaha. Akhristayaasha aan ku qanacsanayn aad u badan, waxaanu ku daray Tusaale meesha ku haboon ee maqaalka.)
Qorista barnaamijyada BPF iyadoo la isticmaalayo libbpf
Qorista barnaamijyada BPF iyadoo la adeegsanayo koodka mishiinada waxay noqon kartaa mid xiiso leh marka ugu horeysa oo kaliya, ka dibna qanacsanaanta ayaa dejisa. Waqtigan xaadirka ah waxaad u baahan tahay inaad u jeedsato dareenkaaga llvm, kaas oo leh dhabarka soo saarista koodka qaab dhismeedka BPF, iyo sidoo kale maktabad libbpf, kaas oo kuu ogolaanaya inaad qorto dhinaca isticmaalaha ee codsiyada BPF oo aad ku shubto koodka barnaamijyada BPF ee la sameeyay llvm/clang.
Runtii sida aynu ku arki doonno qormadan iyo qormooyinka danbe ee soo socda. libbpf wuxuu qabtaa shaqo aad u badan la'aanteed (ama qalab la mid ah - iproute2, libbcc, libbpf-goiwm) waa wax aan macquul aheyn in la noolaado. Mid ka mid ah sifooyinka dilaaga ah ee mashruuca libbpf waa BPF CO-RE (Compile once, Run Everywhere) - mashruuc kuu ogolaanaya inaad qorto barnaamijyada BPF ee la qaadi karo hal kernel ilaa mid kale, awood u leh inuu ku shaqeeyo API-yo kala duwan (tusaale, marka qaabka kernel-ka uu isbeddelo nooca ilaa version). Si aad awood ugu yeelatid inaad la shaqeyso CO-RE, kernel-kaagu waa in lagu soo ururiyaa taageerada BTF (waxaan ku sharraxaynaa sida tan loo sameeyo qaybta Qalabka Horumarinta. Waxaad hubin kartaa in kernel-kaagu uu ku dhisan yahay BTF iyo in kale - iyadoo uu jiro faylka soo socda:
Faylkan waxa uu kaydiyaa macluumaadka ku saabsan dhammaan noocyada xogta ee loo isticmaalo kernel-ka waxaana loo adeegsadaa dhammaan tusaalayaashayada iyadoo la adeegsanayo libbpf. Waxaan si faahfaahsan ugala hadli doonaa CO-RE maqaalka soo socda, laakiin kan - kaliya ku dhis naftaada kernel leh CONFIG_DEBUG_INFO_BTF.
Maktabadda libbpf si toos ah ugu nool tusaha tools/lib/bpf kernel iyo horumarintiisa waxaa lagu fuliyaa liiska boostada [email protected]. Si kastaba ha ahaatee, kayd gaar ah ayaa loo hayaa baahida codsiyada ku nool meel ka baxsan kernel-ka https://github.com/libbpf/libbpf taas oo maktabadda kernel ay u muuqato si loo akhriyo wax badan ama ka yar sida ay tahay.
Qaybtan waxaan ku eegi doonaa sida aad u abuuri karto mashruuc isticmaalaya libbpf, aynu qorno dhawr (badan ama kayar oo aan macno lahayn) barnaamijyo imtixaan oo si faahfaahsan u falanqeeyo sida ay u wada shaqeeyaan. Tani waxay noo ogolaan doontaa inaan si sahlan ugu sharaxno qaybaha soo socda sida saxda ah ee barnaamijyada BPF ay ula falgalaan khariidadaha, caawiyayaasha kernel-ka, BTF, iwm.
Caadi ahaan mashaariicda la isticmaalayo libbpf ku dar kaydka GitHub sida git submodule, waxaanu samayn doonaa si la mid ah:
Inkasta oo barnaamijkeenu uu noqday mid aad u fudud, haddana waxaan u baahanahay inaan fiiro gaar ah u yeelano faahfaahin badan. Marka hore, faylka madaxa ee ugu horreeya ee aan ku darno waa vmlinux.h, kaas oo aan hadda soo saarnay annagoo adeegsanayna bpftool btf dump - hadda uma baahnid in aan rakibno xirmada kernel-headers si aan u ogaano sida qaab-dhismeedka kernel-ku u eg yahay. Faylka madaxa ee soo socda ayaa nooga imaanaya maktabadda libbpf. Hadda waxaan u baahanahay oo kaliya si aan u qeexno makro SEC, kaas oo u diraya jilaha qaybta ku habboon ee faylka shayga ELF. Barnaamijkayagu waxa uu ka kooban yahay qaybta xdp/simple, halka ka hor inta aan la jarjarin aan ku qeexno nooca barnaamijka BPF - kani waa heshiiska lagu isticmaalo libbpf, iyadoo lagu saleynayo magaca qaybta waxay bedeli doontaa nooca saxda ah ee bilowga bpf(2). Barnaamijka BPF laftiisa ayaa ah C - aad u fudud oo ka kooban hal xariiq return XDP_PASS. Ugu dambeyntii, qayb gaar ah "license" waxa ku jira magaca shatiga.
Waxaan ku ururin karnaa barnaamijkayaga anagoo adeegsanayna llvm/clang, nooca>= 10.0.0, ama ka sii fiican, (eeg qaybta Qalabka Horumarinta):
Haa, way shaqeysay! Hadda, waxaan haynaa faylka binary ee barnaamijka, waxaanan rabnaa inaan abuurno codsi ku dhejin doona kernel-ka. Ujeedadaas awgeed maktabadda libbpf waxay ina siinaysaa laba ikhtiyaar - isticmaal API heer hoose ah ama API heer sare ah. Waxaan mari doonaa dariiqa labaad, maadaama aan rabno inaan barano sida wax loo qoro, loo raro, looguna xiro barnaamijyada BPF dadaal yar oo loogu talagalay daraasaddooda xigta.
Marka hore, waxaan u baahanahay inaan ka soo saarno "qalfoofka" barnaamijkeena binary-ga iyadoo la isticmaalayo isla utility bpftool - mindida Swiss ee adduunka BPF (taas oo loo qaadan karo macno ahaan, tan iyo Daniel Borkman, mid ka mid ah abuurayaasha iyo ilaaliyayaasha BPF, waa Swiss):
$ bpftool gen skeleton xdp-simple.bpf.o > xdp-simple.skel.h
Faylka ku jira xdp-simple.skel.h ka kooban yahay code binary ee barnaamijkeena iyo hawlaha maaraynta - rarista, lifaaqa, tirtirto shayga. Kiiskeena fudud tani waxay u egtahay mid xad dhaaf ah, laakiin sidoo kale waxay ka shaqeysaa kiiska halka faylka shayga uu ka kooban yahay barnaamijyo badan oo BPF ah iyo khariidado iyo si aan u xirno ELF weyn waxaan kaliya u baahanahay inaan abuurno qalfoofka oo aan wacno hal ama laba shaqo oo ka mid ah codsiga gaarka ah. ayaa qoraya Aynu hadda dhaqaaqno.
Haddaan si adag u hadlo, barnaamijkeenu waa wax fudud:
#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);
}
Waxaan halkaan ku arki karnaa raadadka API-hooseeya: qaab-dhismeedka struct bpf_program *simple и struct bpf_link *simple. Qaab dhismeedka koowaad wuxuu si gaar ah u qeexayaa barnaamijkayaga, oo ku qoran qaybta xdp/simple, kan labaadna wuxuu qeexayaa sida barnaamijku ugu xidhmo isha dhacdada.
function xdp_simple_bpf__open_and_load, furaya shay ELF, kala jeexjeexay, abuuraa dhammaan qaab-dhismeedka iyo qaab-dhismeedyada (marka laga reebo barnaamijka, ELF sidoo kale waxay ka kooban tahay qaybo kale - xogta, xogta kaliya ee akhriska ah, macluumaadka debugging, shatiga, iwm.), ka dibna ku shuba kernelka iyadoo la adeegsanayo nidaam wac bpf, oo aan ku hubin karno innaga oo ururinayna barnaamijka:
# bpftool p d x id 463
int simple(void *ctx):
; return XDP_PASS;
0: (b7) r0 = 2
1: (95) exit
Wax cusub! Barnaamijku waxa uu daabacay qaybo ka mid ah faylka isha ee C. Tan waxa samaysay maktabadda libbpf, kaas oo ka helay qaybta debug-ka ee binary-ga, wuxuu ku soo ururiyay shay BTF, oo ku shubtay kernelka isagoo isticmaalaya BPF_BTF_LOAD, ka dibna cayimay sharraxaadda faylka natiijada marka aad barnaamijka ku shubayso amarka BPG_PROG_LOAD.
Gudaha qaab-dhismeedka "barashada tusaale ahaan" jaantuska, aan tixgelinno mid ka mid ah hawlaha caawiyaha, bpf_get_smp_processor_id(), la hubo faylka ku jira kernel/bpf/helpers.c. Waxay soo celinaysaa nambarka processor-ka uu ku shaqeynayo barnaamijka BPF ee u yeeray. Laakin uma xiisayneyno macnaheeda sida xaqiiqda ah in hirgelinteedu ay qaadato hal sadar:
Qeexitaannada shaqada caawiyaha BPF waxay la mid yihiin qeexitaannada wicitaanka nidaamka Linux. Halkan, tusaale ahaan, hawl ayaa lagu qeexaa oo aan lahayn wax dood ah. (Hawl qaadata, dheh, saddex dood ayaa lagu qeexaa iyadoo la adeegsanayo makro BPF_CALL_3. Tirada ugu badan ee dooduhu waa shan.) Si kastaba ha ahaatee, tani waa kaliya qaybta koowaad ee qeexida. Qaybta labaad waa in la qeexo qaabka nooca struct bpf_func_proto, oo ka kooban sharraxaadda shaqada caawiye ee uu xaqiijiyaha fahmayo:
Si barnaamijyada BPF ee nooc gaar ah ay u isticmaalaan shaqadan, waa in ay ka diwaan galiyaan, tusaale ahaan nooca BPF_PROG_TYPE_XDP shaqo ayaa lagu qeexaa kernel-ka xdp_func_proto, kaas oo go'aaminaya aqoonsiga shaqada caawiye in XDP ay taageerto hawshan iyo in kale. Shaqadeenu waa taageerooyinka:
Noocyada cusub ee barnaamijka BPF ayaa lagu "qeexay" faylka include/linux/bpf_types.h iyadoo la isticmaalayo makro BPF_PROG_TYPE. Waxaa lagu qeexay xigashooyin sababtoo ah waa qeexitaan macquul ah, iyo ereyada luqadda C qeexida dhammaan qaab-dhismeedka la taaban karo ayaa ka dhaca meelo kale. Gaar ahaan, faylka kernel/bpf/verifier.c dhammaan qeexitaannada faylka bpf_types.h waxaa loo isticmaalaa in lagu abuuro qaabab kala duwan bpf_verifier_ops[]:
Taasi waa, nooc kasta oo ka mid ah barnaamijka BPF, tilmaame qaab dhismeedka xogta nooca ayaa la qeexay struct bpf_verifier_ops, kaas oo lagu bilaabay qiimaha _name ## _verifier_ops, i.e. xdp_verifier_ops si ay u xdp... Qaab dhismeedka xdp_verifier_opsgo'aamiyay faylka ku jira net/core/filter.c sida soo socota:
Halkan waxaan ku aragnaa shaqadayada la yaqaan xdp_func_proto, kaas oo wadi doona hubinta mar kasta oo ay la kulanto caqabad nooc ah hawlaha gudaha barnaamijka BPF, eeg verifier.c.
Aynu eegno sida barnaamijka mala-awaalka ah ee BPF uu u isticmaalo shaqada bpf_get_smp_processor_id. Si taas loo sameeyo, waxaan dib ugu qoreynaa barnaamijka qaybteena hore sida soo socota:
Safka hore waxaan ku aragnaa tilmaamo call, halbeegga IMM oo la mid ah 8, iyo SRC_REG - eber. Sida uu dhigayo heshiiska ABI ee uu isticmaalo hubiyaha, kani waa wicitaanka caawiye nambarka sideedaad. Marka la bilaabo, caqli-galku waa sahlan yahay. Ka soo celi qiimaha diiwaanka r0 laga guuriyay r1 iyo xariiqyada 2,3 waxa loo rogaa nooca u32 - 32-bit ee sare waa la nadiifiyay. Sadarka 4,5,6,7 waxaan ku celinaynaa 2 (XDP_PASS) ama 1 (XDP_DROP) iyadoo ku xiran in kaaliyaha uu ka shaqeeyo laynka 0 uu soo celiyay eber ama aan eber ahayn.
Aynu is tijaabinno: ku shubo barnaamijka oo aynu eegno wax soo saarka 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
Halbeegyada hawlaha caawiye ayaa lagu gudbiyaa diiwaannada r1-r5, qiimahana waxaa lagu soo celiyaa diiwaanka r0. Ma jiraan wax hawlo ah oo qaata wax ka badan shan dood, taageero iyagana lama filayo in mustaqbalka lagu daro.
Aynu eegno caawiyaha kernel-ka cusub iyo sida BPF u gudbiso cabirrada. Aan dib u qorno xdp-simple.bpf.c sida soo socota (xadadka intiisa kale isma bedelin):
SEC("xdp/simple")
int simple(void *ctx)
{
bpf_printk("running on CPU%un", bpf_get_smp_processor_id());
return XDP_PASS;
}
Barnaamijkeenu waxa uu daabacaa tirada CPU-ga uu ku shaqaynayo. Aynu soo ururinno oo eegno koodka:
Halkan waxaan isticmaalnaa shaqada bpf_set_link_xdp_fd, kaas oo ku xidha barnaamijyada BPF nooca XDP-ga iyo isku-xidhka shabakadaha. Waxaan hardcoded nambarka interface lo, taas oo had iyo jeer ah 1. Waxaan wadnaa shaqada laba jeer si aan marka hore ka saarno barnaamijkii hore haddii lagu dhejiyay. Ogow hadda uma baahnin caqabad pause ama wareeg aan xad lahayn: barnaamijka raridayagu wuu baxayaa, laakiin barnaamijka BPF lama dili doono maadaama uu ku xidhan yahay isha dhacdada. Ka dib markii si guul leh loo soo dejiyo iyo isku xirka, barnaamijka waxaa loo bilaabi doonaa xirmo kasta oo shabakad ah oo yimaada lo.
Aan soo dejino barnaamijka oo aan eegno interface-ka 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
Barnaamijka aan soo dejinay waxa uu leeyahay ID 669 waxaanan ku aragnaa isla aqoonsiga interface-ka lo. Waxaan u diri doonaa dhowr xirmo 127.0.0.1 (codsi + jawaab):
$ ping -c1 localhost
oo hadda aan eegno waxa ku jira faylka casriga ah ee khaladka ah /sys/kernel/debug/tracing/trace_pipe, kaas oo bpf_printk Farriimihiisa ayuu qoray:
# 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
Laba baako ayaa lagu arkay lo oo lagu farsameeyay CPU0 - barnaamijkeenii ugu horreeyay ee BPF oo aan macno lahayn ayaa shaqeeyay!
Waxaa xusid mudan taas bpf_printk Ma aha wax aan waxba ahayn in ay u qorto feylka cilladaha: tani ma aha kaaliyaha ugu guulaha badan ee loo isticmaalo wax soo saarka, laakiin hadafkeenu wuxuu ahaa inaan muujino wax fudud.
Helitaanka maabyada barnaamijyada BPF
Tusaale: adigoo isticmaalaya khariidad ka socota barnaamijka BPF
Qaybihii hore waxaan ku barannay sida loo sameeyo oo loo isticmaalo maab-ka-baxyada isticmaalaha, oo hadda aan eegno qaybta kernel-ka. Aan ku bilowno, sida caadada ah, tusaale. Aan dib u qorno barnaamijkeena xdp-simple.bpf.c sida soo socota:
Aynu eegno inay ku xidhan tahay lo oo soo dir qaar ka mid ah baakado:
$ 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
$ 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
Laakiin haddii aan eegno barnaamijkii hore loo raray, waxaan aragnaa tilmaame khariidadda saxda ah (line 4):
Sidaa darteed, waxaan ku soo gabagabeyn karnaa in waqtiga la bilaabayo barnaamijkeena loader, isku xirka &woo waxaa lagu beddelay wax maktabad leh libbpf. Marka hore waxaan eegi doonaa wax soo saarka strace:
kuna beddel diiwaanka isha ee ku jira BPF_PSEUDO_MAP_FD, iyo IMM-kii ugu horreeyay ee sharraxa faylka ee khariidadeena iyo, haddii ay la mid tahay, tusaale ahaan, 0xdeadbeef, ka dibna natiijada waxaan heli doonaa tilmaamaha
18 11 00 00 ef eb ad de 00 00 00 00 00 00 00 00 r1 = 0 ll
Tani waa sida macluumaadka khariidadda loogu wareejiyo barnaamij gaar ah oo la raray BPF. Xaaladdan oo kale, khariidadda waxaa la samayn karaa iyadoo la isticmaalayo BPF_MAP_CREATE, oo lagu furay aqoonsi isticmaalaya BPF_MAP_GET_FD_BY_ID.
Wadarta, marka la isticmaalayo libbpf Algorithm waa sida soo socota:
Inta lagu guda jiro ururinta, diiwaanada waxaa lagu abuuray miiska raritaan xiriirinta maabyada
libbpf furaya buuga shayga ELF, helaya dhamaan maabkii la isticmaalay oo u abuuraa sharraxayaal faylal ah
Sharaxayaasha faylka ayaa lagu shubaa kernel-ka iyada oo qayb ka ah tilmaamaha LD64
Sidii ballanku ahaa, halkan waxaa tusaale u ah akhristayaasha doonaya in ay ogaadaan sida loo sameeyo loona raro barnaamij isticmaalaya maab, iyada oo aan caawin libbpf. Tani waxay noqon kartaa mid faa'iido leh marka aad ka shaqeyneyso deegaan aadan dhisi karin ku tiirsanaanta, ama aad badbaadin karto xoogaa, ama qorto barnaamij sida ply, kaas oo soo saara koodka binary BPF ee duulista.
Si loo fududeeyo raacitaanka macquulka ah, waxaan dib u qori doonaa tusaalaheena ujeedooyinkan xdp-simple. Koodhka barnaamijka oo dhammaystiran oo xoogaa la ballaariyey ayaa laga heli karaa tan gist.
Macnaha codsigayagu waa sida soo socota:
samee khariidad nooc ah BPF_MAP_TYPE_ARRAY iyadoo la isticmaalayo amarka BPF_MAP_CREATE,
samee barnaamij isticmaalaya khariidadan,
ku xidh barnaamijka interface-ka lo,
taas oo u tarjumeysa aadanaha sida
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);
}
waa map_create wuxuu abuuraa khariidad si la mid ah sidii aan ku samaynay tusaalihii ugu horreeyay ee ku saabsan nidaamka wicitaanka bpf - "Kernel, fadlan ii samee khariidad cusub oo qaabaysan 8 walxood oo kala ah __u64 oo ii soo celi tusaha faylka":
Layli kuwa aan iyagu qorin tan laftooda - raadi map_fd.
Waxa barnaamijkayaga ku hadhay qayb kale oo aan la shaacin - xdp_attach. Nasiib darro, barnaamijyada sida XDP laguma xidhi karo iyada oo la isticmaalayo nidaamka wicitaanka bpf. Dadka abuuray BPF iyo XDP waxay ka yimaadeen bulshada Linux ee khadka tooska ah, taas oo macnaheedu yahay inay isticmaaleen midka ay yaqaaniin (laakiin maaha inay isticmaalaan. caadi dadka) interface ee la falgalka kernel-ka: saldhigyada netlinksidoo kale eeg RFC3549. Habka ugu fudud ee loo fuliyo xdp_attach ayaa koodhka ka soo koobiyaysa libbpf, oo ah, laga bilaabo faylka netlink.c, taasoo ah tii aanu samaynay, annagoo in yar soo gaabinay:
Ku soo dhawoow aduunka netlink sockets
Fur nooca godka 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;
}
Waxaan ka akhrinay godkan:
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;
}
Ugu dambayntii, waa kan shaqadeenii oo furta godka oo u soo dirtaa farriin gaar ah oo ay ku jirto sharraxaha faylka:
Aynu eegno in barnaamijkeenu ku xidhan yahay iyo in kale 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
Hurray, wax walba waa shaqeeyaan. Ogow, jid ahaan, in khariidadeena ay mar kale soo bandhigtay qaab bytes ah. Tani waxay sabab u tahay xaqiiqda ah, ka duwan libbpf Ma aan shubin macluumaadka nooca (BTF). Laakiin wax badan ayaan ka hadli doonaa marka xigta.
Qalabka Horumarinta
Qaybtan, waxaan ku eegi doonaa qalabka wax soo saar ee BPF ugu yar.
Guud ahaan, uma baahnid wax gaar ah si aad u horumariso barnaamijyada BPF - BPF waxay ku shaqeysaa kernel qaybinta wanaagsan, barnaamijyadana waxaa la dhisay iyadoo la isticmaalayo clang, kaas oo laga keeni karo xirmada. Si kastaba ha noqotee, sababtoo ah xaqiiqda ah in BPF ay ku jirto horumarinta, kernel-ka iyo qalabka ayaa si joogto ah isbeddelaya, haddii aadan rabin inaad qorto barnaamijyada BPF adigoo isticmaalaya habab hore oo laga bilaabo 2019, markaa waxaad u baahan doontaa inaad ururiso.
BPF waxay saaxiib la tahay LLVM, in kasta oo barnaamijyada BPF ee dhowaanahan lagu soo ururin karo gcc, dhammaan horumarka hadda jira waxaa loo fuliyaa LLVM. Sidaa darteed, marka hore, waxaan dhisi doonaa version hadda clang ka 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
... много времени спустя
$
Hadda waxaan hubin karnaa in wax walba si sax ah isugu yimaadeen:
(Awaamiirta golaha clang aan ka qaatay bpf_devel_QA.)
Ma rakibi doono barnaamijyada aan hadda dhisnay, laakiin taa beddelkeeda ku darso PATH, tusaale ahaan:
export PATH="`pwd`/bin:$PATH"
(Tani waa lagu dari karaa .bashrc ama fayl gaar ah. Shakhsi ahaan, waxaan ku daraa waxyaalahan oo kale ~/bin/activate-llvm.sh markii loo baahdona waan sameeyaa . activate-llvm.sh.)
Pahole iyo BTF
Faa'iidada pahole loo isticmaalo marka la dhisayo kernel si loo abuuro macluumaadka cilladaha ee qaabka BTF. Ma geli doono si faahfaahsan maqaalkan ku saabsan faahfaahinta tignoolajiyada BTF, marka laga reebo xaqiiqda ah inay ku habboon tahay oo aan rabno inaan isticmaalno. Markaa haddii aad dhisayso kernel-kaaga, marka hore dhis pahole (la'aan pahole ma awoodi doontid inaad ku dhisto kernel ikhtiyaarka 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 loogu talagalay tijaabinta BPF
Marka aan sahaminayo fursadaha BPF, waxaan rabaa in aan ururiyo xuduntayda. Tani, guud ahaan marka loo eego, maahan lagama maarmaan, maadaama aad awoodi doonto inaad ururiso oo aad ku shubto barnaamijyada BPF kernel-ka qaybinta, si kastaba ha ahaatee, haysashada kernel-kaaga ayaa kuu ogolaanaysa inaad isticmaasho sifooyinka BPF ee ugu dambeeyay, kaas oo ka muuqan doona qaybintaada bilaha ugu fiican. , ama, sida kiiska qaar ka mid ah qalabyada wax-ka-hortagga ah gabi ahaanba lama daabici doono mustaqbalka la filayo. Sidoo kale, udub-dhexaadkeeda ayaa dareensan in ay muhiim tahay in lagu tijaabiyo koodka.
Si aad u dhisto kernel waxaad u baahan tahay, marka hore, kernel laftiisa, marka labaadna, faylka qaabeynta kernel. Si loo tijaabiyo BPF waxaan isticmaali karnaa kuwa caadiga ah vanilj kernel ama mid ka mid ah kernels horumarinta. Taariikh ahaan, horumarinta BPF waxay ka dhacdaa gudaha bulshada isku xidhka Linux, sidaas darteed dhammaan isbeddellada mar hore ama hadhow waxay maraan David Miller, ilaaliye isku xidhka Linux. Iyada oo ku xidhan dabeecadooda - wax ka beddelka ama astaamo cusub - isbeddellada shabakadu waxay u dhacaan mid ka mid ah laba qaybood - net ama net-next. Isbeddellada BPF waxaa loo qaybiyaa si la mid ah inta u dhaxaysa bpf и bpf-next, kuwaas oo markaa la isugu geeyey shabaq iyo shabaq-xiga, siday u kala horreeyaan. Faahfaahin dheeraad ah, arag bpf_devel_QA и netdev-FAQ. Markaa dooro kernel ku salaysan dhadhankaaga iyo baahiyaha xasiloonida nidaamka aad tijaabinayso (*-next kernels ayaa ah kuwa ugu xasilloon kuwa liiska ku jira).
Way ka baxsan tahay baaxadda maqaalkan in laga hadlo sida loo maareeyo faylasha qaabeynta kernel - waxaa loo maleynayaa inaad horeyba u taqaanay sida tan loo sameeyo, ama diyaar u ah inuu wax barto kaligiis. Si kastaba ha ahaatee, tilmaamaha soo socdaa waa inay ahaadaan kuwo badan ama ka yar oo ku filan si ay kuu siiyaan nidaam karti u leh BPF.
Soo deji mid ka mid ah kernels-ka sare:
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git
$ cd bpf-next
Dhis isku xidhka kernel-ka shaqeeya ee ugu yar:
$ cp /boot/config-`uname -r` .config
$ make localmodconfig
Daar doorashooyinka BPF ee faylka .config doorashadaada (badanaa CONFIG_BPF mar horeba waa la hawlgelin doonaa maadaama systemd uu isticmaalo). Waa kuwan liiska xulashooyinka kernel-ka loo isticmaalo maqaalkan:
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
Kadibna si fudud ayaan u ururin karnaa oo u rakibi karnaa modules-yada iyo kernel-ka (sida, waxaad ku ururin kartaa kernel adoo isticmaalaya kuwa cusub ee la soo ururiyey. clangisagoo ku daray CC=clang):
$ make -s -j $(getconf _NPROCESSORS_ONLN)
$ sudo make modules_install
$ sudo make install
oo dib ugu bilow kernel-ka cusub (waxaan u isticmaalayaa tan kexec ka xirmada 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
Utility inta badan la isticmaalo ee maqaalka waxay noqon doontaa utility bpftool, oo loo keenay qayb ka mid ah kernel Linux. Waxaa qoray oo ay ilaaliyeen horumariyeyaasha BPF ee horumarinta BPF waxaana loo isticmaali karaa in lagu maareeyo dhammaan noocyada walxaha BPF - barnaamijyada rarka, abuurista iyo tafatirka maabka, sahaminta nolosha nidaamka deegaanka BPF, iwm. Dukumentiyada qaabka koodhadhka isha ee bogagga man waa la heli karaa xudunta u ah ama, mar hore la soo ururiyey, shabaqa.
Waqtiga qoraalkan bpftool u soo diyaarsan oo kaliya RHEL, Fedora iyo Ubuntu (eeg, tusaale ahaan, duntan, kaas oo ka sheekeynaya sheekada aan dhammaan ee baakadaha bpftool ee Debian). Laakiin haddii aad hore u dhistay kernelkaaga, ka dibna dhis bpftool sida ugu fudud ee pie:
$ 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 ]
$
(Halkan ${linux} - kani waa hagahaaga kernel-ka.) Kadib fulinta amaradan bpftool waxaa lagu soo ururin doonaa buug-tusaha ${linux}/tools/bpf/bpftool waxaana lagu dari karaa wadada (marka ugu horeysa ee isticmaalaha root) ama ku koobbi /usr/local/sbin.
Ururi bpftool waxaa fiican in la isticmaalo kan dambe clang, la soo ururiyey sida kor lagu sharaxay, oo hubi in si sax ah loo ururiyey - adigoo isticmaalaya, tusaale ahaan, amarka
$ 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
...
kaas oo tusi doona sifada BPF ee karti u leh kernelkaaga.
By habka, amarkii hore waxaa loo maamuli karaa sida
# bpftool f p k
Tan waxaa lagu sameeyaa isbarbardhig la leh yutiilitida xirmada iproute2, meesha aan ka, tusaale ahaan, odhan ip a s eth0 halkii ip addr show dev eth0.
gunaanad
BPF waxay kuu ogolaanaysaa inaad kabto boodada si aad si wax ku ool ah u cabbirto oo aad duulimaadka u beddesho shaqada xudunta u ah. Nidaamku wuxuu u soo baxay inuu noqdo mid aad u guuleysta, oo ku jira caadooyinka ugu wanaagsan ee UNIX: hab fudud oo kuu ogolaanaya inaad dib u dhigto barnaamijka kernel-ka ayaa loo oggolaaday tiro aad u badan oo dad ah iyo ururo ah inay tijaabiyaan. Iyo, inkasta oo tijaabooyinka, iyo sidoo kale horumarinta kaabayaasha BPF lafteeda, ay aad uga fog yihiin in la dhammeeyo, nidaamku wuxuu horeyba u leeyahay ABI xasilloon oo kuu ogolaanaya inaad dhisto la isku halleyn karo, iyo tan ugu muhiimsan, caqli-gal ganacsi oo waxtar leh.
Waxaan jeclaan lahaa in aan ogaado, fikradayda, tignoolajiyada ayaa noqotay mid caan ah sababtoo ah, dhinaca kale, waa la isticmaali karaa. inuu ciyaaro (nashqada mishiinka waxa la fahmi karaa in ka badan ama ka yar hal fiidkii), dhinaca kale, si loo xalliyo dhibaatooyinka aan la xalin karin (quruxda) ka hor muuqaalkiisa. Labadan qaybood oo wada jir ah ayaa dadka ku qasbaya inay tijaabiyaan oo ay ku riyoodaan, taas oo keenta in ay soo baxaan xalal cusub oo badan.
Maqaalkani, in kasta oo aan si gaar ah u gaabanayn, waa hordhac kaliya ee adduunka BPF mana qeexayo sifooyinka "horumarsan" iyo qaybaha muhiimka ah ee dhismaha. Qorshaha horay u socdaa waa sidan oo kale: maqaalka soo socdaa wuxuu noqon doonaa dulmar ku saabsan noocyada barnaamijka BPF (waxaa jira 5.8 nooc oo barnaamij ah oo lagu taageerayo kernel 30), ka dib waxaan ugu dambeyntii eegi doonaa sida loo qoro codsiyada BPF ee dhabta ah iyadoo la adeegsanayo barnaamijyada raadinta kernel Tusaale ahaan, ka dib waa waqtigii koorsada qoto dheer ee dhismaha BPF, oo ay ku xigto tusaalooyinka isku xirka BPF iyo codsiyada amniga.
Tixraaca BPF iyo XDP - dukumeenti ku saabsan BPF ee cilium, ama si ka badan oo sax ah oo laga helay Daniel Borkman, mid ka mid ah abuurayaasha iyo ilaaliyayaasha BPF. Tani waa mid ka mid ah sharraxaadda ugu horreeya ee halista ah, taas oo ka duwan kuwa kale in Daanyeel uu si sax ah u yaqaan waxa uu qorayo oo aysan jirin wax khalad ah. Gaar ahaan, dukumeentigani wuxuu qeexayaa sida loola shaqeeyo barnaamijyada BPF ee noocyada XDP iyo TC iyadoo la adeegsanayo tamarta caanka ah ip ka xirmada iproute2.
Dukumeenti/shabakad/filter.txt - faylka asalka ah oo wata dukumeenti loogu talagalay classic ka dibna BPF la dheereeyey. Akhris wanaagsan haddii aad rabto inaad u dhex gasho luqadda kulanka iyo faahfaahinta qaabdhismeedka farsamada.
Blog ku saabsan BPF ka facebook. Si dhif ah ayaa loo cusbooneysiiyaa, laakiin si habboon, sida Alexei Starovoitov (qoraaga eBPF) iyo Andrii Nakryiko - (hayaha) ay halkaas ku qoraan. libbpf).
Sirta bpftool. Dul twitter madadaalo leh oo ka socda Quentin Monnet oo wata tusaalooyin iyo siraha isticmaalka bpftool.