In principio erat technicae artis et vocatum BPF. Vidimus eam prior, Veteris Testamenti articulus huius seriei. Anno 2013, per conatus Alexei Starovoitov et Daniel Borkman, eius versio emendata, optimizata pro modernis machinis 64 frenum, in Linux nucleo evoluta est et inclusa. Haec nova technologia breviter appellata Interna BPF, deinde BPF appellata, et nunc, post aliquot annos, omnes simpliciter appellat BPF.
Dure loquendo, BPF permittit te utentis arbitrarii copiam in spatio nuclei Linux currere, et nova architectura tam prospere evenit ut duodecim plures articulos egebimus ad omnes eius applicationes describendas. (Sola res tincidunt bene non fecerunt, ut videre potes in codice perficiendi infra, logo honestum creabat.
Hic articulus describit structuram machinae virtualis BPF, nuclei interfaces ad operandum cum instrumentis BPF, evolutionis instrumentis, necnon brevissima et brevissima perspectiva exsistentium facultatum, i.e. omnia quae in posterum desiderabimus ad altiorem applicationem applicationum BPF.
Administrandi ratio bpf obiecti utens vocationem. Cum aliquo intellectu systematis iam positi, tandem spectabimus quomodo res ab usuario spatii creare et manipulare utendo speciali systemate vocamus. bpf(2).
ΠΠΈΡΠ΅ΠΌ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ BPF Ρ ΠΏΠΎΠΌΠΎΡΡΡ libbpf. Utique scribere potes programmata vocationis systematis utens. Sed difficile est. Ad missionem magis realisticam, programmarii nuclei bibliothecam elaboraverunt libbpf. Nos basicum BPF applicationem sceleti creabimus, quo in exemplis subsequentibus utemur.
Kernel Diaconi. Hic discemus quomodo programmata BPF accessere possint munera adiutoris nuclei - instrumentum quod cum mappis fundamentaliter dilatat facultates novae BPF comparatae classicae.
Accessus ad chartas ex programmatibus BPF. Hoc loco satis clare intelligemus quomodo programmata quae in mappis utuntur, creare possimus. Et etiam in verificatorem magnum et potentem acumen accipiamus.
Instrumenta progressio. Subsidia de sectione quam ad utilitates et nucleos experimentorum convocandas.
Conclusio. In fine articuli, qui hoc longe legunt, verba moventia invenient, et brevem descriptionem eorum quae in sequentibus articulis fient. Ponemus etiam plures nexus studiorum sui erga eos qui desiderium vel facultatem continuationem exspectare non habent.
Introductio ad Architecturam BPF
Antequam architecturam BPF considerare incipiamus, unum extremum tempus ad (oh) referemus classic BPFquae tamquam responsio ad adventum machinis RISC evoluta est et quaestionem eliquandi efficiendi televisificam solvit. Architectura ita feliciter evenit ut, cum in Berkeley UNIX novemties collisione nata esset, ad systemata operativa maxime exsistentia deportaretur, in viginti insanis superfuit et adhuc novas applicationes invenit.
Novus BPF explicavit ut responsio ad ubiquitatem machinis 64-frenum, nubium officia et auctam necessitatem instrumentorum ad SDN creandum (Software-defined networking). A nucleo fabrum retis evolutae ut emendato reposito pro classic BPF, novus BPF literam sex mensium postea applicationes in difficili negotio systemata Linux investigandi invenit, et nunc, sex annis post eius speciem, totum proximum articulum mox indigebimus. enumerare rationes programmata.
Ridiculam imaginibus
In suo nucleo, BPF est sandbox virtualis machina quae te permittit ut "arbitrarium" codicem in spatio nucleo currere sine securitate afferat. BPF programmata in spatio usoris creantur, in nucleum onusta et ad fontem aliquo eventui connexae. Eventus esse potest, exempli gratia, traditio fasciculi ad interfaciem retis, deductio functionis alicuius nuclei, etc. In casu sarcina, progressio BPF habebit accessum ad notitias et metadatas fasciculi (ad legendi et fortasse scribendi secundum rationem programmatis); in casu nuclei muneris, argumenta. munus, additis acinum indicibusque memoriae, etc.
Propius inspiciamus hunc processum. In primis, fama de prima differentia a classicis BPF, quae programmata scripta sunt in coadunatione. In nova versione, architectura amplificata est ut programmata in linguis alta conscribi possent, imprimis, sane in C. Propter hoc, finis llvm elaboratum est, quod permittit te ad architecturam bytecode generare.
Architectura BPF designata est, ex parte, ut efficaciter in hodiernis machinis curreret. Ad hoc opus in praxi faciendum, bytecode BPF, olim in nucleum onustus, in codicem nativum translatum est utens componente compilator nomine JIT.Jquemad In Time). Deinde, si meministi, programmata classica BPF in nucleo onerata erat et eventui fonti atomice affixa - in contextu unius systematis vocationis. In nova architectura, hoc duobus gradibus accidit - primo, codice oneratur in nucleo utens ratio vocationis. bpf(2)ac deinde, postea, per alias machinas varias secundum rationem programmatis, propositum eventui principii adiungitur.
Hic lector quaestionem habere potest: an fieri potuit? Quomodo salus talis codicis praestatur exsecutio? Executio salus nobis praestatur a stadio onerandi BPF programmatis verificantis (Anglice haec scaena verificatrix appellatur et verbo Anglico uti pergo);
Verificatorium analysris staticae est, quod efficit ut programma normalem operationem nuclei non rumpat. Hoc obiter non significat propositum non posse impedire operationi systematis - BPF programmatis, secundum genus, legere et rescribere sectiones memoriae nuclei, reddere valores functionum, stringere, appendere, rescribere. atque etiam deinceps retiacula facis. Verificatorium cautiones quae programmatis BPF currit, nucleum non collidet et programma quod secundum regulas accessum scribere habet, exempli gratia, notitia exitu fasciculi, memoriam nuclei extra fasciculum rescribere non poterit. Verificatorium paulo subtilius in sectione respondente intuebimur, postquam cetera omnia BPF comprehendimus.
Quid ergo tam longe didicimus? Usor programmatis in C scribit, eam in nucleo utens ratio vocationis onerat bpf(2), ubi a uerificante retunditur et bytecode in natalem translatum. Tunc idem vel alius usor programmatum cum eventu coniungit et incipit agere. Caliga et nexus separare pluribus de causis necessarium est. Uno modo, currens verificator est relative carus et ex eadem programmate sumendo pluries tempus computatorium consumimus. Secundo, quemadmodum programma coniungitur a suo genere dependet, et unum interface "universale" ante annum elaboratum non potest convenire novis programmatis rationibus. (Quamquam nunc architectura maturior fieri possit, idea est hoc instrumenti in plano coniungendi libbpf.)
Videat attentus lector nos imaginibus nondum confectos esse. Immo omnia supradicta non explicant cur BPF fundamentaliter imaginem mutet comparatam classic BPF. Duae innovationes quae insigniter ampliant scopum applicabilitatis, facultas est utendi memoria communi et adiutorio nucleo functionum. In BPF, memoria communicata perficit utens maps sic dictas β structuris communicatis cum certis API. Probabiliter hoc nomen obtinuit quod primum genus tabulae ut appareret erat mensa Nullam. Tunc apparuerunt vestes, locales (per-CPU) tabulae Nullam et vestitus localis, arbores quaesitae, tabulae quae in BPF programmata et multo plura indicant. Quid nunc nobis interest, quod programmata BPF nunc facultatem habent perseverandi status inter vocat et eam cum aliis programmatis et cum spatio usoris communicandi.
Maps accessed ex processibus usoris utens ratio vocationis bpf(2), et ex BPF programmatibus in nucleo decurrentibus functionibus adiutoris utentis. Praeterea adiutores sunt non solum ad operandum cum mappis, sed etiam ad alias facultates nucleos accedunt. Exempli gratia, BPF programmata adiutoria functionibus uti possunt ad alia interfaces transmittere, eventus perf generare, structuras nuclei accedere, et sic porro.
In summa, BPF facultatem praebet arbitrariam, i.e., verificantis probatam, usoris in spatio nuclei onerandi. Hoc signum statum inter vocationes et commutationem notitias cum spatio usoris servare potest, et etiam accessum ad subsystematum nuclei subsystematis permissum est.
Hoc iam simile est facultatibus a nucleo modulorum comparatis, quibus BPF aliquas utilitates habet (sane, si similes applicationes comparare potes, exempli gratia ratio typum - arbitrarium cum BPF scribere non potes). Limen ingressum inferiorem notare potes (quaedam utilitates quae BPF utuntur, utentem non requirunt ut artes nuclei programmandi, vel artes programmandi in genere), salus runtime (tolle manum tuam in commenta pro iis qui systema scribentem non rumpunt. seu modulorum probatio), atomicity - est tempus downtime cum modulorum reloading, et subsystem subsystem BPF efficit ut nullae eventus fallantur (quod pulchrum est, hoc omnibus generibus BPF programmatis verum non est).
Praesentia talium facultatum instrumentum universale facit BPF ad augendum nucleum, quod in praxi confirmatur: plura ac magis nova programmatum genera adduntur BPF, magis magisque magnae societates BPF utuntur in pugna servientibus 24-7, magis ac magis satus negotium suum aedificant in solutionibus secundum quae in BPF nituntur. BPF ubique adhibetur: in defensione contra impetus DDoS, SDN creandi (exempli gratia, retiacula kubernetes exsequentes), sicut instrumentum systematis principale repetens et collectorem statisticum, in intrusione systemata detectionis et systemata sandbox, etc.
Percontationem partem articuli hic perficiamus et accuratius machinam virtualem et BPF ecosystematis intueamur.
Digressio: utilitates
Ut exempla in sequentibus sectionibus currere possint, pluribus utilitatibus saltem opus sit llvm/clang cum bpf auxilio et bpftool. sectioni Progressio Tools Leges instructiones ad utilitatem congregandas ac acinum tuum. Hoc capitulum infra positum est, ne nostre praesentationis concordiam turbet.
Rectum BPF Machina registra et Instructio Ratio
Architectura et ratio imperii BPF elaborata est ratione habita quod programmata in lingua C scribenda et in nucleo oneratique in codicem vernacum translati sunt. Numerus ergo registrorum ac mandatorum statuto oculo ad intersectionem, sensu mathematico, de facultatibus machinis recentiorum electi sunt. Variae praeterea programmata restrictiones impositae sunt, exempli gratia, donec nuper loramenta et subroutina scribere non potuit, et numerus instructionum ad 4096 limitatus est (nunc programmata privilegiata usque ad decies centena millia instructionum onerare possunt).
BPF habet undecim user-pervia 64-bit commentariis r0-r10 et programma considit. Register r10 tabulam continet regulam et solum legitur. Programmata aditus ad 512 byte acervum runtime et indefinitum memoriae communicatae in forma mappis.
BPF programmata certa certae programmatis nuclei adiutores currere permittuntur et functiones regulares recentius. Unumquodque munus vocatum capere potest quinque argumentis, in registris elapsis r1-r5ac reditus pretii est r0. Confirmatur quod post reditum ab officio contenta tabulariorum r6-r9 Non mutabitur.
Ad translationem programmatis efficiens, registra r0-r11 omnes enim architecturae fultae unice sunt descriptae ad veras tabulas, ratione habita ABI notarum architecturae hodiernae. Verbi gratia, x86_64 registra r1-r5, ad munus parametri transeundi, monstrantur rdi, rsi, rdx, rcx, r8, quae ad parametri functiones transire solebant x86_64. Exempli gratia, codicem a sinistra vertit ad codicem a dextra sic;
actis mandare r0 etiam proventus programmatis et in registro redire solebant r1 progressio monstratorem contextum reddit - secundum rationem programmatis, hoc esse potest, exempli gratia, structuram struct xdp_md (Nam XDP) seu structuram struct __sk_buff (Pro diversis network programs) seu structuram struct pt_regs (pro diversis generibus programmatum) etc.
Statutum igitur tabularum habuimus, adiutores nucleos, acervum, monstratorem contextus et memoriam in forma mappis communicavit. Non quod haec omnia absolute necessaria sint in itinere, sed...
Descriptio pergamus et loqui de systemate imperii in his rebus operandi. Omnis (Fere omnes) BPF 64- bit habent instructiones certam magnitudinem. Si unam disciplinam spectes super 64 frenum Big Machina Endian videbis
est Code β haec est descriptam instructionis; Dst/Src sunt descriptam accepti et principii respective; Off - 16-bit incisum signatum, et Imm est 32-bit signatus integer in quibusdam instructionibus (similis CBPF constanti K). modum translitterandi Code unum est duorum generum;
Instructiones classes 0, 1, 2, 3 definiunt praecepta ad memoriam operandam. They dicuntur, BPF_LD, BPF_LDX, BPF_ST, BPF_STXrespectively. Classes IV, VII.BPF_ALU, BPF_ALU64) ALU instructiones constituunt. Classes V, VI.BPF_JMP, BPF_JMP32) Mandata continent jump.
Ulterior ratio perscrutandi ratio instructionis BPF est haec: loco adamussim recensentes omnes instructiones earumque parametri, duo exemplorum in hac sectione videbimus et ex illis patebit quomodo instructiones actu operantur et quomodo. manually disassemble quolibet binario lima pro BPF. Ad materiam postea in articulo consolidandam, etiam singulis instructionibus occurremus in sectionibus de Verifier, JIT compilator, translatione classicorum BPF, tum cum mappis studens, functiones vocantes, etc.
Cum de singulis praeceptis loquimur, ad nucleum imaginum referemus bpf.h ΠΈ bpf_common.hquae definiunt instructiones numerales codicis BPF. Cum architecturae in tuo proprio et/vel binario parsing studeas, in sequentibus fontibus semanticos invenire potes, ordine multiplicitatis digestus: Priyatus eBPF spec, BPF et XDP Reference Guide, Instructio Set, Documentation/networking/filter.txt et quidem in codice fonte Linux - uerificante, JIT, BPF interprete.
Exempli gratia: disassembling BPF in caput tuum
Intueamur exemplum in quo programma componimus readelf-example.c et specta inde binarii. Nos originale contentus erit revelare readelf-example.c infra, postquam logicam suam ex codicibus binariis restituimus;
Imperio codes sunt pares b7, 15, b7 ΠΈ 95. Recole quod minimum significantes tres frusta sunt instructionis classis. In nobis, quarta pars omnium praeceptorum vacua est, ita instructio classes sunt 7, 5, 7, 5, respective. Classis 7 est. BPF_ALU64et 5 is BPF_JMP. Utraque enim forma instructio eadem est (vide supra), et programmata nostra sic rescribere possumus (simul reliquas columnas in forma humana scribemus);
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
operatio b class ALU64 - eam BPF_MOV. Pretium assignat ad locum desideratum. Si frenum est paro s tunc valorem ex tabulario fonte sumatur et si, ut in nobis est, non sit positum, tunc ex agro pretium accipitur. Imm. Sic ergo in prima et tertia instructiones operationis perficimus r0 = Imm. Praeterea, JMP operatio 1 classis est BPF_JEQ (Sil si aequalis). In nobis, cum bit S nulla est, valorem fontis mandare cum agro comparat Imm. Si valores coincidunt, transitus occurrit PC + Offquibus PCut solet, sequentis instructionis oratio continet. Denique JMP Classis IX Operatio est BPF_EXIT. Haec institutio propositum terminat, ad nucleum reverti r0. Novam columnam addamus tabulae nostrae;
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
Hoc commodiore forma scribere possumus:
r0 = 1
if (r1 == 0) goto END
r0 = 2
END:
exit
Si meminimus quid sit in actis mandare r1 programma monstratorem contextus e nucleo reddit et in registro r0 valor ad nucleum redditur, tunc videre possumus quod si monstrator contextus nullus est, tunc revertamur 1, et aliter - 2. Inspiciamus nos recte considerare principium;
Etiam programma vanum est, sed in quattuor simplices tantum instructiones vertit.
Exempli gratia: 16-byte disciplinam
Supra memoravimus nonnullas instructiones plusquam 64 frusta sumere. Hoc valet, verbi gratia, ad instructiones lddw (Codex = 0x18 = BPF_LD | BPF_DW | BPF_IMM) β duplici verbo ex agris in registro onerare Imm. Qui est punctus Imm Magnitudinem habet XXXII, et duplex sermo est 32 bits, qui statim valorem 64-bit levans in tabulario in uno 64 frenum instructio non operatur. Ad hoc faciendae duae instructiones adjacentes solent alteram partem valoris 64-obscenorum in agro recondere Imm. Exemplum:
Itaque binarii codices BPF legere didicimus et parati sumus ad aliquam instructionem si opus sit. Sed dignum est dicere in usu commodius et velocius programmata discurrere ut instrumenta normae adhibentes, exempli gratia:
(Primo didici quaedam de singulis in hoc ordine descriptis jejunium Alexei Starovoitov in BPF Blog.)
BPF objects - programs and maps - are created from user space using command BPF_PROG_LOAD ΠΈ BPF_MAP_CREATE ratio vocationis bpf(2)quomodo hoc in sequente articulo acciderit, exacte loquemur. Facit nucleos notitias structuras et pro unoquoque eorum refcount (reference count) positum est ad unum, et lima descriptor obiecto demonstrans usori redditur. Post manubrium clauditur refcount objectum ab uno reducitur, et cum nihilum pervenit, destruitur objectum.
Si progressio mappis utitur, tunc refcount hae mappae auctae singulatim onerata ratione, i.e. eorum documenti descriptores possunt claudi a user processum et adhuc refcount non fiet nulla;
Post feliciter programmata onerantes, eam ad aliquem generantis eventum pertinere solemus. Exempli causa, in retis interfaciem imponere possumus cum fasciculis advenientis vel cum aliquo connectere tracepoint in core. Hic, relatio contrarii etiam unum augebit et in programmate oneratus tabellam descriptorem claudere poterimus.
Quid fit, si iam caesus occlusus est? Genus eventus generantis dependet (hamo). Omnes uncini retis erunt postquam oneratus complet, hi uncini globalis sic dicti sunt. Et, exempli gratia, programmatis vestigium solvetur post processum qui eas terminat (et ideo locales vocantur, a "locus ad processum"). Technicaliter, unci locales semper respondentem fasciculi descriptor in spatio usoris habent et ideo claudunt cum processu clauso, at hami globalis non sunt. In sequenti figura, cruces rubras utens, ostendere conor quomodo terminationis oneris programma afficit objectorum in rebus localibus et in global hamis.
Quare distinctio uncinorum localium et globalum est? Currens nonnulla genera programmatum retis sensum sine usoris spatio facit, exempli gratia, finge praesidium DDoS - bootloader scribit regulas et programmata BPF coniungit cum retis interfaciei, post quae potest ire et occidere se. Contra, debugging vestigium programma finge, quod in genibus decem minutas scripseras - cum consummatum est, nihil coenum in systemate relictum esse velis, et loci hami id efficiet.
Ex altera vero parte, finge te velle cum nucleo in nucleo coniungere et statisticam per multos annos colligere. Hoc in casu, partem usoris absolvere velis et ad statisticam subinde redire. Ratio fasciculi bpf hanc occasionem praebet. In memoria solum pseudo- fasciculi ratio est quae creationem imaginum admittit quae referat BPF obiecta et ita auget refcount obiicit. Post hoc, oneratus potest exire, et res creatas viva remanebit.
Files creandi in bpffs quae referat obiecta BPF, "fibulare" dicitur (ut in sequenti locutione: "processus programmatis BPF vel tabulam suspendere potest"). File obiecta creans pro obiectis BPF sensum facit non solum ad vitam localium rerum amplificandam, sed etiam ad rerum globalium usabilitatem - rediens ad exemplum cum programmate tutelae globalis DDoS, venire ac intueri posse statisticas volumus. de tempore usque ad tempus.
The BPF file system is usually mounted in /sys/fs/bpfsed potest etiam localiter collocari, verbi gratia, sic;
$ mkdir bpf-mountpoint
$ sudo mount -t bpf none bpf-mountpoint
File systema nomina creantur per mandatum BPF_OBJ_PIN BPF ratio vocationis. Ad illustrandum, programma sumamus, componamus, fasciamus, figamus bpffs. Propositum nostrum nihil utile facit, tantum codicem exhibemus ut exemplum possis referre:
Nunc videamus programmata nostra utilitate utens bpftool et respice in comitante ratio vocat bpf(2) (lineae quaedam irrelevant a strace output remota):
Hic programmata oneravimus utendo BPF_PROG_LOAD, file descriptor ex nucleo accepit 3 ac per mandatum BPF_OBJ_PIN adfixum hoc file descriptor ut lima "bpf-mountpoint/test". Post haec progressio bootloader bpftool peractum opus, sed propositum nostrum in nucleo manebat, quamquam eam nulli interfaciei retis adiunximus;
$ 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
Non possumus delere quod lima Northmanni unlink(2) et postea programma respondente delebitur:
$ sudo rm ./bpf-mountpoint/test
$ sudo bpftool prog show id 783
Error: get by id (783): No such file or directory
Deletio obiecti
De obiectis deletis loquendo, declarare necesse est nos, postquam progressio ab hamo (evente generante disiungitur), ne unus novus eventus eius incussus erit, omnes tamen instantiae hodiernae programmatis in ordine normali complebuntur. .
Aliqua genera programmatum BPF permittunt te institutum in musca reponere, i.e. providere serie atomicity replace = detach old program, attach new program. In hoc casu, omnes instantiae activae veteris progressionis opus suum perficiet, et novus eventus tractatores ex novo programmate creabuntur, et "atomicitas" hic significat ne unus eventus omittatur.
Programs attachiando ad res fontes
In hoc articulo, programmata ad eventum fontes coniungentes separatim non describemus, cum sensum hoc in contextu certae rationis evolvamus. Cm. exempli gratia infra, in quo ostendemus quomodo programmata XDP connexa sint.
Manipulating res per bpf System Call
BPF programmata
Omnia BPF obiecta creantur et administrantur ex spatio usoris utens ratio vocationis bpfsequens prototypum habens;
#include <linux/bpf.h>
int bpf(int cmd, union bpf_attr *attr, unsigned int size);
Hic est dolor cmd est de valores generis enum bpf_cmd, attr - monstratorem parametri pro specifica progressio et size β object size according to the point, i.e. plerumque hoc sizeof(*attr). In nucleo 5.8 ratio vocationis bpf 34 alia imperia sustinet; definitionunion bpf_attr occupat CC lineas. Sed hoc non est perterritum, cum per plures articulos nosmetipsos praeceptis et parametris assuefaciamus.
Sit scriptor satus cum bigas BPF_PROG_LOAD, quae programmata BPF creat - copiam BPF mandatorum accipit et in nucleum onerat. In momento onerationis, verificator educitur, deinde JIT compilator et, postquam prospere exsecutionem egerit, programmata fasciculi descriptor ad usorem redditur. Quid ei contigerit proximo in sectione superiore vidimus de vita cycle obiecti BPF.
Nunc scribemus rationem consuetudinis quae simplex BPF programmata onerabit, sed primum diiudicare oportet qualem rationem onerare velimus - eligere debebimus genus et intra huius generis compagem scribe rationem, quae experimentum verificantis praeteribit. Attamen, ne processum inpediat, prompta solutio est hic: programma simile capiemus BPF_PROG_TYPE_XDPqui reddet valorem XDP_PASS (Omit omnes sarcinas). In BPF coadunator valde simplex spectat;
r0 = 2
exit
Post constituimus quod onerabimus, indicabimus tibi quomodo id faciamus;
Interestingly events in a programme incipe cum definitione exercitus insns - BPF programma nostrum in machina codice. Hoc in casu, unaquaeque institutio progressionis BPF in structuram referta est bpf_insn. Primum elementum insns prosequitur instructiones r0 = 2, secundus - exit.
Receptum. Acinum nuclei commodiores macros ad machinas scribendas definit, et fasciculi nuclei capitis usus tools/include/linux/filter.h potuimus scribere
Sed quia programmata scribentis BPF in codice patrio tantum necessarium est ad scripturas probationes in nucleo et articulos circa BPF, absentia horum macronum re vera vitam viae non inpediunt.
Ratione BPF definita, eam ad nucleum onerando movemus. Nostra minimalist paro parametri attr progressio includit genus, copia et numerus instructionum, licentia requiritur et nomen "woo"quam in programmate nostro reperiendi systema demptione utimur. Propositum, ut pollicitus est, in systemate vocationis utendi oneratur bpf.
In fine programmatis finimus in ansa infinita quae payload simulat. Sine ea progressio a nucleo interficietur cum descriptor tabellae quae ratio vocationis ad nos rediit clausa est bpfet non videbimus in ratione.
Bene parati sumus ad probationem. Sit scriptor progressio conveniunt et currere sub stracesisto quod omne opus est ut debet;
Omnia est bonum, bpf(2) rediit ansa 3 ad nos et ivimus in ansam infinitam cum pause(). Conemur invenire propositum nostrum in systemate. Ad hoc ad alium terminum ibimus et utilitate utimur bpftool:
Videmus programmata onusta in systematis esse woo cui global ID est CCCXC et est currently in progressu simple-prog non est aperta lima descriptor monstrans progressio (et si simple-prog consummans officium, tum woo peribit). Ut malesuada progressio woo bytes - duas instructiones - ex codicibus binariis in architectura BPF sumit, sed in forma nativi (x16_86) iam 64 bytes est. Intueamur propositum nostrum in forma originali;
non miror. Nunc videamus codicem a JIT compilator genitum:
# 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
non est valde efficax exit(2)sed in aequitate nimis simplex programma nostra est, et pro non levibus programmatibus prologus et epilogus a JIT compilator additi sunt, utique necessarii.
Maps
BPF programmata memoriae structurae locis uti possunt, quae pervia sunt tum aliis programs BPF et programmata in spatio usoris. Res mappae dictae sunt et in hac sectione ostendemus quomodo ea tractandi utens ratio vocationis bpf.
Dicamus statim facultates tabularum non limitari solum ad accessum ad memoriam communem. Exstant mappae speciales quae continentes, exempli gratia, monstratores programmatis BPF vel indicibus retis interfaces, mappas operandi cum rebus pert, etc. Nolumus hic loqui, ne lectorem confundamus. Praeter haec, quaestiones synchronisationum neglegimus, cum exempla nostris non magni momenti sint. A list of available map types can be found in <linux/bpf.h>atque in hac sectione exemplum primi generis historice, tabulae detrahendae adhibebimus BPF_MAP_TYPE_HASH.
Nullam mensam si facias, inquis, C++, dicas unordered_map<int,long> wooQuod in Russian significat "mensam opus" woo immensa magnitudine, cuius claves typus sunt intac valores generis sunt long" Ad mensam detrahendam BPF, necesse est nos multum idem facere, praeterquam quod magnitudinem maximam tabulae denotare debemus et pro specierum clavium et valorum specificando . Ad partum uti imperium maps BPF_MAP_CREATE ratio vocationis bpf. Inspice programmata plus minusve minima quae chartam geographicam creat. Post priorem rationem quae programmata BPF onerat, hic tibi simplex videri debet:
Hic definimus ambitum parametri attr, in qua dicimus "necessarium mensam cum clavibus et valore quantitatis" sizeof(int)in quibus maximum quattuor elementorum ponere possum. Cum tabulas BPF creans, alios parametros exprimere potes, exempli gratia, eodem modo ac in exemplo programmatis, nomen obiecti quod designamus. "woo".
Hic est ratio vocationis bpf(2) nobis reddidit descriptor numerus map 3 deinde programma, ut expectatur, ulteriores instructiones in vocatione systematis observat pause(2).
Nunc propositum nostrum ad curriculum vel ad terminum alium aperiendum mittamus et rem nostram utilitate utentem intueamur bpftool (mappa nostra ab aliis nomine suo distinguere possumus);
$ sudo bpftool map
...
114: hash name woo flags 0x0
key 4B value 4B max_entries 4 memlock 4096B
...
Numerus 114 est global ID obiecti nostri. Aliqua programma in systematis uti potest hoc ID ad aperiendum tabulam existentem utens mandatum BPF_MAP_GET_FD_BY_ID ratio vocationis bpf.
Nunc cum nostra Nullam mensam ludere possumus. Intueamur contenta:
$ sudo bpftool map dump id 114
Found 0 elements
Vacua. Let's put a value in it hash[1] = 1:
$ sudo bpftool map update id 114 key 1 0 0 0 value 1 0 0 0
Intueamur ad mensam iterum:
$ sudo bpftool map dump id 114
key: 01 00 00 00 value: 01 00 00 00
Found 1 element
euge! Unum elementum addere potuimus. Nota nos laborare in gradu byte ad hoc faciendum, quia bptftool Nescit cuius generis bona in tabula fascia sint. (Scientia haec ad usum BTF transferri potest, sed nunc plura.
Quam exacte bpftool legit et elementa addit? Vide sub cucullo:
Primum tabulam aperuimus a suo globali ID usura imperio BPF_MAP_GET_FD_BY_ID ΠΈ bpf(2) rediit descriptor III nobis. Praeterea per imperium BPF_MAP_GET_NEXT_KEY invenimus primam clavem in mensa transeundo NULL ut monstrator "prior" clavis. Si habent clavem facere possumus BPF_MAP_LOOKUP_ELEMquae refert ad valorem monstratorem value. Proximum gradum conamur invenire proximum elementum transeunte monstratorem ad clavem currentem, sed mensa nostra unum tantum elementum continet ac mandatum. BPF_MAP_GET_NEXT_KEY redit ENOENT.
Sicut expectatur, valde simplex est: mandatum BPF_MAP_GET_FD_BY_ID aperit tabulam nostram per ID, et mandatum BPF_MAP_UPDATE_ELEM elementum overwrites.
Itaque, mensa Nullam ab uno programmate creando, ex alio contenta legere et scribere possumus. Nota quod si ex linea recta facere potuimus, tunc quodlibet aliud propositum in ratione facere potest. Praeter praecepta supra scripta, ad operandum cum mappis ex spatio usoris; haec:
BPF_MAP_LOOKUP_ELEM: Invenire valorem per clavem
BPF_MAP_UPDATE_ELEM; Renovatio / valorem creare
BPF_MAP_DELETE_ELEM: Aufer clavem
BPF_MAP_GET_NEXT_KEY: Invenies altera (vel prima) clavis
BPF_MAP_GET_NEXT_ID: permittit te ire per omnes mappas existentes, id est quomodo operatur bpftool map
BPF_MAP_GET_FD_BY_ID: Aperire tabula existentium in global ID
BPF_MAP_LOOKUP_AND_DELETE_ELEM: Atomically update ad valorem obiecti et revertetur ad senem
BPF_MAP_FREEZE; Fac tabula immutabilis a userspace (hoc operandi infectum non potest)
BPF_MAP_LOOKUP_BATCH, BPF_MAP_LOOKUP_AND_DELETE_BATCH, BPF_MAP_UPDATE_BATCH, BPF_MAP_DELETE_BATCH: massa operationes. Exempli gratia BPF_MAP_LOOKUP_AND_DELETE_BATCH - Haec unicus modus certa est ut omnes valores e charta legendi et reset
Non omnia mandata haec omnia operantur pro omnibus generibus tabularum, sed in generali operando cum aliis mappis ex spatio usoris, prorsus idem spectat ac opus cum tabulis Nullam.
Propter ordinem, experimenta mensa Nullam finiamus. Memento nos mensam creavisse quae quattuor claues continere potest? Pauca plura addamus elementa;
$ 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
Ut expectatur, non successit. Intueamur errorem planius;
$ 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 +++
Omnia denique sunt: ββut expectatur, manipulus BPF_MAP_UPDATE_ELEM novum, quintum, clavem creare conatur, sed fragores E2BIG.
Ita, BPF programmata creare et onerare possumus, ac tabulas ex spatio usoris creare et administrare. Iam spectare logicum est quomodo ex ipsis BPF programmatibus mappis uti possumus. De hac re loqui potuimus in programmatibus difficile-ad-lectus in codicibus machinae tortoribus, sed tempus venit ut ostenderet quomodo programmata BPF re vera scripta et conservata sint - utens libbpf.
(Ad lectores qui inopia exempli humili gradu displicent: in speciali programmata resolvemus quae mappis utentibus et functionibus auxiliatoribus utentibus creatis utuntur. libbpf et dicam tibi, quod ad instructionem attinet. Pro lectoribus displicent maleAddimus exempli gratia suo loco in articulo).
Scribens BPF programs utens libbpf
BPF scribens programmata machinae in codicibus utens primum modo interesting esse potest, deinde satietas oritur. Nunc opus est ut animum ad llvmquae habet backend ad codicem generandi pro architectura BPF, necnon bibliothecae libbpf, quod permittit tibi scribere applicationes usoris BPF et codicem programmatum BPF generatorum utens onerare llvm/clang.
Nam, ut in hoc et subsequentibus articulis videbimus; libbpf non satis multum opus est sine qua (vel instrumenta similia - iproute2, libbcc, libbpf-goImpossibile est vivere. Una interfectorem features project libbpf est BPF CO-RE (Compile Semel, Curre Ubique) - consilium quod permittit tibi libellos BPF scribere, qui ab uno nucleo in alterum portabiles sunt, cum facultate currere in diversis APIs (exempli gratia, cum structura nuclei mutatur ex versione. to version). Ut cum CO-RE laborare possit, nucleus tuus cum subsidio BTF componendus est (describimus quomodo hoc in sectione facere possit. Progressio Tools. Potes inspicere utrum nucleus tuus cum BTF sit constructus vel non admodum simpliciter - praesente fasciculo sequenti:
Hic fasciculus informationum de omnibus notitiarum generibus in nucleo usus est et in omnibus nostris exemplis adhibetur libbpf. Singillatim loquemur de CO-RE in sequenti articulo, sed in hoc uno - modo aedifica te nucleum cum CONFIG_DEBUG_INFO_BTF.
library libbpf recte vivit in indicem tools/lib/bpf nucleus eiusque progressus per tabulas tabellariorum exercetur [email protected]. Repositorium autem separatum servatur pro necessitatibus applicationum extra nucleum viventium https://github.com/libbpf/libbpf in quo plus minusve ac minus acinum bibliotheca praevisa est.
In hac sectione videbimus quomodo project usus creare possit libbpfplura scribere (plus minusve vanum) programmata experiri et quomodo omnia opera enucleare in singillatim. Id nos in sequentibus sectionibus accuratius exponere facilius licebit, quam BPF programmata cum mappis, adiutoribus nucleis, BTF, etc.
Typice uti projects libbpf adde repositorium GitHub pro submodule git, eadem faciemus;
Proximum consilium in hac sectione tale est: scribemus programmata BPF BPF_PROG_TYPE_XDPeaedem ac in exemplo praecedente, sed in C, compilata ea utendo clanget scribe programmata adiutoria quae eam in nucleum onerabunt. In sequentibus sectionibus capacitates utriusque programmatis BPF et programmatis adiutoris augebimus.
Exempli gratia: creando plena application usura libbpf
In primis utimur tabella /sys/kernel/btf/vmlinuxde quo supra dictum est, et eius modi in modum tituli;
$ bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h
Hic fasciculus omnia notitiarum structurarum in nucleo nostro promptas recondet, exempli gratia, hoc modo IPv4 capitis in nucleo definitur:
Etsi programma nostra admodum simplex evasit, multa tamen opera attendere oportet. Primum, fasciculi primi tituli includuntur is vmlinux.h, qua modo generata utens bpftool btf dump - Nunc non opus est sarcinam capitis nuclei instituere ad explorandum quid structurae nuclei simile videant. Sequens fasciculus header ad nos ex bibliotheca venit libbpf. Nunc non nisi eget tortor definire SECqui characterem mittit ad aptam sectionem fasciculi ELF rei. Propositum nostrum in sectione continetur xdp/simple, ubi ante exactivationem generis BPF definimus programma - hoc est placitum in " libbpf, ex nomine sectionis rectam rationem substituet apud startup bpf(2). Programma ipsum BPF est C - simplex valde et in una linea consistit return XDP_PASS. Denique sectionem separatam "license" nomine licentiae continet.
Possumus programmata nostra componere utendo llvm/clang, versione >= 10.0.0, vel adhuc melius, maius (vide sectionem Progressio Tools):
Inter interesting lineamenta: scopum architecturae indicamus -target bpf et iter ad capitis libbpfquas nuper inauguavimus. Etiam, nolite oblivisci -O2sine hac optione sitis in improviso. Inspice codicem nostrum, nonne nos programmata scribere voluimus?
Etiam laboravi! Nunc fasciculum binarium cum programmatis habemus, et applicationem creare volumus quae eam in nucleum onerabunt. Ad hoc bibliothecam libbpf nobis duas optiones praebet - inferiore gradu API vel gradu superiore API utere. Secundum viam ibimus, quia discere volumus quomodo scribere, onera et programmata BPF coniungere minimo conatu pro eorum studio sequentem.
Primum, "sceleton" institutionis nostrae e binario utendo eadem utilitate generare oportet bpftool β Helvetica omitta mundi BPF (quod proprie accipi potest, cum Daniel Borkman, unus e auctoribus et assertoribus BPF, Helvetius est);
$ bpftool gen skeleton xdp-simple.bpf.o > xdp-simple.skel.h
In file xdp-simple.skel.h Codex binarii institutionis nostrae ac functiones continet ad rem nostram administrandam, onerandam, adnectendam, delendam. In nostro simplici casu haec species overkill, sed etiam operatur in casu ubi res fasciculi plures BPF programmata et tabulas continet et ad hunc gigantem ELF onerandum nos solum sceletum generare oportet et unam vel duas functiones ex applicatione consuetudinis appellamus. scribimus Eamus nunc.
Proprie loquendo, programmata oneratus nostra levis est;
#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);
}
est struct xdp_simple_bpf definitur tabella xdp-simple.skel.h et describit rem nostram file:
Vestigia humili gradu API hic videre possumus: structuram struct bpf_program *simple ΠΈ struct bpf_link *simple. Prima structura nominatim describit propositum nostrum, in sectione scriptum xdp/simpleet secunda describit quomodo progressio ad eventum rei pertinet.
munus xdp_simple_bpf__open_and_load, objectum ELF aperit, parsit, omnes structuras ac substructiones creat (praeter rationem, ELF alias sectiones etiam continet - datas, datas, notitias, debugging informationes, licentiam, etc.), eamque onerat in nucleum systematis utendi. vocatus bpfquam a scribendis ac currendi rationibus inhibere possumus;
Nunc inspice programmata nostra utens bpftool. Id inveniamus eam:
# 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)
ac TUBER (utimur forma praecepti correpta bpftool prog dump xlated):
# bpftool p d x id 463
int simple(void *ctx):
; return XDP_PASS;
0: (b7) r0 = 2
1: (95) exit
Aliquid novi! Programma impressum chunks nostri C, fons lima. Hoc factum est in bibliotheca libbpfquae sectionem debug in binario invenit, eam in objecto BTF compilavit, eam in nucleum utens. BPF_BTF_LOAD, ac deinde descriptor limam inde speciem cum programmate oneret cum imperio BPG_PROG_LOAD.
Kernel Adiutores
BPF programmata munera "externa" - adiutores nuclei currere possunt. Munera auxiliatrix haec permittit programmata BPF ad structuras nucleos accedere, mappas administrare et etiam cum "rei mundi" communicare - eventus perf creare, ferramenta moderari (exempli gratia, fasciculas redirectas) etc.
Exemplum: bpf_get_smp_processor_id
Intra "exemplum discendi" paradigma consideremus unum munerum adiutorium; bpf_get_smp_processor_id(), quidam in file kernel/bpf/helpers.c. Redit numerus processus in quem BPF programmatis currit qui vocatur. Sed non sicut in semanticis, sicut in eo quod exsequendum est unam lineam;
In BPF adiutorii functiones definitiones sunt similes definitionibus systematis Linux vocatis. Hic, exempli gratia, munus definitur nullas rationes habere. ( Munus quod sumit, inquam, tribus argumentis utens macro definitur BPF_CALL_3. Argumentorum numerus maximus est quinque.) Sed haec prima pars est tantum definitionis. Secunda pars est genus structurae definire struct bpf_func_protoquae descriptionem continet functionis adiutoris quod verificantis intelligit;
Ut programmata alicuius generis BPF hoc munere utantur, illud subcriptio, exempli gratia pro typ BPF_PROG_TYPE_XDP munus definitur in nucleo xdp_func_protoquae ab adiutorio functionis ID decernit utrum XDP hoc munus sustineat necne. Munus nostrum est fusiles:
Novae BPF programmatis rationes "definiuntur" in tabella include/linux/bpf_types.h usus tortor BPF_PROG_TYPE. In sententiis definitur quia definitio logica est, et in C verbis definitio totius certae structurarum concretarum occurrit alibi. Praesertim in tabella kernel/bpf/verifier.c omnes definitiones ex file bpf_types.h sunt creare aciem structurarum bpf_verifier_ops[]:
Hoc est, ad singulas rationes programmatis BPF, monstratorem ad structuram datam speciei definiendam esse struct bpf_verifier_opsquae initialized cum valore _name ## _verifier_ops, i.e. xdp_verifier_ops ad xdp. Structure xdp_verifier_opsproposuerunt singuli in file net/core/filter.c ut sequitur:
Nota munus nostrum hic videmus xdp_func_proto, quae in verificantem quoties incurrit provocationem current aliquid functiones intra BPF programma, vide verifier.c.
Intueamur quomodo hypothetica BPF progressio munere utitur bpf_get_smp_processor_id. Ad hoc propositum ex praecedenti sectione rescribimus hoc modo:
ille est, bpf_get_smp_processor_id est functio monstratoris cuius valor 8, ubi valor VIII est BPF_FUNC_get_smp_processor_id genus enum bpf_fun_idquae nobis in tabella definita est vmlinux.h (file bpf_helper_defs.h in nucleo scripto generatur, sic numeri "magici" ok sunt. Hoc munus non accipit rationes et valorem generis reddit __u32. Cum in programmate illo curritur; clang generat disciplinam BPF_CALL "jus genus" Progressio et respice in sectione Lets ordinare xdp/simple:
In prima linea videmus mandatum call, parameter IMM = 8 = SRC_REG β nulla. Secundum pactum ABI a uerificante adhibitum, haec vocatio ad munus adiutorium est numerus octonarius. Semel emittitur, logica simplex est. Redi valorem ex mandare r0 copied to r1 et in lineis 2,3 convertitur ad typus u32 β Superiores 32 frena purgantur. In lineis 4,5,6,7 redimus 2 (XDP_PASS) Seu I (XDP_DROP) pendens sive munus adiutorium ex linea 0 nullum valorem vel non-nullam reddidit.
Experiamur ipsi: oneramus rationem et vide in output 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
Ok, uerificans rectam nucleum adiutorem invenit.
Exempli gratia: rationes praetereundo ac tandem progressio currit!
Omnes currunt-gradu adiutorium functiones habent exemplar
u64 fn(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
Parametri ad munera adiuvantis in regestis transeunt r1-r5et valorem in registro redditur r0. Nullae sunt functiones quae plusquam quinque rationes capiant, earumque subsidia in posterum addi non expectatur.
Inspice nucleum novum adiutorem et quomodo parametri BPF transit. Lets RESCRIBO xdp-simple.bpf.c ut sequitur (reliquae lineae non mutatae sunt);
SEC("xdp/simple")
int simple(void *ctx)
{
bpf_printk("running on CPU%un", bpf_get_smp_processor_id());
return XDP_PASS;
}
Programma nostrum imprimit numerum CPU in quo currit. Let's compilare et inspicere in codice:
In lineis 0-7 scribimus chorda running on CPU%unet deinde in linea 8 notum cucurrimus bpf_get_smp_processor_id. In lineis 9-12 paramus argumenta adiutoria bpf_printk - registra r1, r2, r3. Cur tres eorum et non duo sunt? Quod bpf_printk - hoc est tortor serratus circum verus adiutor bpf_trace_printkquae ad magnitudinem chordae format.
Nunc adde duas lineas to xdp-simple.cut programma nostra interface coniungat lo et vere incepit!
Munus hic utimur bpf_set_link_xdp_fdquae programs XDP-type BPF coniungit cum interfaces retis. Nos interface hardcoded numerus losemper, 1. Currimus bis munus prius abducere institutum veterem si adicitur. Animadverte nunc nos provocatione non indigere pause vel ansa infinita: programmata oneratus noster exit, sed programmata BPF non interficietur cum eventui fonte coniungitur. Post opportunam download et connexionem, programma mittetur ad unumquemque fasciculum retis perveniens lo.
Progressio Lets download et vide ad interface lo:
$ sudo ./xdp-simple
$ sudo bpftool p | grep simple
669: xdp name simple tag 4fca62e77ccb43d6 gpl
$ ip l show dev lo
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 xdpgeneric qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
prog/xdp id 669
Progressio nos downloaded ID 669 ac idem videmus in interface lo. Nos mittemus a duobus packages to 127.0.0.1 (postulatio + responsum);
$ ping -c1 localhost
Et nunc videamus de contentis debug virtualis lima /sys/kernel/debug/tracing/trace_pipe, in quibus bpf_printk scribit epistulas suas:
# 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
Duo sunt maculosus packages lo et processit in CPU0 - primum nostrum progressionis plenae vacuae vanitati BPF operatae!
Notatu dignum est bpf_printk Non nihil est quod ad tabellam debug scribit: hoc adiutrix non est felicissima ad usum in productione, sed propositum est aliquid simplex ostendere.
Accessing maps from BPF programs
Exempli gratia: per chartam geographicam ex programmatis BPF
In sectionibus superioribus didicimus tabulas ex spatio usoris creare et uti, et nunc partem nuclei inspiciamus. Incipiamus, ut soles, exemplo. Sit scriptor progressio auctas xdp-simple.bpf.c ut sequitur:
In principio progressionis tabulam definitionis addimus woo: Hoc est 8-elementum ordinatum quod valores addit similes u64 (in C definiamus talem aciem u64 woo[8]). In programma "xdp/simple" nos adepto current processus numerus in variabilis key et utens adiutorium munus bpf_map_lookup_element monstratorem dabimus ad congruentem ingressum in ordine, quem per unum augemus. Translata in Russicam: statistas computamus quibus CPU fasciculi advenientes processit. Progressio scriptor experiri currere:
Let's check that she's hook up to lo et mitte fasciculos:
$ 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
Fere omnes processus in CPU7. Hoc nobis non interest, summa res est ut opera programmatis et intelligamus quomodo ad tabulas accessus ex programmatibus BPF - utendo. Ρ Π΅Π»ΠΏΠ΅ΡΠΎΠ² bpf_mp_*.
Mysticus index
Itaque ad tabulam accedere possumus e programmatis BPF utendi vocat sicut
$ 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
Sed si programmata iam onerata spectemus, monstratorem tabulae rectae videmus (line 4);
Ita concludere possumus quod in tempore deductionis nostrae programmatis oneratis ligamen to &woo successit aliquid cum bibliotheca libbpf. Primum nos te intueri output strace:
Quod videmus libbpf creatus est tabula woo et nostri progressio downloaded simple. Propius inspiciamus quomodo programmata oneremus:
vocatus xdp_simple_bpf__open_and_load ex file xdp-simple.skel.h
quae causas xdp_simple_bpf__load ex file xdp-simple.skel.h
quae causas bpf_object__load_skeleton ex file libbpf/src/libbpf.c
quae causas bpf_object__load_xattr ex libbpf/src/libbpf.c
Munus ultimum, inter alia, vocabo bpf_object__create_mapsquae tabulas exsistentes creat vel aperit, eas in descriptores tabellarios convertens. (Hoc est ubi videmus BPF_MAP_CREATE in output strace.) Deinde munus appellatur bpf_object__relocate nobisque ipsa est, cum meminimus quae vidimus woo in relocation mensa. Id explorantes, tandem in munere versamur bpf_program__relocate, quod " agit cum tabula relocations:
case RELO_LD64:
insn[0].src_reg = BPF_PSEUDO_MAP_FD;
insn[0].imm = obj->maps[relo->map_idx].fd;
break;
ac reponere fons mandare in ea cum BPF_PSEUDO_MAP_FDet primo IMM tabellae geographicae nostrae descriptor, si aequalis est, e.g. 0xdeadbeefergo ex hoc recipiemus disciplinam
18 11 00 00 ef eb ad de 00 00 00 00 00 00 00 00 r1 = 0 ll
Ita est quam tabula geographica ad certas rationes oneratas BPF transfertur. Hoc in casu, tabula utens creari potest BPF_MAP_CREATEEt aperitur per id utens BPF_MAP_GET_FD_BY_ID.
Totalis, cum usura libbpf algorithmus talis est;
in compilatione, monumenta creantur in relocatione mensa pro nexus ad chartas
libbpf ELF librum objectum aperit, omnes usus tabulas invenit et tabella descriptores pro illis creat
file descriptores oneratur in nucleo ut pars instructionis LD64
Ut credis, plus est venire et inspicere in nucleum debebimus. Fortunate sensum habemus - scripsimus significationem BPF_PSEUDO_MAP_FD in fonte registro sepelire possumus, quai nos ad sanctorum omnium sanctorum -. kernel/bpf/verifier.c, ubi munus cum nomine insignito reponit descriptor cum inscriptione structurae typus struct bpf_map:
(Potest plenam codice inveniri Link). Ita dilatare possumus algorithmum nostrum:
dum programmata levat, uerificans recto usu chartae impedit et inscriptione structurae respondentis scribens struct bpf_map
Cum downloading ELF binarii usura libbpf Plus multum agitur, sed in aliis articulis disseremus.
Loading programs and maps without libbpf
Promissum, hic exemplum est lectoribus qui scire volent rationem creare et onerare programmata mappis utitur, sine auxilio libbpf. Hoc esse utile potest cum in ambitu laboras pro quo clientelas aedificare non potes, vel singulas particulas salvas, vel programmata scribens similia. plygenerans BPF codicem in musca.
Ut facilius logicam sequamur, exemplum nostrum ad haec proposita rescribemus xdp-simple. Codex programmatis perfectus et leviter expansus in hoc exemplo reperiri potest SUMMA.
Ratio applicationis nostri talis est:
creare genus tabula BPF_MAP_TYPE_ARRAY per imperium BPF_MAP_CREATE,
creare programma quo hac tabula utitur;
progressio ad coniungere interface lo,
quae vertit in humana as
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);
}
est map_create tabulam facit eodem modo sicut nos in primo exemplo de ratione vocationis bpf - "nucleus, quaeso, fac mihi novam tabulam in forma ordinatae 8 elementorum sicut " __u64 et redde mihi tabella descriptor";
Capta pars prog_load Est definitio nostrae BPF progressio, ordinata structurarum struct bpf_insn insns[]. Sed quia programmate utimur quod in C habemus, possumus aliquantulum fallere;
Exercitium pro eis qui hoc ipsi non scripserunt map_fd.
Una pars magis clausa in programmate nostro relinquitur. xdp_attach. Infeliciter, programmata quasi XDP coniungi non possunt utens ratio vocationis bpf. Homines, qui BPF et XDP creaverunt, erant ex communitate Linux online, quod ea maxime familiari utebantur (non autem ut normalis " people) interface for interacting cum nucleo; netlink bases, vide quoque RFC3549. Simplicissima via ad effectum deducendi xdp_attach exscribend testatem codice e libbpfscilicet ex tabella netlink.cquod est illud quod fecimus, breve illud breviando;
Welcome to the world of netlink bases
Aperire netlink ostium tabernaculi genus 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;
}
Ab hoc nervum legitur:
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;
}
Denique hic munus nostrum est quod nervum aperit et peculiarem nuntium mittit ei qui descriptorem fasciculi continet;
$ 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
Eia, opera omnia. Nota obiter, quod tabula nostra iterum in forma bytes ostenditur. Hoc ex eo quod dissimilis libbpf type informationes non oneratis (BTF). Sed de hoc proximo tempore plura loquemur.
Progressio Tools
In hac sectione spectabimus minimum toolkit BPF elit.
Generaliter, non indigetis speciali ad programmata BPF explicanda - BPF incurrit in quamlibet honestam distributionem nuclei, et programmata utendo aedificantur. clangquae ex sarcina suppleri potest. Attamen, ob hoc quod BPF sub progressione est, nucleus et instrumenta perpetuo mutantur, si nolis scribere programmata BPF utentes methodi antiqui ex MMXIX, tum scribere debebis.
llvm/clang
pahole
et core
bpftool
Debian 10.
llvm/clang
BPF amica est cum LLVM et, quamvis nuper programmata BPF utens gcc componi possit, omnis progressio pro LLVM exercetur. Itaque in emendatione ante omnia aedificabimus clang ex git:
(Conventus instructions clang capta est a me bpf_devel_QA.)
Programmata quae modo aedificavimus non instituemus, sed eos mox adiciemus PATHFor example:
export PATH="`pwd`/bin:$PATH"
(Hoc potest addi .bashrc aut file separatum. Personaliter haec addo similia ~/bin/activate-llvm.sh et, cum opus sit, id faciam . activate-llvm.sh.)
Pahole et BTF *
utilitas pahole usus est cum aedificaretur nucleus ad creandum debugging informationes in BTF forma. In hoc articulo de singulis technologiarum BTF non descendemus, nisi quod commodum est ac volumus uti. Si ergo tu acturus es nucleum tuum, primum aedifica pahole (sine pahole nucleum cum optione aedificare non poteris 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 ad experimentum cum BPF
Cum facultates BPF explorans, nucleum meum convenire volo. Hoc, generaliter loquendo, non est necessarium, quia in distributione nuclei programmata BPF scribere et onerare poteris, tamen nucleum proprium habendo te permittit uti notissimis BPF notis, quae in mensibus maxime apparebit in distributione. aut, ut in quibusdam instrumentis debuggingis, in praevisis futuris omnino non coniciatur. Etiam, nucleus suus, gravem experimentum facit cum codice.
Ad nucleum aedificandum opus est, primum ipsum nucleum, deinde fasciculi nuclei conformationem. Experiri cum BPF uti possumus vanilla nucleo, vel uno nucleo evolutionis. Historice, BPF progressio intra communitatem retis Linux fit ac propterea omnes mutationes citius aut serius per David Miller, Linux conservatorem retis, perveniunt. Secundum naturam earum - emendationum vel novarum notarum - retis mutationes in unum e duobus nucleis cadunt - net aut net-next. Mutationes pro BPF eodem modo distributae sunt bpf ΠΈ bpf-nextquae dein in retia et reticula conduntur, respective. For more details, see bpf_devel_QA ΠΈ netdev-FAQ. Sic nucleum elige in tuo gustu ac firmitate necessitates systematis quam probatis (*-next eorum levissimi nuclei enumerantur).
Extra ambitum huius articuli loqui est quomodo nuclei figurarum imaginum regendi - assumitur te aut hoc facere iam scis. paratus ad discere de proprio. Nihilominus, hae instructiones plus minusve sufficiant ut systema operanti BPF-efficiatur.
Download unum ex nucleis supra:
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git
$ cd bpf-next
Aedificare minimam operationem nucleo config:
$ cp /boot/config-`uname -r` .config
$ make localmodconfig
Admitte BPF options in file .config de tua electione (verisimile CONFIG_BPF iam praestabitur quia systemd illo utitur). Hic index optionum ex nucleo pro hoc articulo usus est:
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
Deinde facile modulos ac nucleos convenire et instituere (obiter nucleum uti recenti conglobato colligere potes. clangper addendo CC=clang):
$ make -s -j $(getconf _NPROCESSORS_ONLN)
$ sudo make modules_install
$ sudo make install
ac reboot cum nova nucleo (utar hoc kexec ex sarcina kexec-tools):
Frequentissima utilitas in articulo erit utilitas bpftoolpartem Linux nucleo supplevit. Legitur et conservatur a tincidunt BPF pro tincidunt BPF et adhiberi potest ad omnia genera objectorum BPF - programmata oneranda, mappas crea et recensendas, vitam BPF ecosystem explorandum, etc. Documenta in forma principii codicis pro homine paginae inveniri possunt in core vel, compilata; ad network.
In tempore scripturae huius bpftool ad RHEL, Fedora et Ubuntu tantum parata venit (vide, v. gr. hoc filum, qui narrat inchoatam fabulam packaging bpftool in Debian). Si autem iam acinum struxisti, tunc aedifica bpftool tam facile quam 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 ]
$
(hic ${linux} - Hoc presul est nucleus tuus.) His peractis mandata bpftool colligentur in Directory ${linux}/tools/bpf/bpftool et adiicere potest ad viam (primum omnium ad usoris root) Vel iustus effingo to /usr/local/sbin.
Collecta bpftool suus 'optimus ut hoc clangconvenerunt ut supra dictum est, deprime an recte, utendo, verbi gratia, mandato
$ 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
...
quod ostendet quae lineamenta BPF in nucleo tuo valeant.
Praecedens praeceptum currere potest obiter
# bpftool f p k
Hoc fit per similitudinem cum utilitatibus e sarcina iproute2ubi possumus, e.g ip a s eth0 pro ip addr show dev eth0.
conclusio,
BPF sinit te culicem calceamere ut efficaciter metiaris et in musca mutet functionem nuclei. Systema egregie evenit in optimis traditionibus UNIX: mechanismum simplex, qui te permittit ut programmata nuclei ingentem numerum hominum et consociationum ad experimentum recipiant. Et, licet experimenta, sicut etiam progressio infrastructurae BPF, absunt ab perfectae, ratio iam stabilis ABI permittit ut certa condere, ac potissimum, logica negotia effectiva.
Vellem notare, mea sententia, technicae artis popularis facta esse quod, ex una parte, potest ludere (architectura machinae una vespera plus minusve intelligi potest), et ex altera parte, quaestiones solvendas quae ante suam speciem (pulchre) solvi non possunt. Haec duo membra simul cogunt homines ad experimentum et somnium, quod ad exitum solutionum magis ac magis eget.
Articulus hic, etsi non proprie brevis, tantum prooemium est ad mundum BPF et notas "progressus" et partes architecturae non describit. Propositum progressus est simile hoc: proximus articulus erit perspectus generum programmatis BPF (sunt 5.8 genera programmatis in 30 nucleo suffulta), tunc demum spectabimus quomodo scribenda sint applicationes reales BPF utentes nucleo typum ducens. ut exemplum, tempus est ad altiorem cursum in architectura BPF, quam exempla BPF retis et applicationis securitatis secuti sunt.
BPF et XDP Reference Guide β Documenta de BPF e cilio, vel accuratius ex Daniele Borkman, uno ex auctoribus et assertoribus BPF. Haec una est ex primis gravium descriptionibus, quae ab aliis discrepat, quod Daniel prorsus novit quid scribat, et nulla ibi errata sunt. Praesertim hoc documentum describit quomodo operari cum BPF programmata XDP et TC specierum notae utilitatis utentes. ip ex sarcina iproute2.
Documentation/networking/filter.txt β fasciculus originalis cum documentis pro classicis et deinde extensis BPF. Bona lege, si vis in conventum linguam et singulas architecturas technicas ingredi.
Blog about BPF from facebook. Raro renovatur, sed apte, ut Alexei Starovoitov (auctor eBPF) et Andrii Nakryiko - (contentor) ibi scribunt. libbpf).
Secreta bpftool. Delectatio twitter filo Quintini Monnet cum exemplis et arcanis utendi bpftool.