BPF Π·Π° Π½Π°ΠΉ-ΠΌΠ°Π»ΠΊΠΈΡ‚Π΅, част ΠΏΡŠΡ€Π²Π°: Ρ€Π°Π·ΡˆΠΈΡ€Π΅Π½ BPF

Π’ Π½Π°Ρ‡Π°Π»ΠΎΡ‚ΠΎ имашС тСхнология ΠΈ сС казвашС BPF. ΠŸΠΎΠ³Π»Π΅Π΄Π½Π°Ρ…ΠΌΠ΅ я ΠΏΡ€Π΅Π΄ΠΈΡˆΠ΅Π½, статия Π·Π° Бтария Π·Π°Π²Π΅Ρ‚ ΠΎΡ‚ Ρ‚Π°Π·ΠΈ сСрия. ΠŸΡ€Π΅Π· 2013 Π³. с усилията Π½Π° АлСксСй Π‘Ρ‚Π°Ρ€ΠΎΠ²ΠΎΠΉΡ‚ΠΎΠ² ΠΈ Π”Π°Π½ΠΈΠ΅Π» Π‘ΠΎΡ€ΠΊΠΌΠ°Π½ бСшС Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Π΅Π½Π° Π½Π΅Π³ΠΎΠ²Π° ΠΏΠΎΠ΄ΠΎΠ±Ρ€Π΅Π½Π° вСрсия, ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€Π°Π½Π° Π·Π° ΡΡŠΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΈ 64-Π±ΠΈΡ‚ΠΎΠ²ΠΈ машини, която бСшС Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Π° Π² ядрото Π½Π° Linux. Π’Π°Π·ΠΈ Π½ΠΎΠ²Π° тСхнология бСшС Π½Π°ΠΊΡ€Π°Ρ‚ΠΊΠΎ Π½Π°Ρ€Π΅Ρ‡Π΅Π½Π° Internal BPF, слСд Ρ‚ΠΎΠ²Π° ΠΏΡ€Π΅ΠΈΠΌΠ΅Π½ΡƒΠ²Π°Π½Π° Π½Π° Extended BPF, Π° сСга, слСд няколко Π³ΠΎΠ΄ΠΈΠ½ΠΈ, всички просто я Π½Π°Ρ€ΠΈΡ‡Π°Ρ‚ ​​BPF.

Π“Ρ€ΡƒΠ±ΠΎ ΠΊΠ°Π·Π°Π½ΠΎ, BPF Π²ΠΈ позволява Π΄Π° стартиратС ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»Π΅Π½ ΠΊΠΎΠ΄, прСдоставСн ΠΎΡ‚ потрСбитСля, Π² пространството Π½Π° ядрото Π½Π° Linux ΠΈ Π½ΠΎΠ²Π°Ρ‚Π° Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π° сС ΠΎΠΊΠ°Π·Π° Ρ‚ΠΎΠ»ΠΊΠΎΠ²Π° ΡƒΡΠΏΠ΅ΡˆΠ½Π°, Ρ‡Π΅ Ρ‰Π΅ Π½ΠΈ трябват ΠΎΡ‰Π΅ Π΄ΡƒΠ·ΠΈΠ½Π° статии, Π·Π° Π΄Π° опишСм всички Π½Π΅ΠΉΠ½ΠΈ прилоТСния. (ЕдинствСното Π½Π΅Ρ‰ΠΎ, ΠΊΠΎΠ΅Ρ‚ΠΎ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΡ†ΠΈΡ‚Π΅ Π½Π΅ са Π½Π°ΠΏΡ€Π°Π²ΠΈΠ»ΠΈ Π΄ΠΎΠ±Ρ€Π΅, ΠΊΠ°ΠΊΡ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π²ΠΈΠ΄ΠΈΡ‚Π΅ Π² ΠΊΠΎΠ΄Π° Π·Π° изпълнСниС ΠΏΠΎ-Π΄ΠΎΠ»Ρƒ, Π΅ ΡΡŠΠ·Π΄Π°Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° ΠΏΡ€ΠΈΠ»ΠΈΡ‡Π½ΠΎ Π»ΠΎΠ³ΠΎ.)

Π’Π°Π·ΠΈ статия описва структурата Π½Π° Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»Π½Π°Ρ‚Π° машина BPF, интСрфСйситС Π½Π° ядрото Π·Π° Ρ€Π°Π±ΠΎΡ‚Π° с BPF, инструмСнтитС Π·Π° Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ°, ΠΊΠ°ΠΊΡ‚ΠΎ ΠΈ ΠΊΡ€Π°Ρ‚ΡŠΠΊ, ΠΌΠ½ΠΎΠ³ΠΎ ΠΊΡ€Π°Ρ‚ΡŠΠΊ ΠΏΡ€Π΅Π³Π»Π΅Π΄ Π½Π° ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π°Ρ‰ΠΈΡ‚Π΅ Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΠΈ, Ρ‚.Π΅. всичко, ΠΎΡ‚ ΠΊΠΎΠ΅Ρ‚ΠΎ Ρ‰Π΅ сС Π½ΡƒΠΆΠ΄Π°Π΅ΠΌ Π² Π±ΡŠΠ΄Π΅Ρ‰Π΅ Π·Π° ΠΏΠΎ-Π·Π°Π΄ΡŠΠ»Π±ΠΎΡ‡Π΅Π½ΠΎ ΠΈΠ·ΡƒΡ‡Π°Π²Π°Π½Π΅ Π½Π° практичСскитС прилоТСния Π½Π° BPF.
BPF Π·Π° Π½Π°ΠΉ-ΠΌΠ°Π»ΠΊΠΈΡ‚Π΅, част ΠΏΡŠΡ€Π²Π°: Ρ€Π°Π·ΡˆΠΈΡ€Π΅Π½ BPF

РСзюмС Π½Π° статията

Π’ΡŠΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π² BPF Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π°Ρ‚Π°. ΠŸΡŠΡ€Π²ΠΎ, Ρ‰Π΅ Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΎΡ‚ ΠΏΡ‚ΠΈΡ‡ΠΈ ΠΏΠΎΠ³Π»Π΅Π΄ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π°Ρ‚Π° Π½Π° BPF ΠΈ Ρ‰Π΅ ΠΎΡ‡Π΅Ρ€Ρ‚Π°Π΅ΠΌ основнитС ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΈ.

РСгистри ΠΈ ΠΊΠΎΠΌΠ°Π½Π΄Π½Π° систСма Π½Π° Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»Π½Π°Ρ‚Π° машина BPF. Π’Π΅Ρ‡Π΅ ΠΈΠΌΠ°ΠΉΠΊΠΈ прСдстава Π·Π° Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π°Ρ‚Π° ΠΊΠ°Ρ‚ΠΎ цяло, Ρ‰Π΅ опишСм структурата Π½Π° Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»Π½Π°Ρ‚Π° машина BPF.

Π–ΠΈΠ·Π½Π΅Π½ Ρ†ΠΈΠΊΡŠΠ» Π½Π° BPF ΠΎΠ±Π΅ΠΊΡ‚ΠΈ, bpffs Ρ„Π°ΠΉΠ»ΠΎΠ²Π° систСма. Π’ Ρ‚ΠΎΠ·ΠΈ Ρ€Π°Π·Π΄Π΅Π» Ρ‰Π΅ Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΏΠΎ-ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ ТизнСния Ρ†ΠΈΠΊΡŠΠ» Π½Π° BPF ΠΎΠ±Π΅ΠΊΡ‚ΠΈ - ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ ΠΈ ΠΊΠ°Ρ€Ρ‚ΠΈ.

Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½Π° ΠΎΠ±Π΅ΠΊΡ‚ΠΈ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° систСмното ΠΏΠΎΠ²ΠΈΠΊΠ²Π°Π½Π΅ bpf. Π‘ извСстно Ρ€Π°Π·Π±ΠΈΡ€Π°Π½Π΅ Π½Π° систСмата, която Π²Π΅Ρ‡Π΅ Π΅ Π½Π°Π»ΠΈΡ†Π΅, Π½Π°ΠΉ-накрая Ρ‰Π΅ Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΊΠ°ΠΊ Π΄Π° създавамС ΠΈ ΠΌΠ°Π½ΠΈΠΏΡƒΠ»ΠΈΡ€Π°ΠΌΠ΅ ΠΎΠ±Π΅ΠΊΡ‚ΠΈ ΠΎΡ‚ потрСбитСлското пространство с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° спСциално систСмно ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅ βˆ’ bpf(2).

ПишСм ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ BPF с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ libbpf. Π Π°Π·Π±ΠΈΡ€Π° сС, ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΏΠΈΡˆΠ΅Ρ‚Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ систСмно ΠΏΠΎΠ²ΠΈΠΊΠ²Π°Π½Π΅. Но Π΅ Ρ‚Ρ€ΡƒΠ΄Π½ΠΎ. Π—Π° ΠΏΠΎ-рСалистичСн сцСнарий ядрСнитС програмисти Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΈΡ…Π° Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° libbpf. Π©Π΅ създадСм основСн скСлСт Π½Π° BPF ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, ΠΊΠΎΠΉΡ‚ΠΎ Ρ‰Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ Π² слСдващитС ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΈ.

ΠŸΠΎΠΌΠΎΡ‰Π½ΠΈΡ†ΠΈ Π½Π° ядрото. Π’ΡƒΠΊ Ρ‰Π΅ Π½Π°ΡƒΡ‡ΠΈΠΌ ΠΊΠ°ΠΊ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° ΠΈΠΌΠ°Ρ‚ Π΄ΠΎΡΡ‚ΡŠΠΏ Π΄ΠΎ ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈΡ‚Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π½Π° ядрото - инструмСнт, ΠΊΠΎΠΉΡ‚ΠΎ Π·Π°Π΅Π΄Π½ΠΎ с ΠΊΠ°Ρ€Ρ‚ΠΈΡ‚Π΅ Ρ€Π°Π·ΡˆΠΈΡ€ΡΠ²Π° Ρ„ΡƒΠ½Π΄Π°ΠΌΠ΅Π½Ρ‚Π°Π»Π½ΠΎ Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΠΈΡ‚Π΅ Π½Π° новия BPF Π² сравнСниС с класичСския.

Π”ΠΎΡΡ‚ΡŠΠΏ Π΄ΠΎ ΠΊΠ°Ρ€Ρ‚ΠΈ ΠΎΡ‚ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅ Π½Π° BPF. Π”ΠΎ Ρ‚ΠΎΠ·ΠΈ ΠΌΠΎΠΌΠ΅Π½Ρ‚ Ρ‰Π΅ Π·Π½Π°Π΅ΠΌ Π΄ΠΎΡΡ‚Π°Ρ‚ΡŠΡ‡Π½ΠΎ, Π·Π° Π΄Π° Ρ€Π°Π·Π±Π΅Ρ€Π΅ΠΌ ΠΊΠ°ΠΊ Ρ‚ΠΎΡ‡Π½ΠΎ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° създавамС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ ΠΊΠ°Ρ€Ρ‚ΠΈ. И Π½Π΅ΠΊΠ° Π΄ΠΎΡ€ΠΈ Π΄Π° Π½Π°Π΄Π½ΠΈΠΊΠ½Π΅ΠΌ Π½Π°Π±ΡŠΡ€Π·ΠΎ Π² страхотния ΠΈ ΠΌΠΎΠ³ΡŠΡ‰ Π²Π΅Ρ€ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€.

Π˜Π½ΡΡ‚Ρ€ΡƒΠΌΠ΅Π½Ρ‚ΠΈ Π·Π° Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ°. Π Π°Π·Π΄Π΅Π» Π·Π° ΠΏΠΎΠΌΠΎΡ‰ Π·Π° Ρ‚ΠΎΠ²Π° ΠΊΠ°ΠΊ Π΄Π° сглобитС Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΈΡ‚Π΅ ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ ΠΈ ядро ​​за СкспСримСнти.

Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅. Π’ края Π½Π° статията, ΠΏΡ€ΠΎΡ‡Π΅Π»ΠΈΡ‚Π΅ Π΄ΠΎΡ‚ΡƒΠΊ Ρ‰Π΅ намСрят ΠΌΠΎΡ‚ΠΈΠ²ΠΈΡ€Π°Ρ‰ΠΈ Π΄ΡƒΠΌΠΈ ΠΈ ΠΊΡ€Π°Ρ‚ΠΊΠΎ описаниС Π½Π° Ρ‚ΠΎΠ²Π°, ΠΊΠΎΠ΅Ρ‚ΠΎ Ρ‰Π΅ сС случи Π² слСдващитС статии. Π©Π΅ ΠΈΠ·Π±Ρ€ΠΎΠΈΠΌ ΠΈ Ρ€Π΅Π΄ΠΈΡ†Π° Π²Ρ€ΡŠΠ·ΠΊΠΈ Π·Π° самообучСниС Π·Π° Ρ‚Π΅Π·ΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ нямат ΠΆΠ΅Π»Π°Π½ΠΈΠ΅ ΠΈΠ»ΠΈ Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ Π΄Π° Ρ‡Π°ΠΊΠ°Ρ‚ ΠΏΡ€ΠΎΠ΄ΡŠΠ»ΠΆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ.

Π’ΡŠΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π² BPF Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π°Ρ‚Π°

ΠŸΡ€Π΅Π΄ΠΈ Π΄Π° Π·Π°ΠΏΠΎΡ‡Π½Π΅ΠΌ Π΄Π° Ρ€Π°Π·Π³Π»Π΅ΠΆΠ΄Π°ΠΌΠ΅ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π°Ρ‚Π° Π½Π° BPF, Ρ‰Π΅ сС ΠΏΠΎΠ·ΠΎΠ²Π΅ΠΌ Π·Π° послСдСн ΠΏΡŠΡ‚ (ΠΎ) Π½Π° класичСски BPF, ΠΊΠΎΠΉΡ‚ΠΎ бСшС Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Π΅Π½ Π² ΠΎΡ‚Π³ΠΎΠ²ΠΎΡ€ Π½Π° появата Π½Π° RISC машини ΠΈ Ρ€Π΅ΡˆΠΈ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° с Π΅Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π½ΠΎΡ‚ΠΎ Ρ„ΠΈΠ»Ρ‚Ρ€ΠΈΡ€Π°Π½Π΅ Π½Π° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ. АрхитСктурата сС ΠΎΠΊΠ°Π·Π° Ρ‚ΠΎΠ»ΠΊΠΎΠ²Π° ΡƒΡΠΏΠ΅ΡˆΠ½Π°, Ρ‡Π΅, Ρ€ΠΎΠ΄Π΅Π½Π° ΠΏΡ€Π΅Π· Π΅Π»Π΅Π³Π°Π½Ρ‚Π½ΠΈΡ‚Π΅ дСвСтдСсСт Π³ΠΎΠ΄ΠΈΠ½ΠΈ Π² Berkeley UNIX, тя бСшС прСнСсСна Π² ΠΏΠΎΠ²Π΅Ρ‡Π΅Ρ‚ΠΎ ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π°Ρ‰ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΎΠ½Π½ΠΈ систСми, оцСля Π² Π»ΡƒΠ΄ΠΈΡ‚Π΅ двадСсСттС Π³ΠΎΠ΄ΠΈΠ½ΠΈ ΠΈ всС ΠΎΡ‰Π΅ Π½Π°ΠΌΠΈΡ€Π° Π½ΠΎΠ²ΠΈ прилоТСния.

Новият BPF Π΅ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Π΅Π½ ΠΊΠ°Ρ‚ΠΎ ΠΎΡ‚Π³ΠΎΠ²ΠΎΡ€ Π½Π° повсСмСстното разпространСниС Π½Π° 64-Π±ΠΈΡ‚ΠΎΠ²ΠΈ машини, ΠΎΠ±Π»Π°Ρ‡Π½ΠΈ услуги ΠΈ ΠΏΠΎΠ²ΠΈΡˆΠ΅Π½Π°Ρ‚Π° Π½ΡƒΠΆΠ΄Π° ΠΎΡ‚ инструмСнти Π·Π° създаванС Π½Π° SDN (SсофтуСр-dΡƒΡΡŠΠ²ΡŠΡ€ΡˆΠ΅Π½ΡΡ‚Π²Π°Π½ nΠΌΡ€Π΅ΠΆΠΎΠ²Π° Ρ€Π°Π±ΠΎΡ‚Π°). Π Π°Π·Ρ€Π°Π±ΠΎΡ‚Π΅Π½ ΠΎΡ‚ ΠΌΡ€Π΅ΠΆΠΎΠ²ΠΈ ΠΈΠ½ΠΆΠ΅Π½Π΅Ρ€ΠΈ Π½Π° ядрото ΠΊΠ°Ρ‚ΠΎ ΠΏΠΎΠ΄ΠΎΠ±Ρ€Π΅Π½ замСститСл Π½Π° класичСския BPF, новият BPF Π±ΡƒΠΊΠ²Π°Π»Π½ΠΎ ΡˆΠ΅ΡΡ‚ мСсСца ΠΏΠΎ-късно Π½Π°ΠΌΠ΅Ρ€ΠΈ прилоТСния Π² Ρ‚Ρ€ΡƒΠ΄Π½Π°Ρ‚Π° Π·Π°Π΄Π°Ρ‡Π° Π·Π° прослСдяванС Π½Π° Linux систСми ΠΈ сСга, ΡˆΠ΅ΡΡ‚ Π³ΠΎΠ΄ΠΈΠ½ΠΈ слСд появата ΠΌΡƒ, Ρ‰Π΅ Π½ΠΈ Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠ° цяла слСдваща статия само Π·Π° ΠΈΠ·Π±Ρ€ΠΎΠΉΡ‚Π΅ Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈΡ‚Π΅ Ρ‚ΠΈΠΏΠΎΠ²Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ.

БмСшни ΠΊΠ°Ρ€Ρ‚ΠΈΠ½ΠΊΠΈ

Π’ основата си BPF Π΅ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»Π½Π° машина с пясък, която Π²ΠΈ позволява Π΄Π° ΠΈΠ·ΠΏΡŠΠ»Π½ΡΠ²Π°Ρ‚Π΅ β€žΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»Π΅Π½β€œ ΠΊΠΎΠ΄ Π² пространството Π½Π° ядрото, Π±Π΅Π· Π΄Π° ΠΊΠΎΠΌΠΏΡ€ΠΎΠΌΠ΅Ρ‚ΠΈΡ€Π°Ρ‚Π΅ сигурността. BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅ сС ΡΡŠΠ·Π΄Π°Π²Π°Ρ‚ Π² потрСбитСлско пространство, Π·Π°Ρ€Π΅ΠΆΠ΄Π°Ρ‚ сС Π² ядрото ΠΈ сС ΡΠ²ΡŠΡ€Π·Π²Π°Ρ‚ към някакъв ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ Π½Π° ΡΡŠΠ±ΠΈΡ‚ΠΈΡ. Π‘ΡŠΠ±ΠΈΡ‚ΠΈΠ΅ ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ доставка Π½Π° ΠΏΠ°ΠΊΠ΅Ρ‚ Π΄ΠΎ ΠΌΡ€Π΅ΠΆΠΎΠ² интСрфСйс, стартиранС Π½Π° някаква функция Π½Π° ядрото ΠΈ Ρ‚.Π½. Π’ случай Π½Π° ΠΏΠ°ΠΊΠ΅Ρ‚, ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° BPF Ρ‰Π΅ ΠΈΠΌΠ° Π΄ΠΎΡΡ‚ΡŠΠΏ Π΄ΠΎ Π΄Π°Π½Π½ΠΈΡ‚Π΅ ΠΈ ΠΌΠ΅Ρ‚Π°Π΄Π°Π½Π½ΠΈΡ‚Π΅ Π½Π° ΠΏΠ°ΠΊΠ΅Ρ‚Π° (Π·Π° Ρ‡Π΅Ρ‚Π΅Π½Π΅ ΠΈ, Π΅Π²Π΅Π½Ρ‚ΡƒΠ°Π»Π½ΠΎ, запис, Π² зависимост ΠΎΡ‚ Ρ‚ΠΈΠΏΠ° Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π°); Π² случай Π½Π° изпълнСниС Π½Π° функция Π½Π° ядрото, Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΈΡ‚Π΅ Π½Π° функцията, Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»Π½ΠΎ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈ към ΠΏΠ°ΠΌΠ΅Ρ‚Ρ‚Π° Π½Π° ядрото ΠΈ Ρ‚.Π½.

НСка Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΏΠΎ-ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ Ρ‚ΠΎΠ·ΠΈ процСс. ΠšΠ°Ρ‚ΠΎ Π½Π°Ρ‡Π°Π»ΠΎ, Π½Π΅ΠΊΠ° ΠΏΠΎΠ³ΠΎΠ²ΠΎΡ€ΠΈΠΌ Π·Π° ΠΏΡŠΡ€Π²Π°Ρ‚Π° Ρ€Π°Π·Π»ΠΈΠΊΠ° ΠΎΡ‚ класичСския BPF, ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅ Π·Π° ΠΊΠΎΠΈΡ‚ΠΎ са написани Π½Π° асСмблСр. Π’ Π½ΠΎΠ²Π°Ρ‚Π° вСрсия Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π°Ρ‚Π° бСшС Ρ€Π°Π·ΡˆΠΈΡ€Π΅Π½Π°, Ρ‚Π°ΠΊΠ° Ρ‡Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅ Π΄Π° ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ написани Π½Π° Π΅Π·ΠΈΡ†ΠΈ ΠΎΡ‚ високо Π½ΠΈΠ²ΠΎ, ΠΏΡ€Π΅Π΄ΠΈΠΌΠ½ΠΎ, Ρ€Π°Π·Π±ΠΈΡ€Π° сС, Π½Π° C. Π—Π° Ρ‚Π°Π·ΠΈ Ρ†Π΅Π» бСшС Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Π΅Π½ Π±Π΅ΠΊΠ΅Π½Π΄ Π·Π° llvm, ΠΊΠΎΠΉΡ‚ΠΎ позволява Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π΅ Π½Π° Π±Π°ΠΉΡ‚ ΠΊΠΎΠ΄ Π·Π° BPF Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π°Ρ‚Π°.

BPF Π·Π° Π½Π°ΠΉ-ΠΌΠ°Π»ΠΊΠΈΡ‚Π΅, част ΠΏΡŠΡ€Π²Π°: Ρ€Π°Π·ΡˆΠΈΡ€Π΅Π½ BPF

АрхитСктурата Π½Π° BPF Π΅ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΈΡ€Π°Π½Π° отчасти Π΄Π° Ρ€Π°Π±ΠΎΡ‚ΠΈ Π΅Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π½ΠΎ Π½Π° ΡΡŠΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΈ машини. Π—Π° Π΄Π° Ρ€Π°Π±ΠΎΡ‚ΠΈ Ρ‚ΠΎΠ²Π° Π½Π° ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ°, BPF Π±Π°ΠΉΡ‚ ΠΊΠΎΠ΄ΡŠΡ‚, слСд ΠΊΠ°Ρ‚ΠΎ бъдС Π·Π°Ρ€Π΅Π΄Π΅Π½ Π² ядрото, сС ΠΏΡ€Π΅Π²Π΅ΠΆΠ΄Π° Π² собствСн ΠΊΠΎΠ΄ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚, Π½Π°Ρ€Π΅Ρ‡Π΅Π½ JIT ΠΊΠΎΠΌΠΏΠΈΠ»Π°Ρ‚ΠΎΡ€ (JУст In TΠ°Π·). Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π°, Π°ΠΊΠΎ си спомнятС, Π² класичСския BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° бСшС Π·Π°Ρ€Π΅Π΄Π΅Π½Π° Π² ядрото ΠΈ ΠΏΡ€ΠΈΠΊΡ€Π΅ΠΏΠ΅Π½Π° към ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΠΊΠ° Π½Π° ΡΡŠΠ±ΠΈΡ‚ΠΈΠ΅ Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½ΠΎ - Π² контСкста Π½Π° Π΅Π΄Π½ΠΎ систСмно ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅. Π’ Π½ΠΎΠ²Π°Ρ‚Π° Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π° Ρ‚ΠΎΠ²Π° сС случва Π½Π° Π΄Π²Π° Π΅Ρ‚Π°ΠΏΠ° - ΠΏΡŠΡ€Π²ΠΎ ΠΊΠΎΠ΄ΡŠΡ‚ сС Π·Π°Ρ€Π΅ΠΆΠ΄Π° Π² ядрото Ρ‡Ρ€Π΅Π· систСмно ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅ bpf(2)ΠΈ слСд Ρ‚ΠΎΠ²Π°, ΠΏΠΎ-късно, Ρ‡Ρ€Π΅Π· Π΄Ρ€ΡƒΠ³ΠΈ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ Π²Π°Ρ€ΠΈΡ€Π°Ρ‚ Π² зависимост ΠΎΡ‚ Ρ‚ΠΈΠΏΠ° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°, ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° сС прикрСпя към ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΠΊΠ° Π½Π° ΡΡŠΠ±ΠΈΡ‚ΠΈΠ΅.

Π’ΡƒΠΊ читатСлят ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΈΠΌΠ° Π²ΡŠΠΏΡ€ΠΎΡ: възмоТно Π»ΠΈ Π΅? Как сС Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€Π° бСзопасността Π½Π° изпълнСниС Π½Π° Ρ‚Π°ΠΊΡŠΠ² ΠΊΠΎΠ΄? БСзопасността Π½Π° ΠΈΠ·ΠΏΡŠΠ»Π½Π΅Π½ΠΈΠ΅Ρ‚ΠΎ Π½ΠΈ Π΅ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€Π°Π½Π° ΠΎΡ‚ Π΅Ρ‚Π°ΠΏΠ° Π½Π° Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅ Π½Π° BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ, Π½Π°Ρ€Π΅Ρ‡Π΅Π½ verifier (Π½Π° английски Ρ‚ΠΎΠ·ΠΈ Π΅Ρ‚Π°ΠΏ сС Π½Π°Ρ€ΠΈΡ‡Π° verifier ΠΈ Π°Π· Ρ‰Π΅ ΠΏΡ€ΠΎΠ΄ΡŠΠ»ΠΆΠ° Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌ английската Π΄ΡƒΠΌΠ°):

BPF Π·Π° Π½Π°ΠΉ-ΠΌΠ°Π»ΠΊΠΈΡ‚Π΅, част ΠΏΡŠΡ€Π²Π°: Ρ€Π°Π·ΡˆΠΈΡ€Π΅Π½ BPF

Verifier Π΅ статичСн Π°Π½Π°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€, ΠΊΠΎΠΉΡ‚ΠΎ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€Π°, Ρ‡Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° няма Π΄Π° Π½Π°Ρ€ΡƒΡˆΠΈ Π½ΠΎΡ€ΠΌΠ°Π»Π½Π°Ρ‚Π° Ρ€Π°Π±ΠΎΡ‚Π° Π½Π° ядрото. Π’ΠΎΠ²Π°, ΠΌΠ΅ΠΆΠ΄Ρƒ Π΄Ρ€ΡƒΠ³ΠΎΡ‚ΠΎ, Π½Π΅ ΠΎΠ·Π½Π°Ρ‡Π°Π²Π°, Ρ‡Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° сС намСсва Π² Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚Π° Π½Π° систСмата - BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅, Π² зависимост ΠΎΡ‚ Ρ‚ΠΈΠΏΠ°, ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Ρ‡Π΅Ρ‚Π°Ρ‚ ΠΈ прСнаписват сСкции ΠΎΡ‚ ΠΏΠ°ΠΌΠ΅Ρ‚Ρ‚Π° Π½Π° ядрото, Π΄Π° Π²Ρ€ΡŠΡ‰Π°Ρ‚ стойности Π½Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Π΄Π° изрязват, добавят, прСнаписват ΠΈ Π΄ΠΎΡ€ΠΈ ΠΏΡ€Π΅ΠΏΡ€Π°Ρ‰Π° ΠΌΡ€Π΅ΠΆΠΎΠ²ΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ. Verifier Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€Π°, Ρ‡Π΅ ΠΈΠ·ΠΏΡŠΠ»Π½Π΅Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π° BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° няма Π΄Π° сринС ядрото ΠΈ Ρ‡Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°, която спорСд ΠΏΡ€Π°Π²ΠΈΠ»Π°Ρ‚Π° ΠΈΠΌΠ° Π΄ΠΎΡΡ‚ΡŠΠΏ Π·Π° запис, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π΄Π°Π½Π½ΠΈΡ‚Π΅ Π½Π° изходящ ΠΏΠ°ΠΊΠ΅Ρ‚, няма Π΄Π° ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΏΡ€Π΅Π·Π°ΠΏΠΈΡˆΠ΅ ΠΏΠ°ΠΌΠ΅Ρ‚Ρ‚Π° Π½Π° ядрото извън ΠΏΠ°ΠΊΠ΅Ρ‚Π°. Π©Π΅ Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ Π²Π΅Ρ€ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Π° ΠΌΠ°Π»ΠΊΠΎ ΠΏΠΎ-ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ Π² ΡΡŠΠΎΡ‚Π²Π΅Ρ‚Π½ΠΈΡ Ρ€Π°Π·Π΄Π΅Π», слСд ΠΊΠ°Ρ‚ΠΎ сС Π·Π°ΠΏΠΎΠ·Π½Π°Π΅ΠΌ с всички останали ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΈ Π½Π° BPF.

И Ρ‚Π°ΠΊΠ°, ΠΊΠ°ΠΊΠ²ΠΎ Π½Π°ΡƒΡ‡ΠΈΡ…ΠΌΠ΅ досСга? ΠŸΠΎΡ‚Ρ€Π΅Π±ΠΈΡ‚Π΅Π»ΡΡ‚ пишС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Π½Π° C, Π·Π°Ρ€Π΅ΠΆΠ΄Π° я Π² ядрото Ρ‡Ρ€Π΅Π· систСмно ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅ bpf(2), ΠΊΡŠΠ΄Π΅Ρ‚ΠΎ сС провСрява ΠΎΡ‚ Π²Π΅Ρ€ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ ΠΈ сС ΠΏΡ€Π΅Π²Π΅ΠΆΠ΄Π° Π² СстСствСн Π±Π°ΠΉΡ‚ΠΊΠΎΠ΄. Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° ΡΡŠΡ‰ΠΈΡΡ‚ ΠΈΠ»ΠΈ Π΄Ρ€ΡƒΠ³ ΠΏΠΎΡ‚Ρ€Π΅Π±ΠΈΡ‚Π΅Π» ΡΠ²ΡŠΡ€Π·Π²Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° към ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΠΊΠ° Π½Π° ΡΡŠΠ±ΠΈΡ‚ΠΈΠ΅ ΠΈ тя Π·Π°ΠΏΠΎΡ‡Π²Π° Π΄Π° сС изпълнява. РаздСлянСто Π½Π° стартиранС ΠΈ ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅ Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΠΎΡ€Π°Π΄ΠΈ няколко ΠΏΡ€ΠΈΡ‡ΠΈΠ½ΠΈ. ΠŸΡŠΡ€Π²ΠΎ, стартиранСто Π½Π° Π²Π΅Ρ€ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ Π΅ сравнитСлно скъпо ΠΈ ΠΊΠ°Ρ‚ΠΎ изтСглямС Π΅Π΄Π½Π° ΠΈ ΡΡŠΡ‰Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° няколко ΠΏΡŠΡ‚ΠΈ, Π½ΠΈΠ΅ Π³ΡƒΠ±ΠΈΠΌ ΠΊΠΎΠΌΠΏΡŽΡ‚ΡŠΡ€Π½ΠΎ Π²Ρ€Π΅ΠΌΠ΅. Π’Ρ‚ΠΎΡ€ΠΎ, ΠΊΠ°ΠΊ Ρ‚ΠΎΡ‡Π½ΠΎ Π΅ ΡΠ²ΡŠΡ€Π·Π°Π½Π° Π΅Π΄Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° зависи ΠΎΡ‚ нСйния Ρ‚ΠΈΠΏ ΠΈ Π΅Π΄ΠΈΠ½ β€žΡƒΠ½ΠΈΠ²Π΅Ρ€ΡΠ°Π»Π΅Π½β€œ интСрфСйс, Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Π΅Π½ ΠΏΡ€Π΅Π΄ΠΈ Π³ΠΎΠ΄ΠΈΠ½Π°, ΠΌΠΎΠΆΠ΅ Π΄Π° Π½Π΅ Π΅ подходящ Π·Π° Π½ΠΎΠ²ΠΈ Π²ΠΈΠ΄ΠΎΠ²Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ. (Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‡Π΅ сСга, ΠΊΠΎΠ³Π°Ρ‚ΠΎ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π°Ρ‚Π° става ΠΏΠΎ-зряла, ΠΈΠΌΠ° идСя Ρ‚ΠΎΠ·ΠΈ интСрфСйс Π΄Π° сС ΠΎΠ±Π΅Π΄ΠΈΠ½ΠΈ Π½Π° Π½ΠΈΠ²ΠΎ libbpf.)

ВниматСлният Ρ‡ΠΈΡ‚Π°Ρ‚Π΅Π» ΠΌΠΎΠΆΠ΅ Π΄Π° Π·Π°Π±Π΅Π»Π΅ΠΆΠΈ, Ρ‡Π΅ ΠΎΡ‰Π΅ Π½Π΅ смС ΠΏΡ€ΠΈΠΊΠ»ΡŽΡ‡ΠΈΠ»ΠΈ със снимкитС. Π’ΡΡŠΡ‰Π½ΠΎΡΡ‚ всичко ΠΏΠΎ-Π³ΠΎΡ€Π΅ Π½Π΅ обяснява Π·Π°Ρ‰ΠΎ BPF Ρ„ΡƒΠ½Π΄Π°ΠΌΠ΅Π½Ρ‚Π°Π»Π½ΠΎ промСня ΠΊΠ°Ρ€Ρ‚ΠΈΠ½Π°Ρ‚Π° Π² сравнСниС с класичСския BPF. Π”Π²Π΅ ΠΈΠ½ΠΎΠ²Π°Ρ†ΠΈΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»Π½ΠΎ Ρ€Π°Π·ΡˆΠΈΡ€ΡΠ²Π°Ρ‚ ΠΎΠ±Ρ…Π²Π°Ρ‚Π° Π½Π° прилоТимост, са Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚Ρ‚Π° Π·Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° сподСлСна ΠΏΠ°ΠΌΠ΅Ρ‚ ΠΈ ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π½Π° ядрото. Π’ BPF сподСлСната ΠΏΠ°ΠΌΠ΅Ρ‚ сС Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€Π° с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° Ρ‚Π°ΠΊΠ° Π½Π°Ρ€Π΅Ρ‡Π΅Π½ΠΈΡ‚Π΅ ΠΊΠ°Ρ€Ρ‚ΠΈ - сподСлСни структури ΠΎΡ‚ Π΄Π°Π½Π½ΠΈ със спСцифичСн API. ВСроятно са ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΈ Ρ‚ΠΎΠ²Π° ΠΈΠΌΠ΅, Π·Π°Ρ‰ΠΎΡ‚ΠΎ ΠΏΡŠΡ€Π²ΠΈΡΡ‚ Ρ‚ΠΈΠΏ ΠΊΠ°Ρ€Ρ‚Π°, ΠΊΠΎΠΉΡ‚ΠΎ сС появи, бСшС Ρ…Π΅Ρˆ Ρ‚Π°Π±Π»ΠΈΡ†Π°. Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° сС появиха масиви, Π»ΠΎΠΊΠ°Π»Π½ΠΈ (Π½Π° CPU) Ρ…Π΅Ρˆ Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ ΠΈ Π»ΠΎΠΊΠ°Π»Π½ΠΈ масиви, Π΄ΡŠΡ€Π²Π΅Ρ‚Π° Π·Π° Ρ‚ΡŠΡ€ΡΠ΅Π½Π΅, ΠΊΠ°Ρ€Ρ‚ΠΈ, ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Ρ‰ΠΈ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈ към BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ ΠΈ ΠΌΠ½ΠΎΠ³ΠΎ Π΄Ρ€ΡƒΠ³ΠΈ. Π’ΠΎΠ²Π°, ΠΊΠΎΠ΅Ρ‚ΠΎ Π΅ интСрСсно Π·Π° нас сСга, Π΅, Ρ‡Π΅ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅ Π²Π΅Ρ‡Π΅ ΠΈΠΌΠ°Ρ‚ способността Π΄Π° Π·Π°ΠΏΠ°Π·Π²Π°Ρ‚ ΡΡŠΡΡ‚ΠΎΡΠ½ΠΈΠ΅Ρ‚ΠΎ ΠΌΠ΅ΠΆΠ΄Ρƒ повикванията ΠΈ Π΄Π° Π³ΠΎ сподСлят с Π΄Ρ€ΡƒΠ³ΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ ΠΈ с потрСбитСлско пространство.

Π”ΠΎΡΡ‚ΡŠΠΏΡŠΡ‚ Π΄ΠΎ ΠΊΠ°Ρ€Ρ‚ΠΈΡ‚Π΅ сС ΠΎΡΡŠΡ‰Π΅ΡΡ‚Π²ΡΠ²Π° ΠΎΡ‚ потрСбитСлски процСси Ρ‡Ρ€Π΅Π· систСмно ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅ bpf(2)ΠΈ ΠΎΡ‚ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ, Ρ€Π°Π±ΠΎΡ‚Π΅Ρ‰ΠΈ Π² ядрото, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‰ΠΈ ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. ОсвСн Ρ‚ΠΎΠ²Π° ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π°Ρ‚ ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈΡ†ΠΈ Π½Π΅ само Π·Π° Ρ€Π°Π±ΠΎΡ‚Π° с ΠΊΠ°Ρ€Ρ‚ΠΈ, Π½ΠΎ ΠΈ Π·Π° Π΄ΠΎΡΡ‚ΡŠΠΏ Π΄ΠΎ Π΄Ρ€ΡƒΠ³ΠΈ Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΠΈ Π½Π° ядрото. НапримСр, BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π·Π° ΠΏΡ€Π΅ΠΏΡ€Π°Ρ‰Π°Π½Π΅ Π½Π° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ към Π΄Ρ€ΡƒΠ³ΠΈ интСрфСйси, Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π΅ Π½Π° ΠΏΠ΅Ρ€Ρ„ ΡΡŠΠ±ΠΈΡ‚ΠΈΡ, Π΄ΠΎΡΡ‚ΡŠΠΏ Π΄ΠΎ структури Π½Π° ядрото ΠΈ Ρ‚.Π½.

BPF Π·Π° Π½Π°ΠΉ-ΠΌΠ°Π»ΠΊΠΈΡ‚Π΅, част ΠΏΡŠΡ€Π²Π°: Ρ€Π°Π·ΡˆΠΈΡ€Π΅Π½ BPF

Π’ ΠΎΠ±ΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅, BPF прСдоставя Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ Π·Π° Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅ Π½Π° ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»Π΅Π½, Ρ‚.Π΅. тСстван ΠΎΡ‚ Π²Π΅Ρ€ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€, потрСбитСлски ΠΊΠΎΠ΄ Π² пространството Π½Π° ядрото. Π’ΠΎΠ·ΠΈ ΠΊΠΎΠ΄ ΠΌΠΎΠΆΠ΅ Π΄Π° Π·Π°ΠΏΠ°Π·Π²Π° ΡΡŠΡΡ‚ΠΎΡΠ½ΠΈΠ΅ ΠΌΠ΅ΠΆΠ΄Ρƒ повиквания ΠΈ Π΄Π° обмСня Π΄Π°Π½Π½ΠΈ с потрСбитСлско пространство, Π° ΡΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° ΠΈΠΌΠ° Π΄ΠΎΡΡ‚ΡŠΠΏ Π΄ΠΎ подсистСми Π½Π° ядрото, Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈ ΠΎΡ‚ Ρ‚ΠΎΠ·ΠΈ Ρ‚ΠΈΠΏ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°.

Π’ΠΎΠ²Π° Π²Π΅Ρ‡Π΅ Π΅ ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎ Π½Π° Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΠΈΡ‚Π΅, прСдоставСни ΠΎΡ‚ ΠΌΠΎΠ΄ΡƒΠ»ΠΈΡ‚Π΅ Π½Π° ядрото, Π² сравнСниС с ΠΊΠΎΠΈΡ‚ΠΎ BPF ΠΈΠΌΠ° някои прСдимства (Ρ€Π°Π·Π±ΠΈΡ€Π° сС, ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° сравняватС само ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΈ прилоТСния, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ прослСдяванС Π½Π° систСмата - Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π½Π°ΠΏΠΈΡˆΠ΅Ρ‚Π΅ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»Π΅Π½ Π΄Ρ€Π°ΠΉΠ²Π΅Ρ€ с BPF). ΠœΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΎΡ‚Π±Π΅Π»Π΅ΠΆΠΈΡ‚Π΅ ΠΏΠΎ-нисък ΠΏΡ€Π°Π³ Π·Π° Π²Π»ΠΈΠ·Π°Π½Π΅ (някои ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ BPF, Π½Π΅ изискват потрСбитСлят Π΄Π° ΠΈΠΌΠ° умСния Π·Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ€Π°Π½Π΅ Π½Π° ядрото ΠΈΠ»ΠΈ умСния Π·Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ€Π°Π½Π΅ ΠΊΠ°Ρ‚ΠΎ цяло), бСзопасност ΠΏΠΎ Π²Ρ€Π΅ΠΌΠ΅ Π½Π° Ρ€Π°Π±ΠΎΡ‚Π° (Π²Π΄ΠΈΠ³Π½Π΅Ρ‚Π΅ Ρ€ΡŠΠΊΠ°Ρ‚Π° си Π² ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΡ‚Π΅ Π·Π° Ρ‚Π΅Π·ΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ Π½Π΅ са Ρ€Π°Π·Π±ΠΈΠ»ΠΈ систСмата ΠΏΡ€ΠΈ писанС ΠΈΠ»ΠΈ тСстванС Π½Π° ΠΌΠΎΠ΄ΡƒΠ»ΠΈ), атомарност - ΠΈΠΌΠ° ΠΏΡ€Π΅ΠΊΡŠΡΠ²Π°Π½Π΅ ΠΏΡ€ΠΈ ΠΏΡ€Π΅Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅ Π½Π° ΠΌΠΎΠ΄ΡƒΠ»ΠΈ ΠΈ подсистСмата BPF Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€Π°, Ρ‡Π΅ няма пропуснати ΡΡŠΠ±ΠΈΡ‚ΠΈΡ (чСстно ΠΊΠ°Π·Π°Π½ΠΎ, Ρ‚ΠΎΠ²Π° Π½Π΅ Π΅ вярно Π·Π° всички Ρ‚ΠΈΠΏΠΎΠ²Π΅ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ).

НаличиСто Π½Π° Ρ‚Π°ΠΊΠΈΠ²Π° Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΠΈ ΠΏΡ€Π°Π²ΠΈ BPF унивСрсалСн инструмСнт Π·Π° Ρ€Π°Π·ΡˆΠΈΡ€ΡΠ²Π°Π½Π΅ Π½Π° ядрото, ΠΊΠΎΠ΅Ρ‚ΠΎ сС ΠΏΠΎΡ‚Π²ΡŠΡ€ΠΆΠ΄Π°Π²Π° ΠΎΡ‚ ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ°Ρ‚Π°: всС ΠΏΠΎΠ²Π΅Ρ‡Π΅ ΠΈ ΠΏΠΎΠ²Π΅Ρ‡Π΅ Π½ΠΎΠ²ΠΈ Π²ΠΈΠ΄ΠΎΠ²Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ сС добавят към BPF, всС ΠΏΠΎΠ²Π΅Ρ‡Π΅ ΠΈ ΠΏΠΎΠ²Π΅Ρ‡Π΅ Π³ΠΎΠ»Π΅ΠΌΠΈ ΠΊΠΎΠΌΠΏΠ°Π½ΠΈΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ BPF Π½Π° Π±ΠΎΠΉΠ½ΠΈ ΡΡŠΡ€Π²ΡŠΡ€ΠΈ 24Γ—7, всС ΠΏΠΎΠ²Π΅Ρ‡Π΅ ΠΈ ΠΏΠΎΠ²Π΅Ρ‡Π΅ стартиращитС Ρ„ΠΈΡ€ΠΌΠΈ ΠΈΠ·Π³Ρ€Π°ΠΆΠ΄Π°Ρ‚ своя бизнСс Π²ΡŠΡ€Ρ…Ρƒ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ, Π±Π°Π·ΠΈΡ€Π°Π½ΠΈ Π½Π° BPF. BPF сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° навсякъдС: Π·Π° Π·Π°Ρ‰ΠΈΡ‚Π° срСщу DDoS Π°Ρ‚Π°ΠΊΠΈ, създаванС Π½Π° SDN (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ внСдряванС Π½Π° ΠΌΡ€Π΅ΠΆΠΈ Π·Π° kubernetes), ΠΊΠ°Ρ‚ΠΎ основСн инструмСнт Π·Π° прослСдяванС Π½Π° систСмата ΠΈ ΡΡŠΠ±ΠΈΡ€Π°Π½Π΅ Π½Π° статистичСски Π΄Π°Π½Π½ΠΈ, Π² систСми Π·Π° ΠΎΡ‚ΠΊΡ€ΠΈΠ²Π°Π½Π΅ Π½Π° ΠΏΡ€ΠΎΠ½ΠΈΠΊΠ²Π°Π½Π΅ ΠΈ ΠΏΡΡΡŠΡ‡Π½ΠΈ систСми ΠΈ Π΄Ρ€.

НСка Π·Π°Π²ΡŠΡ€ΡˆΠΈΠΌ ΠΎΠ±Π·ΠΎΡ€Π½Π°Ρ‚Π° част Π½Π° статията Ρ‚ΡƒΠΊ ΠΈ Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»Π½Π°Ρ‚Π° машина ΠΈ СкосистСмата Π½Π° BPF ΠΏΠΎ-ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ.

ΠžΡ‚ΠΊΠ»ΠΎΠ½Π΅Π½ΠΈΠ΅: ΠΊΠΎΠΌΡƒΠ½Π°Π»Π½ΠΈ услуги

Π—Π° Π΄Π° ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΈΠ·ΠΏΡŠΠ»Π½ΡΠ²Π°Ρ‚Π΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΈΡ‚Π΅ Π² слСдващитС Ρ€Π°Π·Π΄Π΅Π»ΠΈ, ΠΌΠΎΠΆΠ΅ Π΄Π° сС Π½ΡƒΠΆΠ΄Π°Π΅Ρ‚Π΅ ΠΎΡ‚ Ρ€Π΅Π΄ΠΈΡ†Π° ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ, ΠΏΠΎΠ½Π΅ llvm/clang с ΠΏΠΎΠ΄Π΄Ρ€ΡŠΠΆΠΊΠ° Π½Π° bpf ΠΈ bpftool, Π’ Ρ€Π°Π·Π΄Π΅Π»Π° Π˜Π½ΡΡ‚Ρ€ΡƒΠΌΠ΅Π½Ρ‚ΠΈ Π·Π° Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠœΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΏΡ€ΠΎΡ‡Π΅Ρ‚Π΅Ρ‚Π΅ инструкциитС Π·Π° асСмблиранС Π½Π° ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈΡ‚Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ, ΠΊΠ°ΠΊΡ‚ΠΎ ΠΈ Π²Π°ΡˆΠ΅Ρ‚ΠΎ ядро. Π’ΠΎΠ·ΠΈ Ρ€Π°Π·Π΄Π΅Π» Π΅ поставСн ΠΏΠΎ-Π΄ΠΎΠ»Ρƒ, Π·Π° Π΄Π° Π½Π΅ Π½Π°Ρ€ΡƒΡˆΠ°Π²Π° хармонията Π½Π° Π½Π°ΡˆΠ΅Ρ‚ΠΎ прСдставянС.

BPF РСгистри Π½Π° Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»Π½Π° машина ΠΈ систСма Π·Π° инструкции

АрхитСктурата ΠΈ ΠΊΠΎΠΌΠ°Π½Π΄Π½Π°Ρ‚Π° систСма Π½Π° BPF са Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Π΅Π½ΠΈ, ΠΊΠ°Ρ‚ΠΎ сС Π²Π·Π΅ΠΌΠ΅ ΠΏΡ€Π΅Π΄Π²ΠΈΠ΄ Ρ„Π°ΠΊΡ‚ΡŠΡ‚, Ρ‡Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅ Ρ‰Π΅ Π±ΡŠΠ΄Π°Ρ‚ написани Π½Π° Π΅Π·ΠΈΠΊΠ° C ΠΈ слСд Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅ Π² ядрото Ρ‰Π΅ Π±ΡŠΠ΄Π°Ρ‚ ΠΏΡ€Π΅Π²Π΅Π΄Π΅Π½ΠΈ Π² собствСн ΠΊΠΎΠ΄. Π‘Π»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»Π½ΠΎ броят Π½Π° рСгистритС ΠΈ Π½Π°Π±ΠΎΡ€ΡŠΡ‚ ΠΎΡ‚ ΠΊΠΎΠΌΠ°Π½Π΄ΠΈ са ΠΈΠ·Π±Ρ€Π°Π½ΠΈ с ΠΎΠ³Π»Π΅Π΄ Π½Π° прСсСчната Ρ‚ΠΎΡ‡ΠΊΠ°, Π² матСматичСски смисъл, Π½Π° Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΠΈΡ‚Π΅ Π½Π° ΡΡŠΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΈΡ‚Π΅ машини. ОсвСн Ρ‚ΠΎΠ²Π° бяха Π½Π°Π»ΠΎΠΆΠ΅Π½ΠΈ Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ ограничСния Π²ΡŠΡ€Ρ…Ρƒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ доскоро Π½Π΅ бСшС възмоТно Π΄Π° сС ΠΏΠΈΡˆΠ°Ρ‚ Ρ†ΠΈΠΊΠ»ΠΈ ΠΈ ΠΏΠΎΠ΄ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ, Π° броят Π½Π° инструкциитС бСшС ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ Π΄ΠΎ 4096 (сСга ΠΏΡ€ΠΈΠ²ΠΈΠ»Π΅Π³ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡ‚Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° зарСдят Π΄ΠΎ Π΅Π΄ΠΈΠ½ ΠΌΠΈΠ»ΠΈΠΎΠ½ инструкции).

BPF ΠΈΠΌΠ° СдинадСсСт Π΄ΠΎΡΡ‚ΡŠΠΏΠ½ΠΈ Π·Π° потрСбитСля 64-Π±ΠΈΡ‚ΠΎΠ²ΠΈ Ρ€Π΅Π³ΠΈΡΡ‚ΡŠΡ€Π° r0-r10 ΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ΅Π½ брояч. РСгистрирам r10 ΡΡŠΠ΄ΡŠΡ€ΠΆΠ° ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π» Π½Π° Ρ€Π°ΠΌΠΊΠ° ΠΈ Π΅ само Π·Π° Ρ‡Π΅Ρ‚Π΅Π½Π΅. ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅ ΠΈΠΌΠ°Ρ‚ Π΄ΠΎΡΡ‚ΡŠΠΏ Π΄ΠΎ 512-Π±Π°ΠΉΡ‚ΠΎΠ² стСк ΠΏΠΎ Π²Ρ€Π΅ΠΌΠ΅ Π½Π° изпълнСниС ΠΈ Π½Π΅ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΎ количСство сподСлСна ΠΏΠ°ΠΌΠ΅Ρ‚ ΠΏΠΎΠ΄ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π° Π½Π° ΠΊΠ°Ρ€Ρ‚ΠΈ.

На BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅ Π΅ Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΎ Π΄Π° ΠΈΠ·ΠΏΡŠΠ»Π½ΡΠ²Π°Ρ‚ спСцифичСн Π½Π°Π±ΠΎΡ€ ΠΎΡ‚ ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈΡ†ΠΈ Π½Π° ядрото ΠΎΡ‚ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ΅Π½ Ρ‚ΠΈΠΏ ΠΈ, наскоро, ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. Всяка ΠΈΠ·Π²ΠΈΠΊΠ°Π½Π° функция ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΏΡ€ΠΈΠ΅ΠΌΠ° Π΄ΠΎ ΠΏΠ΅Ρ‚ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π°, ΠΏΡ€Π΅Π΄Π°Π²Π°Π½ΠΈ Π² рСгистри r1-r5ΠΈ Π²ΡŠΡ€Π½Π°Ρ‚Π°Ρ‚Π° стойност сС ΠΏΡ€Π΅Π΄Π°Π²Π° Π½Π° r0. Π“Π°Ρ€Π°Π½Ρ‚ΠΈΡ€Π°Π½ΠΎ Π΅, Ρ‡Π΅ слСд Π²Ρ€ΡŠΡ‰Π°Π½Π΅ ΠΎΡ‚ функцията, ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π° рСгистритС r6-r9 Няма Π΄Π° сС ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈ.

Π—Π° Π΅Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π΅Π½ ΠΏΡ€Π΅Π²ΠΎΠ΄ Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ, рСгистри r0-r11 Π·Π° всички ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ°Π½ΠΈ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€ΠΈ са ΡƒΠ½ΠΈΠΊΠ°Π»Π½ΠΎ ΠΊΠ°Ρ€Ρ‚ΠΎΠ³Ρ€Π°Ρ„ΠΈΡ€Π°Π½ΠΈ към Ρ€Π΅Π°Π»Π½ΠΈ рСгистри, ΠΊΠ°Ρ‚ΠΎ сС Π²Π·Π΅ΠΌΠ°Ρ‚ ΠΏΡ€Π΅Π΄Π²ΠΈΠ΄ характСристикитС Π½Π° ABI Π½Π° Ρ‚Π΅ΠΊΡƒΡ‰Π°Ρ‚Π° Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π°. НапримСр Π·Π° x86_64 рСгистри r1-r5, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½ΠΈ Π·Π° ΠΏΡ€Π΅Π΄Π°Π²Π°Π½Π΅ Π½Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»Π½ΠΈ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈ, сС ΠΏΠΎΠΊΠ°Π·Π²Π°Ρ‚ Π½Π° rdi, rsi, rdx, rcx, r8, ΠΊΠΎΠΈΡ‚ΠΎ сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ Π·Π° ΠΏΡ€Π΅Π΄Π°Π²Π°Π½Π΅ Π½Π° ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈ Π½Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π½Π° x86_64. НапримСр ΠΊΠΎΠ΄ΡŠΡ‚ отляво сС ΠΏΡ€Π΅Π²Π΅ΠΆΠ΄Π° Π² ΠΊΠΎΠ΄Π° отдясно ΠΏΠΎ слСдния Π½Π°Ρ‡ΠΈΠ½:

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

РСгистрирам r0 ΡΡŠΡ‰ΠΎ сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π·Π° Π²Ρ€ΡŠΡ‰Π°Π½Π΅ Π½Π° Ρ€Π΅Π·ΡƒΠ»Ρ‚Π°Ρ‚Π° ΠΎΡ‚ ΠΈΠ·ΠΏΡŠΠ»Π½Π΅Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° ΠΈ Π² Ρ€Π΅Π³ΠΈΡΡ‚ΡŠΡ€Π° r1 Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° сС ΠΏΡ€Π΅Π΄Π°Π²Π° ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π» към контСкста - Π² зависимост ΠΎΡ‚ Π²ΠΈΠ΄Π° Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π°, Ρ‚ΠΎΠ²Π° ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ структура struct xdp_md (Π·Π° XDP) ΠΈΠ»ΠΈ структура struct __sk_buff (Π·Π° Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ ΠΌΡ€Π΅ΠΆΠΎΠ²ΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ) ΠΈΠ»ΠΈ структура struct pt_regs (Π·Π° Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ Π²ΠΈΠ΄ΠΎΠ²Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ Π·Π° прослСдяванС) ΠΈ Π΄Ρ€.

И Ρ‚Π°ΠΊΠ°, ΠΈΠΌΠ°Ρ…ΠΌΠ΅ Π½Π°Π±ΠΎΡ€ ΠΎΡ‚ рСгистри, ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈΡ†ΠΈ Π½Π° ядрото, стСк, контСкстСн ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π» ΠΈ сподСлСна ΠΏΠ°ΠΌΠ΅Ρ‚ ΠΏΠΎΠ΄ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π° Π½Π° ΠΊΠ°Ρ€Ρ‚ΠΈ. НС Ρ‡Π΅ всичко Ρ‚ΠΎΠ²Π° Π΅ Π°Π±ΡΠΎΠ»ΡŽΡ‚Π½ΠΎ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΠΎ Π²Ρ€Π΅ΠΌΠ΅ Π½Π° ΠΏΡŠΡ‚ΡƒΠ²Π°Π½Π΅Ρ‚ΠΎ, Π½ΠΎ...

НСка ΠΏΡ€ΠΎΠ΄ΡŠΠ»ΠΆΠΈΠΌ описаниСто ΠΈ Π΄Π° ΠΏΠΎΠ³ΠΎΠ²ΠΎΡ€ΠΈΠΌ Π·Π° ΠΊΠΎΠΌΠ°Π½Π΄Π½Π°Ρ‚Π° систСма Π·Π° Ρ€Π°Π±ΠΎΡ‚Π° с Ρ‚Π΅Π·ΠΈ ΠΎΠ±Π΅ΠΊΡ‚ΠΈ. Всичко (ΠŸΠΎΡ‡Ρ‚ΠΈ всички) BPF инструкциитС ΠΈΠΌΠ°Ρ‚ фиксиран 64-Π±ΠΈΡ‚ΠΎΠ² Ρ€Π°Π·ΠΌΠ΅Ρ€. Ако ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅Ρ‚Π΅ Π΅Π΄Π½Π° инструкция Π½Π° 64-Π±ΠΈΡ‚ΠΎΠ²Π° Big Endian машина, Ρ‰Π΅ Π²ΠΈΠ΄ΠΈΡ‚Π΅

BPF Π·Π° Π½Π°ΠΉ-ΠΌΠ°Π»ΠΊΠΈΡ‚Π΅, част ΠΏΡŠΡ€Π²Π°: Ρ€Π°Π·ΡˆΠΈΡ€Π΅Π½ BPF

Π’ΡƒΠΊ Code - Ρ‚ΠΎΠ²Π° Π΅ ΠΊΠΎΠ΄ΠΈΡ€Π°Π½Π΅Ρ‚ΠΎ Π½Π° инструкцията, Dst/Src са ΠΊΠΎΠ΄ΠΈΡ€ΠΎΠ²ΠΊΠΈΡ‚Π΅ ΡΡŠΠΎΡ‚Π²Π΅Ρ‚Π½ΠΎ Π½Π° ΠΏΡ€ΠΈΠ΅ΠΌΠ½ΠΈΠΊΠ° ΠΈ ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΠΊΠ°, Off - 16-Π±ΠΈΡ‚ΠΎΠ² ΠΎΡ‚ΡΡ‚ΡŠΠΏ със Π·Π½Π°ΠΊ ΠΈ Imm Π΅ 32-Π±ΠΈΡ‚ΠΎΠ²ΠΎ цяло число със Π·Π½Π°ΠΊ, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½ΠΎ Π² някои инструкции (ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎ Π½Π° cBPF константата K). ΠšΠΎΠ΄ΠΈΡ€Π°Π½Π΅ Code ΠΈΠΌΠ° Π΅Π΄ΠΈΠ½ ΠΎΡ‚ Π΄Π²Π°Ρ‚Π° Π²ΠΈΠ΄Π°:

BPF Π·Π° Π½Π°ΠΉ-ΠΌΠ°Π»ΠΊΠΈΡ‚Π΅, част ΠΏΡŠΡ€Π²Π°: Ρ€Π°Π·ΡˆΠΈΡ€Π΅Π½ BPF

КласовС инструкции 0, 1, 2, 3 Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π°Ρ‚ ΠΊΠΎΠΌΠ°Π½Π΄ΠΈ Π·Π° Ρ€Π°Π±ΠΎΡ‚Π° с ΠΏΠ°ΠΌΠ΅Ρ‚. Π’Π΅ са Π½Π°Ρ€Π΅Ρ‡Π΅Π½ΠΈ, BPF_LD, BPF_LDX, BPF_ST, BPF_STX, ΡΡŠΠΎΡ‚Π²Π΅Ρ‚Π½ΠΎ. КласовС 4, 7 (BPF_ALU, BPF_ALU64) прСдставляват Π½Π°Π±ΠΎΡ€ ΠΎΡ‚ ALU инструкции. КласовС 5, 6 (BPF_JMP, BPF_JMP32) ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Ρ‚ инструкции Π·Π° прСскачанС.

По-Π½Π°Ρ‚Π°Ρ‚ΡŠΡˆΠ½ΠΈΡΡ‚ ΠΏΠ»Π°Π½ Π·Π° ΠΈΠ·ΡƒΡ‡Π°Π²Π°Π½Π΅ Π½Π° систСмата Π·Π° инструкции Π½Π° BPF Π΅ слСдният: вмСсто Π΄Π° изброявамС Ρ‰Π°Ρ‚Π΅Π»Π½ΠΎ всички инструкции ΠΈ Ρ‚Π΅Ρ…Π½ΠΈΡ‚Π΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈ, Ρ‰Π΅ Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ няколко ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° Π² Ρ‚ΠΎΠ·ΠΈ Ρ€Π°Π·Π΄Π΅Π» ΠΈ ΠΎΡ‚ тях Ρ‰Π΅ станС ясно ΠΊΠ°ΠΊ Π²ΡΡŠΡ‰Π½ΠΎΡΡ‚ работят инструкциитС ΠΈ ΠΊΠ°ΠΊ Π΄Π° Ρ€ΡŠΡ‡Π½ΠΎ Ρ€Π°Π·Π³Π»ΠΎΠ±Π΅Ρ‚Π΅ всСки Π΄Π²ΠΎΠΈΡ‡Π΅Π½ Ρ„Π°ΠΉΠ» Π·Π° BPF. Π—Π° Π΄Π° консолидирамС ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Π° ΠΏΠΎ-късно Π² статията, Ρ‰Π΅ сС срСщнСм ΠΈ с ΠΎΡ‚Π΄Π΅Π»Π½ΠΈ инструкции Π² Ρ€Π°Π·Π΄Π΅Π»ΠΈΡ‚Π΅ Π·Π° Verifier, JIT ΠΊΠΎΠΌΠΏΠΈΠ»Π°Ρ‚ΠΎΡ€, ΠΏΡ€Π΅Π²ΠΎΠ΄ Π½Π° класичСски BPF, ΠΊΠ°ΠΊΡ‚ΠΎ ΠΈ ΠΏΡ€ΠΈ ΠΈΠ·ΡƒΡ‡Π°Π²Π°Π½Π΅ Π½Π° ΠΊΠ°Ρ€Ρ‚ΠΈ, ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅ Π½Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΈ Ρ‚.Π½.

ΠšΠΎΠ³Π°Ρ‚ΠΎ Π³ΠΎΠ²ΠΎΡ€ΠΈΠΌ Π·Π° ΠΎΡ‚Π΄Π΅Π»Π½ΠΈ инструкции, Ρ‰Π΅ Π³ΠΎΠ²ΠΎΡ€ΠΈΠΌ Π·Π° основнитС Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ bpf.h ΠΈ bpf_common.h, ΠΊΠΎΠΈΡ‚ΠΎ опрСдСлят Ρ†ΠΈΡ„Ρ€ΠΎΠ²ΠΈΡ‚Π΅ ΠΊΠΎΠ΄ΠΎΠ²Π΅ Π½Π° BPF инструкциитС. ΠšΠΎΠ³Π°Ρ‚ΠΎ ΠΈΠ·ΡƒΡ‡Π°Π²Π°Ρ‚Π΅ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π° самостоятСлно ΠΈ/ΠΈΠ»ΠΈ Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€Π°Ρ‚Π΅ Π΄Π²ΠΎΠΈΡ‡Π½ΠΈ Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅, ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π½Π°ΠΌΠ΅Ρ€ΠΈΡ‚Π΅ сСмантика Π² слСднитС ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΡ†ΠΈ, сортирани ΠΏΠΎ слоТност: НСофициална спСцификация Π½Π° eBPF, Π‘ΠΏΡ€Π°Π²ΠΎΡ‡Π½ΠΎ Ρ€ΡŠΠΊΠΎΠ²ΠΎΠ΄ΡΡ‚Π²ΠΎ Π·Π° BPF ΠΈ XDP, Π½Π°Π±ΠΎΡ€ ΠΎΡ‚ инструкции, Documentation/networking/filter.txt ΠΈ, Ρ€Π°Π·Π±ΠΈΡ€Π° сС, Π² изходния ΠΊΠΎΠ΄ Π½Π° Linux - Π²Π΅Ρ€ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€, JIT, BPF ΠΈΠ½Ρ‚Π΅Ρ€ΠΏΡ€Π΅Ρ‚Π°Ρ‚ΠΎΡ€.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€: разглобяванС Π½Π° BPF Π² Π³Π»Π°Π²Π°Ρ‚Π° Π²ΠΈ

НСка Π΄Π° Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π² ΠΊΠΎΠΉΡ‚ΠΎ ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€Π°ΠΌΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° readelf-example.c ΠΈ ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅Ρ‚Π΅ получСния Π΄Π²ΠΎΠΈΡ‡Π΅Π½ Ρ„Π°ΠΉΠ». НиС Ρ‰Π΅ Ρ€Π°Π·ΠΊΡ€ΠΈΠ΅ΠΌ ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»Π½ΠΎΡ‚ΠΎ ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Π½ΠΈΠ΅ readelf-example.c ΠΏΠΎ-Π΄ΠΎΠ»Ρƒ, слСд ΠΊΠ°Ρ‚ΠΎ Π²ΡŠΠ·ΡΡ‚Π°Π½ΠΎΠ²ΠΈΠΌ Π»ΠΎΠ³ΠΈΠΊΠ°Ρ‚Π° ΠΌΡƒ ΠΎΡ‚ Π΄Π²ΠΎΠΈΡ‡Π½ΠΈ ΠΊΠΎΠ΄ΠΎΠ²Π΅:

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

ΠŸΡŠΡ€Π²Π°Ρ‚Π° ΠΊΠΎΠ»ΠΎΠ½Π° Π² ΠΈΠ·Ρ…ΠΎΠ΄Π° readelf Π΅ ΠΎΡ‚ΡΡ‚ΡŠΠΏ ΠΈ Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° сС ΡΡŠΡΡ‚ΠΎΠΈ ΠΎΡ‚ Ρ‡Π΅Ρ‚ΠΈΡ€ΠΈ ΠΊΠΎΠΌΠ°Π½Π΄ΠΈ:

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

ΠšΠΎΠ΄ΠΎΠ²Π΅Ρ‚Π΅ Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄ΠΈΡ‚Π΅ са Π΅Π΄Π½Π°ΠΊΠ²ΠΈ b7, 15, b7 ΠΈ 95. Π‘ΠΏΠΎΠΌΠ½Π΅Ρ‚Π΅ си, Ρ‡Π΅ Π½Π°ΠΉ-ΠΌΠ°Π»ΠΊΠΎ Π·Π½Π°Ρ‡ΠΈΠΌΠΈΡ‚Π΅ Ρ‚Ρ€ΠΈ Π±ΠΈΡ‚Π° са ΠΊΠ»Π°ΡΡŠΡ‚ Π½Π° инструкцията. Π’ нашия случай Ρ‡Π΅Ρ‚Π²ΡŠΡ€Ρ‚ΠΈΡΡ‚ Π±ΠΈΡ‚ ΠΎΡ‚ всички инструкции Π΅ ΠΏΡ€Π°Π·Π΅Π½, Ρ‚Π°ΠΊΠ° Ρ‡Π΅ класовСтС инструкции са ΡΡŠΠΎΡ‚Π²Π΅Ρ‚Π½ΠΎ 7, 5, 7, 5. Клас 7 Π΅ BPF_ALU64, Π° 5 Π΅ BPF_JMP. И Π·Π° Π΄Π²Π°Ρ‚Π° класа Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΡŠΡ‚ Π½Π° инструкциитС Π΅ Π΅Π΄ΠΈΠ½ ΠΈ ΡΡŠΡ‰ (Π²ΠΈΠΆΡ‚Π΅ ΠΏΠΎ-Π³ΠΎΡ€Π΅) ΠΈ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΏΡ€Π΅Π½Π°ΠΏΠΈΡˆΠ΅ΠΌ Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° ΠΏΠΎ Ρ‚ΠΎΠ·ΠΈ Π½Π°Ρ‡ΠΈΠ½ (Π² ΡΡŠΡ‰ΠΎΡ‚ΠΎ Π²Ρ€Π΅ΠΌΠ΅ Ρ‰Π΅ ΠΏΡ€Π΅Π½Π°ΠΏΠΈΡˆΠ΅ΠΌ останалитС ΠΊΠΎΠ»ΠΎΠ½ΠΈ Π² Ρ‡ΠΎΠ²Π΅ΡˆΠΊΠ° Ρ„ΠΎΡ€ΠΌΠ°):

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

ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΡ b клас ALU64 - BPF_MOV. Π’ΠΎΠΉ присвоява стойност Π½Π° цСлСвия Ρ€Π΅Π³ΠΈΡΡ‚ΡŠΡ€. Ако Π±ΠΈΡ‚ΡŠΡ‚ Π΅ Π·Π°Π΄Π°Π΄Π΅Π½ s (ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ), Ρ‚ΠΎΠ³Π°Π²Π° стойността сС Π²Π·Π΅ΠΌΠ° ΠΎΡ‚ Ρ€Π΅Π³ΠΈΡΡ‚ΡŠΡ€Π° ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ, Π° Π°ΠΊΠΎ, ΠΊΠ°ΠΊΡ‚ΠΎ Π² нашия случай, Π½Π΅ Π΅ Π·Π°Π΄Π°Π΄Π΅Π½, Ρ‚ΠΎΠ³Π°Π²Π° стойността сС Π²Π·Π΅ΠΌΠ° ΠΎΡ‚ ΠΏΠΎΠ»Π΅Ρ‚ΠΎ Imm. Π’Π°ΠΊΠ° Ρ‡Π΅ Π² ΠΏΡŠΡ€Π²Π°Ρ‚Π° ΠΈ Ρ‚Ρ€Π΅Ρ‚Π°Ρ‚Π° инструкция ΠΈΠ·Π²ΡŠΡ€ΡˆΠ²Π°ΠΌΠ΅ опСрацията r0 = Imm. ОсвСн Ρ‚ΠΎΠ²Π° JMP клас 1 опСрация Π΅ BPF_JEQ (скочи, Π°ΠΊΠΎ Π΅ Ρ€Π°Π²Π½ΠΎ). Π’ нашия случай, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Π±ΠΈΡ‚ S Π΅ Π½ΡƒΠ»Π°, Ρ‚ΠΎΠΉ сравнява стойността Π½Π° изходния Ρ€Π΅Π³ΠΈΡΡ‚ΡŠΡ€ с ΠΏΠΎΠ»Π΅Ρ‚ΠΎ Imm. Ако стойноститС ΡΡŠΠ²ΠΏΠ°Π΄Π°Ρ‚, Ρ‚ΠΎΠ³Π°Π²Π° сС ΠΈΠ·Π²ΡŠΡ€ΡˆΠ²Π° ΠΏΡ€Π΅Ρ…ΠΎΠ΄ΡŠΡ‚ към PC + OffΠšΡŠΠ΄Π΅Ρ‚ΠΎ PC, ΠΊΠ°ΠΊΡ‚ΠΎ ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ, ΡΡŠΠ΄ΡŠΡ€ΠΆΠ° адрСса Π½Π° слСдващата инструкция. И накрая, JMP Class 9 Operation Π΅ BPF_EXIT. Π’Π°Π·ΠΈ инструкция прСкратява ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π°, Π²Ρ€ΡŠΡ‰Π°ΠΉΠΊΠΈ сС към ядрото r0. НСка Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Π½ΠΎΠ²Π° ΠΊΠΎΠ»ΠΎΠ½Π° към Π½Π°ΡˆΠ°Ρ‚Π° Ρ‚Π°Π±Π»ΠΈΡ†Π°:

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

МоТСм Π΄Π° ΠΏΡ€Π΅Π½Π°ΠΏΠΈΡˆΠ΅ΠΌ Ρ‚ΠΎΠ²Π° Π² ΠΏΠΎ-ΡƒΠ΄ΠΎΠ±Π½Π° Ρ„ΠΎΡ€ΠΌΠ°:

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

Ако си спомним ΠΊΠ°ΠΊΠ²ΠΎ ΠΈΠΌΠ° Π² Ρ€Π΅Π³ΠΈΡΡ‚ΡŠΡ€Π° r1 Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° сС ΠΏΡ€Π΅Π΄Π°Π²Π° ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π» към контСкста ΠΎΡ‚ ядрото ΠΈ Π² Ρ€Π΅Π³ΠΈΡΡ‚ΡŠΡ€Π° r0 стойността сС Π²Ρ€ΡŠΡ‰Π° Π½Π° ядрото, Ρ‚ΠΎΠ³Π°Π²Π° ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Π²ΠΈΠ΄ΠΈΠΌ, Ρ‡Π΅ Π°ΠΊΠΎ указатСлят към контСкста Π΅ Π½ΡƒΠ»Π°, Ρ‚ΠΎΠ³Π°Π²Π° Π²Ρ€ΡŠΡ‰Π°ΠΌΠ΅ 1, Π° Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π΅Π½ случай - 2. НСка ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΠΌ Π΄Π°Π»ΠΈ смС ΠΏΡ€Π°Π²ΠΈ, ΠΊΠ°Ρ‚ΠΎ ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅ΠΌ ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΠΊΠ°:

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

Π”Π°, Ρ‚ΠΎΠ²Π° Π΅ бСзсмислСна ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°, Π½ΠΎ сС ΠΏΡ€Π΅Π²Π΅ΠΆΠ΄Π° само Π² Ρ‡Π΅Ρ‚ΠΈΡ€ΠΈ прости инструкции.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° ΠΈΠ·ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅: 16-Π±Π°ΠΉΡ‚ΠΎΠ²Π° инструкция

По-Ρ€Π°Π½ΠΎ спомСнахмС, Ρ‡Π΅ някои инструкции Π·Π°Π΅ΠΌΠ°Ρ‚ ΠΏΠΎΠ²Π΅Ρ‡Π΅ ΠΎΡ‚ 64 Π±ΠΈΡ‚Π°. Π’ΠΎΠ²Π° сС отнася Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° инструкциитС lddw (Код = 0x18 = BPF_LD | BPF_DW | BPF_IMM) β€” Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅ Π½Π° Π΄Π²ΠΎΠΉΠ½Π° Π΄ΡƒΠΌΠ° ΠΎΡ‚ ΠΏΠΎΠ»Π΅Ρ‚Π°Ρ‚Π° Π² Ρ€Π΅Π³ΠΈΡΡ‚ΡŠΡ€Π° Imm, Π€Π°ΠΊΡ‚ Π΅, Ρ‡Π΅ Imm ΠΈΠΌΠ° Ρ€Π°Π·ΠΌΠ΅Ρ€ 32, Π° Π΄Π²ΠΎΠΉΠ½Π°Ρ‚Π° Π΄ΡƒΠΌΠ° Π΅ 64 Π±ΠΈΡ‚Π°, Ρ‚Π°ΠΊΠ° Ρ‡Π΅ Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅Ρ‚ΠΎ Π½Π° 64-Π±ΠΈΡ‚ΠΎΠ²Π° нСпосрСдствСна стойност Π² Ρ€Π΅Π³ΠΈΡΡ‚ΡŠΡ€ Π² Π΅Π΄Π½Π° 64-Π±ΠΈΡ‚ΠΎΠ²Π° инструкция няма Π΄Π° Ρ€Π°Π±ΠΎΡ‚ΠΈ. Π—Π° Π΄Π° Π½Π°ΠΏΡ€Π°Π²ΠΈΡ‚Π΅ Ρ‚ΠΎΠ²Π°, Π΄Π²Π΅ съсСдни инструкции сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ Π·Π° ΡΡŠΡ…Ρ€Π°Π½ΡΠ²Π°Π½Π΅ Π½Π° Π²Ρ‚ΠΎΡ€Π°Ρ‚Π° част ΠΎΡ‚ 64-Π±ΠΈΡ‚ΠΎΠ²Π°Ρ‚Π° стойност Π² ΠΏΠΎΠ»Π΅Ρ‚ΠΎ Imm, ΠŸΡ€ΠΈΠΌΠ΅Ρ€:

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

Има само Π΄Π²Π΅ инструкции Π² Π΅Π΄Π½Π° Π΄Π²ΠΎΠΈΡ‡Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°:

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

Π©Π΅ сС срСщнСм ΠΎΡ‚Π½ΠΎΠ²ΠΎ с инструкции lddw, ΠΊΠΎΠ³Π°Ρ‚ΠΎ Π³ΠΎΠ²ΠΎΡ€ΠΈΠΌ Π·Π° прСмСствания ΠΈ Ρ€Π°Π±ΠΎΡ‚Π° с ΠΊΠ°Ρ€Ρ‚ΠΈ.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€: разглобяванС Π½Π° BPF с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° стандартни инструмСнти

И Ρ‚Π°ΠΊΠ°, Π½ΠΈΠ΅ сС Π½Π°ΡƒΡ‡ΠΈΡ…ΠΌΠ΅ Π΄Π° Ρ‡Π΅Ρ‚Π΅ΠΌ BPF Π΄Π²ΠΎΠΈΡ‡Π½ΠΈ ΠΊΠΎΠ΄ΠΎΠ²Π΅ ΠΈ смС Π³ΠΎΡ‚ΠΎΠ²ΠΈ Π΄Π° Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€Π°ΠΌΠ΅ всяка инструкция, Π°ΠΊΠΎ Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ. Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‚ΠΎΠ²Π° си струва Π΄Π° сС ΠΊΠ°ΠΆΠ΅, Ρ‡Π΅ Π½Π° ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ° Π΅ ΠΏΠΎ-ΡƒΠ΄ΠΎΠ±Π½ΠΎ ΠΈ ΠΏΠΎ-Π±ΡŠΡ€Π·ΠΎ Π΄Π° разглобяватС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° стандартни инструмСнти, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€:

$ llvm-objdump -d x64.o

Disassembly of section .text:

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

Π–ΠΈΠ·Π½Π΅Π½ Ρ†ΠΈΠΊΡŠΠ» Π½Π° BPF ΠΎΠ±Π΅ΠΊΡ‚ΠΈ, bpffs Ρ„Π°ΠΉΠ»ΠΎΠ²Π° систСма

(Π—Π° ΠΏΡŠΡ€Π²ΠΈ ΠΏΡŠΡ‚ Π½Π°ΡƒΡ‡ΠΈΡ… някои ΠΎΡ‚ подробноститС, описани Π² Ρ‚ΠΎΠ·ΠΈ ΠΏΠΎΠ΄Ρ€Π°Π·Π΄Π΅Π» ΠΎΡ‚ пост АлСксСй Π‘Ρ‚Π°Ρ€ΠΎΠ²ΠΎΠΉΡ‚ΠΎΠ² Π² Π‘Π»ΠΎΠ³ Π½Π° БНЀ.)

BPF ΠΎΠ±Π΅ΠΊΡ‚ΠΈ - ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ ΠΈ ΠΊΠ°Ρ€Ρ‚ΠΈ - сС ΡΡŠΠ·Π΄Π°Π²Π°Ρ‚ ΠΎΡ‚ потрСбитСлско пространство с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄ΠΈ BPF_PROG_LOAD ΠΈ BPF_MAP_CREATE систСмно ΠΏΠΎΠ²ΠΈΠΊΠ²Π°Π½Π΅ bpf(2), Ρ‰Π΅ Π³ΠΎΠ²ΠΎΡ€ΠΈΠΌ ΠΊΠ°ΠΊ Ρ‚ΠΎΡ‡Π½ΠΎ сС случва Ρ‚ΠΎΠ²Π° Π² слСдващия Ρ€Π°Π·Π΄Π΅Π». Π’ΠΎΠ²Π° създава структури ΠΎΡ‚ Π΄Π°Π½Π½ΠΈ Π½Π° ядрото ΠΈ Π·Π° всяка ΠΎΡ‚ тях refcount (Π±Ρ€ΠΎΠΉ ΠΏΡ€Π΅ΠΏΡ€Π°Ρ‚ΠΊΠΈ) Π΅ Π·Π°Π΄Π°Π΄Π΅Π½ Π½Π° Π΅Π΄Π½ΠΎ ΠΈ Ρ„Π°ΠΉΠ»ΠΎΠ² дСскриптор, сочСщ към ΠΎΠ±Π΅ΠΊΡ‚Π°, сС Π²Ρ€ΡŠΡ‰Π° Π½Π° потрСбитСля. Π‘Π»Π΅Π΄ ΠΊΠ°Ρ‚ΠΎ Π΄Ρ€ΡŠΠΆΠΊΠ°Ρ‚Π° Π΅ Π·Π°Ρ‚Π²ΠΎΡ€Π΅Π½Π° refcount ΠΎΠ±Π΅ΠΊΡ‚ΡŠΡ‚ сС намалява с Π΅Π΄ΠΈΠ½ΠΈΡ†Π° ΠΈ ΠΊΠΎΠ³Π°Ρ‚ΠΎ достигнС Π½ΡƒΠ»Π°, ΠΎΠ±Π΅ΠΊΡ‚ΡŠΡ‚ сС ΡƒΠ½ΠΈΡ‰ΠΎΠΆΠ°Π²Π°.

Ако ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° ΠΊΠ°Ρ€Ρ‚ΠΈ, Ρ‚ΠΎΠ³Π°Π²Π° refcount Ρ‚Π΅Π·ΠΈ ΠΊΠ°Ρ€Ρ‚ΠΈ сС ΡƒΠ²Π΅Π»ΠΈΡ‡Π°Π²Π°Ρ‚ с Π΅Π΄ΠΈΠ½ΠΈΡ†Π° слСд Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅ Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π°, Ρ‚.Π΅. Ρ‚Π΅Ρ…Π½ΠΈΡ‚Π΅ Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΈ дСскриптори ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ Π·Π°Ρ‚Π²ΠΎΡ€Π΅Π½ΠΈ ΠΎΡ‚ потрСбитСлския процСс ΠΈ ΠΏΠ°ΠΊ refcount няма Π΄Π° станС Π½ΡƒΠ»Π°:

BPF Π·Π° Π½Π°ΠΉ-ΠΌΠ°Π»ΠΊΠΈΡ‚Π΅, част ΠΏΡŠΡ€Π²Π°: Ρ€Π°Π·ΡˆΠΈΡ€Π΅Π½ BPF

Π‘Π»Π΅Π΄ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅ Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°, ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ я ΠΏΡ€ΠΈΠΊΠ°Ρ‡Π²Π°ΠΌΠ΅ към някакъв Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ Π½Π° ΡΡŠΠ±ΠΈΡ‚ΠΈΡ. НапримСр, ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Π³ΠΎ поставим Π½Π° ΠΌΡ€Π΅ΠΆΠΎΠ² интСрфСйс, Π·Π° Π΄Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π²Π° входящи ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ ΠΈΠ»ΠΈ Π΄Π° Π³ΠΎ ΡΠ²ΡŠΡ€ΠΆΠ΅ΠΌ с някои tracepoint Π² ΡΡŠΡ€Ρ†Π΅Π²ΠΈΠ½Π°Ρ‚Π°. Π’ Ρ‚ΠΎΠ·ΠΈ ΠΌΠΎΠΌΠ΅Π½Ρ‚ Π±Ρ€ΠΎΡΡ‡ΡŠΡ‚ Π½Π° ΠΏΡ€Π΅ΠΏΡ€Π°Ρ‚ΠΊΠΈΡ‚Π΅ ΡΡŠΡ‰ΠΎ Ρ‰Π΅ сС ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈ с Π΅Π΄ΠΈΠ½ΠΈΡ†Π° ΠΈ Ρ‰Π΅ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Π·Π°Ρ‚Π²ΠΎΡ€ΠΈΠΌ файловия дСскриптор Π² ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° Π·Π° Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅.

Какво сС случва, Π°ΠΊΠΎ сСга ΠΈΠ·ΠΊΠ»ΡŽΡ‡ΠΈΠΌ Π±ΡƒΡƒΡ‚Π»ΠΎΡƒΠ΄ΡŠΡ€Π°? Зависи ΠΎΡ‚ Ρ‚ΠΈΠΏΠ° Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ Π½Π° ΡΡŠΠ±ΠΈΡ‚ΠΈΡ (ΠΊΡƒΠΊΠ°). Всички ΠΌΡ€Π΅ΠΆΠΎΠ²ΠΈ ΠΊΡƒΠΊΠΈΡ‡ΠΊΠΈ Ρ‰Π΅ ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π°Ρ‚ слСд Π·Π°Π²ΡŠΡ€ΡˆΠ²Π°Π½Π΅ Π½Π° Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅Ρ‚ΠΎ, Ρ‚ΠΎΠ²Π° са Ρ‚Π°ΠΊΠ° Π½Π°Ρ€Π΅Ρ‡Π΅Π½ΠΈΡ‚Π΅ Π³Π»ΠΎΠ±Π°Π»Π½ΠΈ ΠΊΡƒΠΊΠΈΡ‡ΠΊΠΈ. И, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅ Π·Π° прослСдяванС Ρ‰Π΅ Π±ΡŠΠ΄Π°Ρ‚ освободСни слСд прСкратяванС Π½Π° процСса, ΠΊΠΎΠΉΡ‚ΠΎ Π³ΠΈ Π΅ създал (ΠΈ Π·Π°Ρ‚ΠΎΠ²Π° сС Π½Π°Ρ€ΠΈΡ‡Π°Ρ‚ ​​локални, ΠΎΡ‚ β€žΠ»ΠΎΠΊΠ°Π»Π½ΠΈ към ΠΏΡ€ΠΎΡ†Π΅ΡΠ°β€œ). ВСхничСски, Π»ΠΎΠΊΠ°Π»Π½ΠΈΡ‚Π΅ ΠΊΡƒΠΊΠΈΡ‡ΠΊΠΈ Π²ΠΈΠ½Π°Π³ΠΈ ΠΈΠΌΠ°Ρ‚ ΡΡŠΠΎΡ‚Π²Π΅Ρ‚Π΅Π½ Ρ„Π°ΠΉΠ»ΠΎΠ² дСскриптор Π² потрСбитСлското пространство ΠΈ слСдоватСлно сС затварят, ΠΊΠΎΠ³Π°Ρ‚ΠΎ ΠΏΡ€ΠΎΡ†Π΅ΡΡŠΡ‚ Π΅ Π·Π°Ρ‚Π²ΠΎΡ€Π΅Π½, Π½ΠΎ Π³Π»ΠΎΠ±Π°Π»Π½ΠΈΡ‚Π΅ ΠΊΡƒΠΊΠΈΡ‡ΠΊΠΈ Π½Π΅ Π³ΠΎ правят. На слСдващата Ρ„ΠΈΠ³ΡƒΡ€Π°, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ Ρ‡Π΅Ρ€Π²Π΅Π½ΠΈ ΠΊΡ€ΡŠΡΡ‚ΠΎΠ²Π΅, сС ΠΎΠΏΠΈΡ‚Π²Π°ΠΌ Π΄Π° ΠΏΠΎΠΊΠ°ΠΆΠ° ΠΊΠ°ΠΊ прСкратяванСто Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° Π·Π° Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅ влияС Π½Π° ΠΆΠΈΠ²ΠΎΡ‚Π° Π½Π° ΠΎΠ±Π΅ΠΊΡ‚ΠΈΡ‚Π΅ Π² случай Π½Π° Π»ΠΎΠΊΠ°Π»Π½ΠΈ ΠΈ Π³Π»ΠΎΠ±Π°Π»Π½ΠΈ ΠΊΡƒΠΊΠΈΡ‡ΠΊΠΈ.

BPF Π·Π° Π½Π°ΠΉ-ΠΌΠ°Π»ΠΊΠΈΡ‚Π΅, част ΠΏΡŠΡ€Π²Π°: Ρ€Π°Π·ΡˆΠΈΡ€Π΅Π½ BPF

Π—Π°Ρ‰ΠΎ ΠΈΠΌΠ° Ρ€Π°Π·Π»ΠΈΠΊΠ° ΠΌΠ΅ΠΆΠ΄Ρƒ Π»ΠΎΠΊΠ°Π»Π½ΠΈ ΠΈ Π³Π»ΠΎΠ±Π°Π»Π½ΠΈ ΠΊΡƒΠΊΠΈΡ‡ΠΊΠΈ? Π˜Π·ΠΏΡŠΠ»Π½Π΅Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π° някои Π²ΠΈΠ΄ΠΎΠ²Π΅ ΠΌΡ€Π΅ΠΆΠΎΠ²ΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ ΠΈΠΌΠ° смисъл Π±Π΅Π· потрСбитСлско пространство, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, прСдставСтС си DDoS Π·Π°Ρ‰ΠΈΡ‚Π° - Π±ΡƒΡƒΡ‚Π»ΠΎΡƒΠ΄ΡŠΡ€ΡŠΡ‚ пишС ΠΏΡ€Π°Π²ΠΈΠ»Π°Ρ‚Π° ΠΈ ΡΠ²ΡŠΡ€Π·Π²Π° BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° към мрСТовия интСрфСйс, слСд ΠΊΠΎΠ΅Ρ‚ΠΎ Π±ΡƒΡƒΡ‚Π»ΠΎΡƒΠ΄ΡŠΡ€ΡŠΡ‚ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΎΡ‚ΠΈΠ΄Π΅ ΠΈ Π΄Π° сС самоубиС. ΠžΡ‚ Π΄Ρ€ΡƒΠ³Π° страна, прСдставСтС си ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Π·Π° прослСдяванС Π½Π° Π³Ρ€Π΅ΡˆΠΊΠΈ, която стС написали Π½Π° ΠΊΠΎΠ»Π΅Π½Π΅ Π·Π° дСсСт ΠΌΠΈΠ½ΡƒΡ‚ΠΈ - ΠΊΠΎΠ³Π°Ρ‚ΠΎ Π΅ Π·Π°Π²ΡŠΡ€ΡˆΠ΅Π½Π°, Π±ΠΈΡ…Ρ‚Π΅ искали Π΄Π° няма оставСн Π±ΠΎΠΊΠ»ΡƒΠΊ Π² систСмата ΠΈ Π»ΠΎΠΊΠ°Π»Π½ΠΈΡ‚Π΅ ΠΊΡƒΠΊΠΈΡ‡ΠΊΠΈ Ρ‰Π΅ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€Π°Ρ‚ Ρ‚ΠΎΠ²Π°.

ΠžΡ‚ Π΄Ρ€ΡƒΠ³Π° страна, прСдставСтС си, Ρ‡Π΅ искатС Π΄Π° сС ΡΠ²ΡŠΡ€ΠΆΠ΅Ρ‚Π΅ с tracepoint Π² ядрото ΠΈ Π΄Π° ΡΡŠΠ±ΠΈΡ€Π°Ρ‚Π΅ статистика Π·Π° ΠΌΠ½ΠΎΠ³ΠΎ Π³ΠΎΠ΄ΠΈΠ½ΠΈ. Π’ Ρ‚ΠΎΠ·ΠΈ случай Π±ΠΈΡ…Ρ‚Π΅ искали Π΄Π° Π·Π°Π²ΡŠΡ€ΡˆΠΈΡ‚Π΅ потрСбитСлската част ΠΈ Π΄Π° сС Π²Ρ€ΡŠΡ‰Π°Ρ‚Π΅ към статистиката ΠΎΡ‚ Π²Ρ€Π΅ΠΌΠ΅ Π½Π° Π²Ρ€Π΅ΠΌΠ΅. Π€Π°ΠΉΠ»ΠΎΠ²Π°Ρ‚Π° систСма bpf прСдоставя Ρ‚Π°Π·ΠΈ Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚. Π’ΠΎΠ²Π° Π΅ псСвдофайлова систСма само Π² ΠΏΠ°ΠΌΠ΅Ρ‚Ρ‚Π°, която позволява ΡΡŠΠ·Π΄Π°Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅, ΠΊΠΎΠΈΡ‚ΠΎ ΠΏΡ€Π΅ΠΏΡ€Π°Ρ‰Π°Ρ‚ към BPF ΠΎΠ±Π΅ΠΊΡ‚ΠΈ ΠΈ ΠΏΠΎ Ρ‚ΠΎΠ·ΠΈ Π½Π°Ρ‡ΠΈΠ½ ΡƒΠ²Π΅Π»ΠΈΡ‡Π°Π²Π°Ρ‚ refcount ΠΎΠ±Π΅ΠΊΡ‚ΠΈ. Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° Ρ‚ΠΎΠ²Π°Ρ€Π°Ρ‡ΡŠΡ‚ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΈΠ·Π»Π΅Π·Π΅ ΠΈ ΡΡŠΠ·Π΄Π°Π΄Π΅Π½ΠΈΡ‚Π΅ ΠΎΡ‚ Π½Π΅Π³ΠΎ ΠΎΠ±Π΅ΠΊΡ‚ΠΈ Ρ‰Π΅ останат ΠΆΠΈΠ²ΠΈ.

BPF Π·Π° Π½Π°ΠΉ-ΠΌΠ°Π»ΠΊΠΈΡ‚Π΅, част ΠΏΡŠΡ€Π²Π°: Ρ€Π°Π·ΡˆΠΈΡ€Π΅Π½ BPF

Π‘ΡŠΠ·Π΄Π°Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ Π² bpffs, ΠΊΠΎΠΈΡ‚ΠΎ ΠΏΡ€Π΅ΠΏΡ€Π°Ρ‰Π°Ρ‚ към BPF ΠΎΠ±Π΅ΠΊΡ‚ΠΈ, сС Π½Π°Ρ€ΠΈΡ‡Π° "Π·Π°ΠΊΡ€Π΅ΠΏΠ²Π°Π½Π΅" (ΠΊΠ°ΠΊΡ‚ΠΎ Π² слСдната Ρ„Ρ€Π°Π·Π°: "ΠΏΡ€ΠΎΡ†Π΅ΡΡŠΡ‚ ΠΌΠΎΠΆΠ΅ Π΄Π° Π·Π°ΠΊΠ°Ρ‡ΠΈ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° ΠΈΠ»ΠΈ ΠΊΠ°Ρ€Ρ‚Π°"). Π‘ΡŠΠ·Π΄Π°Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΈ ΠΎΠ±Π΅ΠΊΡ‚ΠΈ Π·Π° BPF ΠΎΠ±Π΅ΠΊΡ‚ΠΈ ΠΈΠΌΠ° смисъл Π½Π΅ само Π·Π° ΡƒΠ΄ΡŠΠ»ΠΆΠ°Π²Π°Π½Π΅ Π½Π° ΠΆΠΈΠ²ΠΎΡ‚Π° Π½Π° Π»ΠΎΠΊΠ°Π»Π½ΠΈΡ‚Π΅ ΠΎΠ±Π΅ΠΊΡ‚ΠΈ, Π½ΠΎ ΠΈ Π·Π° използваСмостта Π½Π° Π³Π»ΠΎΠ±Π°Π»Π½ΠΈΡ‚Π΅ ΠΎΠ±Π΅ΠΊΡ‚ΠΈ - Π²Ρ€ΡŠΡ‰Π°ΠΉΠΊΠΈ сС към ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° с Π³Π»ΠΎΠ±Π°Π»Π½Π°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Π·Π° Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, искамС Π΄Π° ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Π΄ΠΎΠΉΠ΄Π΅ΠΌ ΠΈ Π΄Π° Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ статистикитС ΠΎΡ‚ Π²Ρ€Π΅ΠΌΠ΅ Π½Π° Π²Ρ€Π΅ΠΌΠ΅.

Π€Π°ΠΉΠ»ΠΎΠ²Π°Ρ‚Π° систСма BPF ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ сС ΠΌΠΎΠ½Ρ‚ΠΈΡ€Π° Π² /sys/fs/bpf, Π½ΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΌΠΎΠ½Ρ‚ΠΈΡ€Π° ΠΈ Π»ΠΎΠΊΠ°Π»Π½ΠΎ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Ρ‚Π°ΠΊΠ°:

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

Π˜ΠΌΠ΅Π½Π°Ρ‚Π° Π½Π° Ρ„Π°ΠΉΠ»ΠΎΠ²Π°Ρ‚Π° систСма сС ΡΡŠΠ·Π΄Π°Π²Π°Ρ‚ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄Π°Ρ‚Π° BPF_OBJ_PIN BPF систСмно ΠΏΠΎΠ²ΠΈΠΊΠ²Π°Π½Π΅. Π—Π° Π΄Π° ΠΈΠ»ΡŽΡΡ‚Ρ€ΠΈΡ€Π°ΠΌΠ΅, Π½Π΅ΠΊΠ° Π²Π·Π΅ΠΌΠ΅ΠΌ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°, ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€Π°ΠΌΠ΅ я, ΠΊΠ°Ρ‡ΠΈΠΌ я ΠΈ я Π·Π°ΠΊΡ€Π΅ΠΏΠΈΠΌ към bpffs. ΠΠ°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Π½Π΅ ΠΏΡ€Π°Π²ΠΈ Π½ΠΈΡ‰ΠΎ ΠΏΠΎΠ»Π΅Π·Π½ΠΎ, Π½ΠΈΠ΅ само прСдставямС ΠΊΠΎΠ΄Π°, Π·Π° Π΄Π° ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π²ΡŠΠ·ΠΏΡ€ΠΎΠΈΠ·Π²Π΅Π΄Π΅Ρ‚Π΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°:

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

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

НСка ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€Π°ΠΌΠ΅ Ρ‚Π°Π·ΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° ΠΈ създадСм Π»ΠΎΠΊΠ°Π»Π½ΠΎ ΠΊΠΎΠΏΠΈΠ΅ Π½Π° Ρ„Π°ΠΉΠ»ΠΎΠ²Π°Ρ‚Π° систСма bpffs:

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

Π‘Π΅Π³Π° Π½Π΅ΠΊΠ° ΠΈΠ·Ρ‚Π΅Π³Π»ΠΈΠΌ Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° ΠΏΠΎΠΌΠΎΡ‰Π½Π°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° bpftool ΠΈ ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅Ρ‚Π΅ ΠΏΡ€ΠΈΠ΄Ρ€ΡƒΠΆΠ°Π²Π°Ρ‰ΠΈΡ‚Π΅ систСмни повиквания bpf(2) (някои нСподходящи Ρ€Π΅Π΄ΠΎΠ²Π΅ са ΠΏΡ€Π΅ΠΌΠ°Ρ…Π½Π°Ρ‚ΠΈ ΠΎΡ‚ ΠΈΠ·Ρ…ΠΎΠ΄Π° Π½Π° strace):

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

Π’ΡƒΠΊ Π·Π°Ρ€Π΅Π΄ΠΈΡ…ΠΌΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° BPF_PROG_LOAD, ΠΏΠΎΠ»ΡƒΡ‡ΠΈ Ρ„Π°ΠΉΠ»ΠΎΠ² дСскриптор ΠΎΡ‚ ядрото 3 ΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ ΠΊΠΎΠΌΠ°Π½Π΄Π°Ρ‚Π° BPF_OBJ_PIN фиксира Ρ‚ΠΎΠ·ΠΈ Ρ„Π°ΠΉΠ»ΠΎΠ² дСскриптор ΠΊΠ°Ρ‚ΠΎ Ρ„Π°ΠΉΠ» "bpf-mountpoint/test". Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° Π·Π° Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅ bpftool ΠΏΡ€ΠΈΠΊΠ»ΡŽΡ‡ΠΈ Ρ€Π°Π±ΠΎΡ‚Π°, Π½ΠΎ Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° остана Π² ядрото, Π²ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‡Π΅ Π½Π΅ я ΠΏΡ€ΠΈΠΊΠ°Ρ‡ΠΈΡ…ΠΌΠ΅ към никакъв ΠΌΡ€Π΅ΠΆΠΎΠ² интСрфСйс:

$ 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

МоТСм Π΄Π° ΠΈΠ·Ρ‚Ρ€ΠΈΠ΅ΠΌ файловия ΠΎΠ±Π΅ΠΊΡ‚ Π½ΠΎΡ€ΠΌΠ°Π»Π½ΠΎ unlink(2) ΠΈ слСд Ρ‚ΠΎΠ²Π° ΡΡŠΠΎΡ‚Π²Π΅Ρ‚Π½Π°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Ρ‰Π΅ бъдС ΠΈΠ·Ρ‚Ρ€ΠΈΡ‚Π°:

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

Π˜Π·Ρ‚Ρ€ΠΈΠ²Π°Π½Π΅ Π½Π° ΠΎΠ±Π΅ΠΊΡ‚ΠΈ

Π“ΠΎΠ²ΠΎΡ€Π΅ΠΉΠΊΠΈ Π·Π° ΠΈΠ·Ρ‚Ρ€ΠΈΠ²Π°Π½Π΅ Π½Π° ΠΎΠ±Π΅ΠΊΡ‚ΠΈ, Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΄Π° сС изясни, Ρ‡Π΅ слСд ΠΊΠ°Ρ‚ΠΎ ΠΈΠ·ΠΊΠ»ΡŽΡ‡ΠΈΠΌ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° ΠΎΡ‚ ΠΊΡƒΠΊΠ°Ρ‚Π° (Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ Π½Π° ΡΡŠΠ±ΠΈΡ‚ΠΈΡ), Π½ΠΈΡ‚ΠΎ Π΅Π΄Π½ΠΎ Π½ΠΎΠ²ΠΎ ΡΡŠΠ±ΠΈΡ‚ΠΈΠ΅ няма Π΄Π° задСйства Π½Π΅ΠΉΠ½ΠΎΡ‚ΠΎ стартиранС, Π½ΠΎ всички Ρ‚Π΅ΠΊΡƒΡ‰ΠΈ копия Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° Ρ‰Π΅ Π±ΡŠΠ΄Π°Ρ‚ Π·Π°Π²ΡŠΡ€ΡˆΠ΅Π½ΠΈ Π² нормалния Ρ€Π΅Π΄ .

Някои Π²ΠΈΠ΄ΠΎΠ²Π΅ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ Π²ΠΈ позволяват Π΄Π° Π·Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° Π² Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅, Ρ‚.Π΅. осигуряват атомарност Π½Π° послСдоватСлността replace = detach old program, attach new program. Π’ Ρ‚ΠΎΠ·ΠΈ случай всички Π°ΠΊΡ‚ΠΈΠ²Π½ΠΈ СкзСмпляри Π½Π° старата вСрсия Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° Ρ‰Π΅ Π·Π°Π²ΡŠΡ€ΡˆΠ°Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚Π° си ΠΈ ΠΎΡ‚ Π½ΠΎΠ²Π°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Ρ‰Π΅ Π±ΡŠΠ΄Π°Ρ‚ създадСни Π½ΠΎΠ²ΠΈ ΠΌΠ°Π½ΠΈΠΏΡƒΠ»Π°Ρ‚ΠΎΡ€ΠΈ Π½Π° ΡΡŠΠ±ΠΈΡ‚ΠΈΡ, Π° β€žΠ°Ρ‚ΠΎΠΌΠ°Ρ€Π½ΠΎΡΡ‚Ρ‚Π°β€œ Ρ‚ΡƒΠΊ ΠΎΠ·Π½Π°Ρ‡Π°Π²Π°, Ρ‡Π΅ Π½ΠΈΡ‚ΠΎ Π΅Π΄Π½ΠΎ ΡΡŠΠ±ΠΈΡ‚ΠΈΠ΅ няма Π΄Π° бъдС пропуснато.

ΠŸΡ€ΠΈΠΊΠ°Ρ‡Π²Π°Π½Π΅ Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ към ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΡ†ΠΈ Π½Π° ΡΡŠΠ±ΠΈΡ‚ΠΈΡ

Π’ Ρ‚Π°Π·ΠΈ статия няма Π΄Π° описвамС ΠΎΡ‚Π΄Π΅Π»Π½ΠΎ ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ към ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΡ†ΠΈ Π½Π° ΡΡŠΠ±ΠΈΡ‚ΠΈΡ, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ ΠΈΠΌΠ° смисъл Π΄Π° сС ΠΈΠ·ΡƒΡ‡Π°Π²Π° Ρ‚ΠΎΠ²Π° Π² контСкста Π½Π° ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π΅Π½ Ρ‚ΠΈΠΏ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°. Π‘ΠΌ. ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΏΠΎ-Π΄ΠΎΠ»Ρƒ, Π² ΠΊΠΎΠΉΡ‚ΠΎ ΠΏΠΎΠΊΠ°Π·Π²Π°ΠΌΠ΅ ΠΊΠ°ΠΊ сС ΡΠ²ΡŠΡ€Π·Π²Π°Ρ‚ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ ΠΊΠ°Ρ‚ΠΎ XDP.

ΠœΠ°Π½ΠΈΠΏΡƒΠ»ΠΈΡ€Π°Π½Π΅ Π½Π° ΠΎΠ±Π΅ΠΊΡ‚ΠΈ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° bpf System Call

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ Π½Π° BPF

Всички BPF ΠΎΠ±Π΅ΠΊΡ‚ΠΈ сС ΡΡŠΠ·Π΄Π°Π²Π°Ρ‚ ΠΈ управляват ΠΎΡ‚ потрСбитСлско пространство с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° систСмно ΠΏΠΎΠ²ΠΈΠΊΠ²Π°Π½Π΅ bpf, ΠΈΠΌΠ°Ρ‰ слСдния ΠΏΡ€ΠΎΡ‚ΠΎΡ‚ΠΈΠΏ:

#include <linux/bpf.h>

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

Π•Ρ‚ΠΎ Π³ΠΎ ΠΎΡ‚Π±ΠΎΡ€Π° cmd Π΅ Π΅Π΄Π½Π° ΠΎΡ‚ стойноститС Π½Π° type enum bpf_cmd, attr β€” ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π» към ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈ Π·Π° ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° ΠΈ size β€” Ρ€Π°Π·ΠΌΠ΅Ρ€ Π½Π° ΠΎΠ±Π΅ΠΊΡ‚Π° спорСд ΠΏΠΎΠΊΠ°Π·Π°Π»Π΅Ρ†Π°, Ρ‚.Π΅. ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ Ρ‚ΠΎΠ²Π° sizeof(*attr). Π’ ядрото 5.8 систСмното ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅ bpf ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ° 34 Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ ΠΊΠΎΠΌΠ°Π½Π΄ΠΈ ΠΈ опрСдСлянС Π½Π° union bpf_attr Π·Π°Π΅ΠΌΠ° 200 Ρ€Π΅Π΄Π°. Но Π½Π΅ Π±ΠΈΠ²Π° Π΄Π° сС плашим ΠΎΡ‚ Ρ‚ΠΎΠ²Π°, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Ρ‰Π΅ сС Π·Π°ΠΏΠΎΠ·Π½Π°Π΅ΠΌ с ΠΊΠΎΠΌΠ°Π½Π΄ΠΈΡ‚Π΅ ΠΈ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈΡ‚Π΅ Π² Ρ‚Π΅Ρ‡Π΅Π½ΠΈΠ΅ Π½Π° няколко статии.

Π”Π° Π·Π°ΠΏΠΎΡ‡Π½Π΅ΠΌ с ΠΎΡ‚Π±ΠΎΡ€Π° BPF_PROG_LOAD, ΠΊΠΎΠΉΡ‚ΠΎ създава BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ - Π²Π·Π΅ΠΌΠ° Π½Π°Π±ΠΎΡ€ ΠΎΡ‚ BPF инструкции ΠΈ Π³ΠΎ Π·Π°Ρ€Π΅ΠΆΠ΄Π° Π² ядрото. Π’ ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° Π½Π° Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅ сС стартира Π²Π΅Ρ€ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΡŠΡ‚, слСд ΠΊΠΎΠ΅Ρ‚ΠΎ JIT ΠΊΠΎΠΌΠΏΠΈΠ»Π°Ρ‚ΠΎΡ€ΡŠΡ‚ ΠΈ слСд ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ изпълнСниС Π΄Π΅ΡΠΊΡ€ΠΈΠΏΡ‚ΠΎΡ€ΡŠΡ‚ Π½Π° програмния Ρ„Π°ΠΉΠ» сС Π²Ρ€ΡŠΡ‰Π° Π½Π° потрСбитСля. ВидяхмС ΠΊΠ°ΠΊΠ²ΠΎ сС случва с Π½Π΅Π³ΠΎ слСд Ρ‚ΠΎΠ²Π° Π² ΠΏΡ€Π΅Π΄ΠΈΡˆΠ½ΠΈΡ Ρ€Π°Π·Π΄Π΅Π» Π·Π° ТизнСния Ρ†ΠΈΠΊΡŠΠ» Π½Π° BPF ΠΎΠ±Π΅ΠΊΡ‚ΠΈ.

Π‘Π΅Π³Π° Ρ‰Π΅ напишСм пСрсонализирана ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°, която Ρ‰Π΅ Π·Π°Ρ€Π΅Π΄ΠΈ проста BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°, Π½ΠΎ ΠΏΡŠΡ€Π²ΠΎ трябва Π΄Π° Ρ€Π΅ΡˆΠΈΠΌ какъв Π²ΠΈΠ΄ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° искамС Π΄Π° Π·Π°Ρ€Π΅Π΄ΠΈΠΌ - Ρ‰Π΅ трябва Π΄Π° ΠΈΠ·Π±Π΅Ρ€Π΅ΠΌ Ρ‚ΠΈΠΏ ΠΈ Π² Ρ€Π°ΠΌΠΊΠΈΡ‚Π΅ Π½Π° Ρ‚ΠΎΠ·ΠΈ Ρ‚ΠΈΠΏ Π½Π°ΠΏΠΈΡˆΠ΅Ρ‚Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°, която Ρ‰Π΅ ΠΏΡ€Π΅ΠΌΠΈΠ½Π΅ тСста Π·Π° ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ°. Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‚ΠΎΠ²Π°, Π·Π° Π΄Π° Π½Π΅ услоТнявамС процСса, Π΅Ρ‚ΠΎ Π΅Π΄Π½ΠΎ Π³ΠΎΡ‚ΠΎΠ²ΠΎ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅: Ρ‰Π΅ Π²Π·Π΅ΠΌΠ΅ΠΌ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° ΠΊΠ°Ρ‚ΠΎ BPF_PROG_TYPE_XDP, ΠΊΠΎΠ΅Ρ‚ΠΎ Ρ‰Π΅ Π²ΡŠΡ€Π½Π΅ стойността XDP_PASS (пропуснСтС всички ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ). Π’ BPF асСмблСр ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° ΠΌΠ½ΠΎΠ³ΠΎ просто:

r0 = 2
exit

Π‘Π»Π΅Π΄ ΠΊΠ°Ρ‚ΠΎ смС Ρ€Π΅ΡˆΠΈΠ»ΠΈ Ρ‡Π΅ Π½ΠΈΠ΅ Ρ‰Π΅ ΠΊΠ°Ρ‡ΠΈΠΌ, ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Π²ΠΈ ΠΊΠ°ΠΆΠ΅ΠΌ ΠΊΠ°ΠΊ Ρ‰Π΅ Π³ΠΎ Π½Π°ΠΏΡ€Π°Π²ΠΈΠΌ:

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

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

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

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

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

    for ( ;; )
        pause();
}

Π˜Π½Ρ‚Π΅Ρ€Π΅ΡΠ½ΠΈΡ‚Π΅ ΡΡŠΠ±ΠΈΡ‚ΠΈΡ Π² ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° Π·Π°ΠΏΠΎΡ‡Π²Π°Ρ‚ с Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π°Π½Π΅Ρ‚ΠΎ Π½Π° масив insns - Π½Π°ΡˆΠ°Ρ‚Π° BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Π² машинСн ΠΊΠΎΠ΄. Π’ Ρ‚ΠΎΠ·ΠΈ случай всяка инструкция Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° BPF Π΅ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈΡ€Π°Π½Π° Π² структурата bpf_insn. ΠŸΡŠΡ€Π²ΠΈ Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ insns спазва инструкциитС r0 = 2, Π²Ρ‚ΠΎΡ€ΠΎ - exit.

ΠžΡ‚ΡΡ‚ΡŠΠΏΠ»Π΅Π½ΠΈΠ΅. Π―Π΄Ρ€ΠΎΡ‚ΠΎ Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π° ΠΏΠΎ-ΡƒΠ΄ΠΎΠ±Π½ΠΈ макроси Π·Π° писанС Π½Π° машинни ΠΊΠΎΠ΄ΠΎΠ²Π΅ ΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° заглавния Ρ„Π°ΠΉΠ» Π½Π° ядрото tools/include/linux/filter.h Π±ΠΈΡ…ΠΌΠ΅ ΠΌΠΎΠ³Π»ΠΈ Π΄Π° пишСм

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

Но Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ писанСто Π½Π° BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ Π² СстСствСн ΠΊΠΎΠ΄ Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ само Π·Π° писанС Π½Π° тСстовС Π² ядрото ΠΈ статии Π·Π° BPF, ΠΎΡ‚ΡΡŠΡΡ‚Π²ΠΈΠ΅Ρ‚ΠΎ Π½Π° Ρ‚Π΅Π·ΠΈ макроси Π²ΡΡŠΡ‰Π½ΠΎΡΡ‚ Π½Π΅ услоТнява ΠΆΠΈΠ²ΠΎΡ‚Π° Π½Π° Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ°.

Π‘Π»Π΅Π΄ ΠΊΠ°Ρ‚ΠΎ Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π°ΠΌΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° BPF, ΠΏΡ€Π΅ΠΌΠΈΠ½Π°Π²Π°ΠΌΠ΅ към Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅Ρ‚ΠΎ ΠΉ Π² ядрото. ΠΠ°ΡˆΠΈΡΡ‚ минималистичСн Π½Π°Π±ΠΎΡ€ ΠΎΡ‚ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈ attr Π²ΠΊΠ»ΡŽΡ‡Π²Π° Π²ΠΈΠ΄Π° Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π°, Π½Π°Π±ΠΎΡ€Π° ΠΈ броя инструкции, нСобходимия Π»ΠΈΡ†Π΅Π½Π· ΠΈ ΠΈΠΌΠ΅ "woo", ΠΊΠΎΠΉΡ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅, Π·Π° Π΄Π° Π½Π°ΠΌΠ΅Ρ€ΠΈΠΌ Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Π² систСмата слСд изтСглянС. ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π°, ΠΊΠ°ΠΊΡ‚ΠΎ бСшС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΎ, сС Π·Π°Ρ€Π΅ΠΆΠ΄Π° Π² систСмата Ρ‡Ρ€Π΅Π· систСмно ΠΏΠΎΠ²ΠΈΠΊΠ²Π°Π½Π΅ bpf.

Π’ края Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° сС ΠΎΠ·ΠΎΠ²Π°Π²Π°ΠΌΠ΅ Π² Π±Π΅Π·ΠΊΡ€Π°Π΅Π½ Ρ†ΠΈΠΊΡŠΠ», ΠΊΠΎΠΉΡ‚ΠΎ симулира полСзния Ρ‚ΠΎΠ²Π°Ρ€. Π‘Π΅Π· Π½Π΅Π³ΠΎ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° Ρ‰Π΅ бъдС ΡƒΠ±ΠΈΡ‚Π° ΠΎΡ‚ ядрото, ΠΊΠΎΠ³Π°Ρ‚ΠΎ файловият дСскриптор, Π²ΡŠΡ€Π½Π°Ρ‚ ΠΎΡ‚ систСмното ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅, бъдС Π·Π°Ρ‚Π²ΠΎΡ€Π΅Π½ bpf, ΠΈ няма Π΄Π° Π³ΠΎ Π²ΠΈΠ΄ΠΈΠΌ Π² систСмата.

Π•, Π½ΠΈΠ΅ смС Π³ΠΎΡ‚ΠΎΠ²ΠΈ Π·Π° тСстванС. НСка сглобим ΠΈ стартирамС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° ΠΏΠΎΠ΄ straceΠ·Π° Π΄Π° ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚Π΅ Π΄Π°Π»ΠΈ всичко Ρ€Π°Π±ΠΎΡ‚ΠΈ ΠΊΠ°ΠΊΡ‚ΠΎ трябва:

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

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

Всичко Π΅ Π½Π°Ρ€Π΅Π΄, bpf(2) Π½ΠΈ Π²ΡŠΡ€Π½Π° ΠΌΠ°Π½ΠΈΠΏΡƒΠ»Π°Ρ‚ΠΎΡ€ 3 ΠΈ Π½ΠΈΠ΅ влязохмС Π² Π±Π΅Π·ΠΊΡ€Π°Π΅Π½ Ρ†ΠΈΠΊΡŠΠ» с pause(). НСка сС ΠΎΠΏΠΈΡ‚Π°ΠΌΠ΅ Π΄Π° Π½Π°ΠΌΠ΅Ρ€ΠΈΠΌ Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Π² систСмата. Π—Π° Π΄Π° Π½Π°ΠΏΡ€Π°Π²ΠΈΠΌ Ρ‚ΠΎΠ²Π°, Ρ‰Π΅ ΠΎΡ‚ΠΈΠ΄Π΅ΠΌ Π½Π° Π΄Ρ€ΡƒΠ³ Ρ‚Π΅Ρ€ΠΌΠΈΠ½Π°Π» ΠΈ Ρ‰Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΠΏΠΎΠΌΠΎΡ‰Π½Π°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° bpftool:

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

Π’ΠΈΠΆΠ΄Π°ΠΌΠ΅, Ρ‡Π΅ ΠΈΠΌΠ° Π·Π°Ρ€Π΅Π΄Π΅Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Π² систСмата woo Ρ‡ΠΈΠΉΡ‚ΠΎ Π³Π»ΠΎΠ±Π°Π»Π΅Π½ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ Π΅ 390 ΠΈ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° сС изпълнява simple-prog ΠΈΠΌΠ° ΠΎΡ‚Π²ΠΎΡ€Π΅Π½ Ρ„Π°ΠΉΠ»ΠΎΠ² дСскриптор, сочСщ към ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° (ΠΈ Π°ΠΊΠΎ simple-prog Ρ‚ΠΎΠ³Π°Π²Π° Ρ‰Π΅ ΡΠ²ΡŠΡ€ΡˆΠΈ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚Π° woo Ρ‰Π΅ ΠΈΠ·Ρ‡Π΅Π·Π½Π΅). ΠšΠ°ΠΊΡ‚ΠΎ сС ΠΎΡ‡Π°ΠΊΠ²Π°, ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° woo Π²Π·Π΅ΠΌΠ° 16 Π±Π°ΠΉΡ‚Π° - Π΄Π²Π΅ инструкции - ΠΎΡ‚ Π΄Π²ΠΎΠΈΡ‡Π½ΠΈ ΠΊΠΎΠ΄ΠΎΠ²Π΅ Π² BPF Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π°Ρ‚Π°, Π½ΠΎ Π² СстСствСната си Ρ„ΠΎΡ€ΠΌΠ° (x86_64) Π²Π΅Ρ‡Π΅ Π΅ 40 Π±Π°ΠΉΡ‚Π°. НСка Π΄Π° Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Π² оригиналния ΠΉ Π²ΠΈΠ΄:

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

Π±Π΅Π· ΠΈΠ·Π½Π΅Π½Π°Π΄ΠΈ. Π‘Π΅Π³Π° Π½Π΅ΠΊΠ° Π΄Π° Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΊΠΎΠ΄Π°, Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½ ΠΎΡ‚ 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

Π½Π΅ Π΅ ΠΌΠ½ΠΎΠ³ΠΎ Π΅Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π΅Π½ Π·Π° exit(2), Π½ΠΎ чСстно ΠΊΠ°Π·Π°Π½ΠΎ, Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Π΅ Ρ‚Π²ΡŠΡ€Π΄Π΅ проста ΠΈ Π·Π° Π½Π΅Ρ‚Ρ€ΠΈΠ²ΠΈΠ°Π»Π½ΠΈΡ‚Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ ΠΏΡ€ΠΎΠ»ΠΎΠ³ΡŠΡ‚ ΠΈ Π΅ΠΏΠΈΠ»ΠΎΠ³ΡŠΡ‚, Π΄ΠΎΠ±Π°Π²Π΅Π½ΠΈ ΠΎΡ‚ JIT ΠΊΠΎΠΌΠΏΠΈΠ»Π°Ρ‚ΠΎΡ€Π°, Ρ€Π°Π·Π±ΠΈΡ€Π° сС, са Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΈ.

ΠšΠ°Ρ€Ρ‚ΠΈ

BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ структурирани области Π½Π° ΠΏΠ°ΠΌΠ΅Ρ‚Ρ‚Π°, ΠΊΠΎΠΈΡ‚ΠΎ са Π΄ΠΎΡΡ‚ΡŠΠΏΠ½ΠΈ ΠΊΠ°ΠΊΡ‚ΠΎ Π·Π° Π΄Ρ€ΡƒΠ³ΠΈ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ, Ρ‚Π°ΠΊΠ° ΠΈ Π·Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ Π² потрСбитСлското пространство. Π’Π΅Π·ΠΈ ΠΎΠ±Π΅ΠΊΡ‚ΠΈ сС Π½Π°Ρ€ΠΈΡ‡Π°Ρ‚ ​​карти ΠΈ Π² Ρ‚ΠΎΠ·ΠΈ Ρ€Π°Π·Π΄Π΅Π» Ρ‰Π΅ ΠΏΠΎΠΊΠ°ΠΆΠ΅ΠΌ ΠΊΠ°ΠΊ Π΄Π° Π³ΠΈ ΠΌΠ°Π½ΠΈΠΏΡƒΠ»ΠΈΡ€Π°ΠΌΠ΅ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° систСмно ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅ bpf.

НСка ΠΊΠ°ΠΆΠ΅ΠΌ Π²Π΅Π΄Π½Π°Π³Π°, Ρ‡Π΅ Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΠΈΡ‚Π΅ Π½Π° ΠΊΠ°Ρ€Ρ‚ΠΈΡ‚Π΅ Π½Π΅ сС ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π°Π²Π°Ρ‚ само Π΄ΠΎ Π΄ΠΎΡΡ‚ΡŠΠΏ Π΄ΠΎ сподСлСна ΠΏΠ°ΠΌΠ΅Ρ‚. Има ΠΊΠ°Ρ€Ρ‚ΠΈ със спСциално ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Ρ‰ΠΈ Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈ към BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ ΠΈΠ»ΠΈ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈ към ΠΌΡ€Π΅ΠΆΠΎΠ²ΠΈ интСрфСйси, ΠΊΠ°Ρ€Ρ‚ΠΈ Π·Π° Ρ€Π°Π±ΠΎΡ‚Π° с perf ΡΡŠΠ±ΠΈΡ‚ΠΈΡ ΠΈ Ρ‚.Π½. Π’ΡƒΠΊ няма Π΄Π° Π³ΠΎΠ²ΠΎΡ€ΠΈΠΌ Π·Π° тях, Π·Π° Π΄Π° Π½Π΅ ΠΎΠ±ΡŠΡ€ΠΊΠ°ΠΌΠ΅ читатСля. ΠžΡ‚Π΄Π΅Π»Π½ΠΎ ΠΎΡ‚ Ρ‚ΠΎΠ²Π°, Π½ΠΈΠ΅ ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€Π°ΠΌΠ΅ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΈΡ‚Π΅ със синхронизацията, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Ρ‚ΠΎΠ²Π° Π½Π΅ Π΅ Π²Π°ΠΆΠ½ΠΎ Π·Π° Π½Π°ΡˆΠΈΡ‚Π΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΈ. ПълСн списък Π½Π° Π½Π°Π»ΠΈΡ‡Π½ΠΈΡ‚Π΅ Ρ‚ΠΈΠΏΠΎΠ²Π΅ ΠΊΠ°Ρ€Ρ‚ΠΈ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π½Π°ΠΌΠ΅Ρ€ΠΈΡ‚Π΅ Π² <linux/bpf.h>, Π° Π² Ρ‚ΠΎΠ·ΠΈ Ρ€Π°Π·Π΄Π΅Π» Ρ‰Π΅ Π²Π·Π΅ΠΌΠ΅ΠΌ Π·Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€ историчСски ΠΏΡŠΡ€Π²ΠΈΡ Ρ‚ΠΈΠΏ, Ρ…Π΅Ρˆ-Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π° BPF_MAP_TYPE_HASH.

Ако ΡΡŠΠ·Π΄Π°Π΄Π΅Ρ‚Π΅ Ρ…Π΅Ρˆ Ρ‚Π°Π±Π»ΠΈΡ†Π° Π², Π΄Π° Ρ€Π΅Ρ‡Π΅ΠΌ, C++, Π±ΠΈΡ…Ρ‚Π΅ ΠΊΠ°Π·Π°Π»ΠΈ unordered_map<int,long> woo, ΠΊΠΎΠ΅Ρ‚ΠΎ Π½Π° руски ΠΎΠ·Π½Π°Ρ‡Π°Π²Π° β€žΠ˜ΠΌΠ°ΠΌ Π½ΡƒΠΆΠ΄Π° ΠΎΡ‚ маса woo Π½Π΅ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ Ρ€Π°Π·ΠΌΠ΅Ρ€, Ρ‡ΠΈΠΈΡ‚ΠΎ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅ са Ρ‚ΠΈΠΏ int, Π° стойноститС са Ρ‚ΠΈΠΏΡŠΡ‚ long" Π—Π° Π΄Π° създадСм BPF Ρ…Π΅Ρˆ Ρ‚Π°Π±Π»ΠΈΡ†Π°, трябва Π΄Π° Π½Π°ΠΏΡ€Π°Π²ΠΈΠΌ ΠΏΠΎΡ‡Ρ‚ΠΈ ΡΡŠΡ‰ΠΎΡ‚ΠΎ, с ΠΈΠ·ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Π½Π° Ρ‚ΠΎΠ²Π°, Ρ‡Π΅ трябва Π΄Π° посочим максималния Ρ€Π°Π·ΠΌΠ΅Ρ€ Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π° ΠΈ вмСсто Π΄Π° посочим Ρ‚ΠΈΠΏΠΎΠ²Π΅Ρ‚Π΅ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅ ΠΈ стойности, трябва Π΄Π° посочим Ρ‚Π΅Ρ…Π½ΠΈΡ‚Π΅ Ρ€Π°Π·ΠΌΠ΅Ρ€ΠΈ Π² Π±Π°ΠΉΡ‚ΠΎΠ²Π΅ . Π—Π° Π΄Π° ΡΡŠΠ·Π΄Π°Π΄Π΅Ρ‚Π΅ ΠΊΠ°Ρ€Ρ‚ΠΈ, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΡ‚Π΅ ΠΊΠΎΠΌΠ°Π½Π΄Π°Ρ‚Π° BPF_MAP_CREATE систСмно ΠΏΠΎΠ²ΠΈΠΊΠ²Π°Π½Π΅ bpf. НСка Π΄Π° Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΏΠΎΠ²Π΅Ρ‡Π΅ ΠΈΠ»ΠΈ ΠΏΠΎ-ΠΌΠ°Π»ΠΊΠΎ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°, която създава ΠΊΠ°Ρ€Ρ‚Π°. Π‘Π»Π΅Π΄ ΠΏΡ€Π΅Π΄ΠΈΡˆΠ½Π°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°, която Π·Π°Ρ€Π΅ΠΆΠ΄Π° BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ, Ρ‚Π°Π·ΠΈ трябва Π΄Π° Π²ΠΈ ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° проста:

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

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

    for ( ;; )
        pause();
}

Π’ΡƒΠΊ Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π°ΠΌΠ΅ Π½Π°Π±ΠΎΡ€ ΠΎΡ‚ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈ attr, Π² ΠΊΠΎΠΉΡ‚ΠΎ ΠΊΠ°Π·Π²Π°ΠΌΠ΅ β€žΠ˜ΠΌΠ°ΠΌ Π½ΡƒΠΆΠ΄Π° ΠΎΡ‚ Ρ…Π΅Ρˆ Ρ‚Π°Π±Π»ΠΈΡ†Π° с ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅ ΠΈ стойности Π½Π° Ρ€Π°Π·ΠΌΠ΅Ρ€Π° sizeof(int), Π² ΠΊΠΎΠΉΡ‚ΠΎ ΠΌΠΎΠ³Π° Π΄Π° слоТа максимум Ρ‡Π΅Ρ‚ΠΈΡ€ΠΈ Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚Π°." ΠšΠΎΠ³Π°Ρ‚ΠΎ ΡΡŠΠ·Π΄Π°Π²Π°Ρ‚Π΅ BPF ΠΊΠ°Ρ€Ρ‚ΠΈ, ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π·Π°Π΄Π°Π΄Π΅Ρ‚Π΅ Π΄Ρ€ΡƒΠ³ΠΈ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΏΠΎ ΡΡŠΡ‰ΠΈΡ Π½Π°Ρ‡ΠΈΠ½, ΠΊΠ°ΠΊΡ‚ΠΎ Π² ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° с ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π°, посочихмС ΠΈΠΌΠ΅Ρ‚ΠΎ Π½Π° ΠΎΠ±Π΅ΠΊΡ‚Π° ΠΊΠ°Ρ‚ΠΎ "woo".

НСка ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€Π°ΠΌΠ΅ ΠΈ стартирамС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π°:

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

Π•Ρ‚ΠΎ Π³ΠΎ систСмното ΠΏΠΎΠ²ΠΈΠΊΠ²Π°Π½Π΅ bpf(2) Π½ΠΈ Π²ΡŠΡ€Π½Π° Π½ΠΎΠΌΠ΅Ρ€Π° Π½Π° дСскрипторната ΠΊΠ°Ρ€Ρ‚Π° 3 ΠΈ слСд Ρ‚ΠΎΠ²Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π°, ΠΊΠ°ΠΊΡ‚ΠΎ сС ΠΎΡ‡Π°ΠΊΠ²Π°, Ρ‡Π°ΠΊΠ° Π΄ΠΎΠΏΡŠΠ»Π½ΠΈΡ‚Π΅Π»Π½ΠΈ инструкции Π² систСмното ΠΏΠΎΠ²ΠΈΠΊΠ²Π°Π½Π΅ pause(2).

Π‘Π΅Π³Π° Π½Π΅ΠΊΠ° ΠΈΠ·ΠΏΡ€Π°Ρ‚ΠΈΠΌ Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Π½Π° Π·Π°Π΄Π΅Π½ ΠΏΠ»Π°Π½ ΠΈΠ»ΠΈ Π΄Π° ΠΎΡ‚Π²ΠΎΡ€ΠΈΠΌ Π΄Ρ€ΡƒΠ³ Ρ‚Π΅Ρ€ΠΌΠΈΠ½Π°Π» ΠΈ Π΄Π° Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ нашия ΠΎΠ±Π΅ΠΊΡ‚ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° ΠΏΠΎΠΌΠΎΡ‰Π½Π°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° bpftool (ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Ρ€Π°Π·Π»ΠΈΡ‡ΠΈΠΌ Π½Π°ΡˆΠ°Ρ‚Π° ΠΊΠ°Ρ€Ρ‚Π° ΠΎΡ‚ Π΄Ρ€ΡƒΠ³ΠΈΡ‚Π΅ ΠΏΠΎ Π½Π΅ΠΉΠ½ΠΎΡ‚ΠΎ ΠΈΠΌΠ΅):

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

Числото 114 Π΅ глобалният ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ Π½Π° нашия ΠΎΠ±Π΅ΠΊΡ‚. Всяка ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Π² систСмата ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Ρ‚ΠΎΠ·ΠΈ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€, Π·Π° Π΄Π° ΠΎΡ‚Π²ΠΎΡ€ΠΈ ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π°Ρ‰Π° ΠΊΠ°Ρ€Ρ‚Π° с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄Π°Ρ‚Π° BPF_MAP_GET_FD_BY_ID систСмно ΠΏΠΎΠ²ΠΈΠΊΠ²Π°Π½Π΅ bpf.

Π‘Π΅Π³Π° ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΈΠ³Ρ€Π°Π΅ΠΌ с Π½Π°ΡˆΠ°Ρ‚Π° Ρ…Π΅Ρˆ Ρ‚Π°Π±Π»ΠΈΡ†Π°. НСка Π΄Π° Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Π½ΠΈΠ΅Ρ‚ΠΎ ΠΌΡƒ:

$ sudo bpftool map dump id 114
Found 0 elements

ΠΏΡ€Π°Π·Π½Π°. НСка поставим стойност Π² Π½Π΅Π³ΠΎ hash[1] = 1:

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

Π”Π° ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅ΠΌ ΠΎΡ‚Π½ΠΎΠ²ΠΎ Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π°:

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

Π£Ρ€Π°! УспяхмС Π΄Π° Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Π΅Π΄ΠΈΠ½ Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚. Π˜ΠΌΠ°ΠΉΡ‚Π΅ ΠΏΡ€Π΅Π΄Π²ΠΈΠ΄, Ρ‡Π΅ трябва Π΄Π° Ρ€Π°Π±ΠΎΡ‚ΠΈΠΌ Π½Π° Π½ΠΈΠ²ΠΎ Π±Π°ΠΉΡ‚, Π·Π° Π΄Π° Π½Π°ΠΏΡ€Π°Π²ΠΈΠΌ Ρ‚ΠΎΠ²Π°, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ bptftool Π½Π΅ Π·Π½Π°Π΅ какъв Ρ‚ΠΈΠΏ са стойноститС Π² Ρ…Π΅Ρˆ-Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π°. (Π’Π΅Π·ΠΈ знания ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ ΠΏΡ€Π΅Ρ…Π²ΡŠΡ€Π»Π΅Π½ΠΈ към нСя с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° BTF, Π½ΠΎ ΠΏΠΎΠ²Π΅Ρ‡Π΅ Π·Π° Ρ‚ΠΎΠ²Π° сСга.)

Как Ρ‚ΠΎΡ‡Π½ΠΎ bpftool Ρ‡Π΅Ρ‚Π΅ ΠΈ добавя Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ΠΈ? НСка Π΄Π° Π½Π°Π΄Π½ΠΈΠΊΠ½Π΅ΠΌ ΠΏΠΎΠ΄ ΠΊΠ°ΠΏΠ°ΠΊΠ°:

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

ΠŸΡŠΡ€Π²ΠΎ ΠΎΡ‚Π²ΠΎΡ€ΠΈΡ…ΠΌΠ΅ ΠΊΠ°Ρ€Ρ‚Π°Ρ‚Π° ΠΏΠΎ нСйния Π³Π»ΠΎΠ±Π°Π»Π΅Π½ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄Π°Ρ‚Π° BPF_MAP_GET_FD_BY_ID ΠΈ bpf(2) Π½ΠΈ Π²ΡŠΡ€Π½Π° дСскриптор 3. По-Π½Π°Ρ‚Π°Ρ‚ΡŠΡˆΠ½ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄Π°Ρ‚Π° BPF_MAP_GET_NEXT_KEY Π½Π°ΠΌΠ΅Ρ€ΠΈΡ…ΠΌΠ΅ ΠΏΡŠΡ€Π²ΠΈΡ ΠΊΠ»ΡŽΡ‡ Π² Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π° Ρ‡Ρ€Π΅Π· ΠΏΡ€Π΅ΠΌΠΈΠ½Π°Π²Π°Π½Π΅ NULL ΠΊΠ°Ρ‚ΠΎ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π» към "ΠΏΡ€Π΅Π΄ΠΈΡˆΠ½ΠΈΡ" ΠΊΠ»ΡŽΡ‡. Ако ΠΈΠΌΠ°ΠΌΠ΅ ΠΊΠ»ΡŽΡ‡Π°, ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Π³ΠΎ Π½Π°ΠΏΡ€Π°Π²ΠΈΠΌ BPF_MAP_LOOKUP_ELEMΠΊΠΎΠΉΡ‚ΠΎ Π²Ρ€ΡŠΡ‰Π° стойност към ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π» value. Π‘Π»Π΅Π΄Π²Π°Ρ‰Π°Ρ‚Π° ΡΡ‚ΡŠΠΏΠΊΠ° Π΅ Π΄Π° сС ΠΎΠΏΠΈΡ‚Π°ΠΌΠ΅ Π΄Π° Π½Π°ΠΌΠ΅Ρ€ΠΈΠΌ слСдващия Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚, ΠΊΠ°Ρ‚ΠΎ ΠΏΠΎΠ΄Π°Π΄Π΅ΠΌ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π» към тСкущия ΠΊΠ»ΡŽΡ‡, Π½ΠΎ Π½Π°ΡˆΠ°Ρ‚Π° Ρ‚Π°Π±Π»ΠΈΡ†Π° ΡΡŠΠ΄ΡŠΡ€ΠΆΠ° само Π΅Π΄ΠΈΠ½ Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ ΠΈ ΠΊΠΎΠΌΠ°Π½Π΄Π°Ρ‚Π° BPF_MAP_GET_NEXT_KEY сС Π·Π°Π²Ρ€ΡŠΡ‰Π° ENOENT.

Π”ΠΎΠ±Ρ€Π΅, Π½Π΅ΠΊΠ° ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈΠΌ стойността с ΠΊΠ»ΡŽΡ‡ 1, Π΄Π° ΠΊΠ°ΠΆΠ΅ΠΌ, Ρ‡Π΅ Π½Π°ΡˆΠ°Ρ‚Π° бизнСс Π»ΠΎΠ³ΠΈΠΊΠ° изисква рСгистрация hash[1] = 2:

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

ΠšΠ°ΠΊΡ‚ΠΎ сС ΠΎΡ‡Π°ΠΊΠ²Π°, Ρ‚ΠΎΠ²Π° Π΅ ΠΌΠ½ΠΎΠ³ΠΎ просто: ΠΊΠΎΠΌΠ°Π½Π΄Π°Ρ‚Π° BPF_MAP_GET_FD_BY_ID отваря Π½Π°ΡˆΠ°Ρ‚Π° ΠΊΠ°Ρ€Ρ‚Π° ΠΏΠΎ ID ΠΈ ΠΊΠΎΠΌΠ°Π½Π΄Π°Ρ‚Π° BPF_MAP_UPDATE_ELEM прСзаписва Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚Π°.

Π’Π°ΠΊΠ° Ρ‡Π΅, слСд ΠΊΠ°Ρ‚ΠΎ създадСм Ρ…Π΅Ρˆ Ρ‚Π°Π±Π»ΠΈΡ†Π° ΠΎΡ‚ Π΅Π΄Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°, ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Ρ‡Π΅Ρ‚Π΅ΠΌ ΠΈ записвамС Π½Π΅ΠΉΠ½ΠΎΡ‚ΠΎ ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Π½ΠΈΠ΅ ΠΎΡ‚ Π΄Ρ€ΡƒΠ³Π°. Π˜ΠΌΠ°ΠΉΡ‚Π΅ ΠΏΡ€Π΅Π΄Π²ΠΈΠ΄, Ρ‡Π΅ Π°ΠΊΠΎ успяхмС Π΄Π° Π½Π°ΠΏΡ€Π°Π²ΠΈΠΌ Ρ‚ΠΎΠ²Π° ΠΎΡ‚ командния Ρ€Π΅Π΄, Ρ‚ΠΎΠ³Π°Π²Π° всяка Π΄Ρ€ΡƒΠ³Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Π² систСмата ΠΌΠΎΠΆΠ΅ Π΄Π° Π³ΠΎ Π½Π°ΠΏΡ€Π°Π²ΠΈ. Π’ допълнСниС към ΠΊΠΎΠΌΠ°Π½Π΄ΠΈΡ‚Π΅, описани ΠΏΠΎ-Π³ΠΎΡ€Π΅, Π·Π° Ρ€Π°Π±ΠΎΡ‚Π° с ΠΊΠ°Ρ€Ρ‚ΠΈ ΠΎΡ‚ потрСбитСлското пространство, слСдното:

  • BPF_MAP_LOOKUP_ELEM: Π½Π°ΠΌΠΈΡ€Π°Π½Π΅ Π½Π° стойност ΠΏΠΎ ΠΊΠ»ΡŽΡ‡
  • BPF_MAP_UPDATE_ELEM: Π°ΠΊΡ‚ΡƒΠ°Π»ΠΈΠ·ΠΈΡ€Π°Π½Π΅/създаванС Π½Π° стойност
  • BPF_MAP_DELETE_ELEM: ΠΈΠ·Π²Π°Π΄Π΅Ρ‚Π΅ ΠΊΠ»ΡŽΡ‡Π°
  • BPF_MAP_GET_NEXT_KEY: Π½Π°ΠΌΠ΅Ρ€Π΅Ρ‚Π΅ слСдващия (ΠΈΠ»ΠΈ ΠΏΡŠΡ€Π²ΠΈΡ) ΠΊΠ»ΡŽΡ‡
  • BPF_MAP_GET_NEXT_ID: позволява Π²ΠΈ Π΄Π° ΠΏΡ€Π΅ΠΌΠΈΠ½Π΅Ρ‚Π΅ ΠΏΡ€Π΅Π· всички ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π°Ρ‰ΠΈ ΠΊΠ°Ρ€Ρ‚ΠΈ, Ρ‚Π°ΠΊΠ° Ρ€Π°Π±ΠΎΡ‚ΠΈ bpftool map
  • BPF_MAP_GET_FD_BY_ID: отваря ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π°Ρ‰Π° ΠΊΠ°Ρ€Ρ‚Π° ΠΏΠΎ нСйния Π³Π»ΠΎΠ±Π°Π»Π΅Π½ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€
  • BPF_MAP_LOOKUP_AND_DELETE_ELEM: Π°Ρ‚ΠΎΠΌΠ½ΠΎ Π°ΠΊΡ‚ΡƒΠ°Π»ΠΈΠ·ΠΈΡ€Π° стойността Π½Π° ΠΎΠ±Π΅ΠΊΡ‚ ΠΈ Π²Ρ€ΡŠΡ‰Π° старата
  • BPF_MAP_FREEZE: Π½Π°ΠΏΡ€Π°Π²Π΅Ρ‚Π΅ ΠΊΠ°Ρ€Ρ‚Π°Ρ‚Π° Π½Π΅ΠΈΠ·ΠΌΠ΅Π½Π½Π° ΠΎΡ‚ потрСбитСлското пространство (Ρ‚Π°Π·ΠΈ опСрация Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Π°)
  • BPF_MAP_LOOKUP_BATCH, BPF_MAP_LOOKUP_AND_DELETE_BATCH, BPF_MAP_UPDATE_BATCH, BPF_MAP_DELETE_BATCH: масови ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ. НапримСр, BPF_MAP_LOOKUP_AND_DELETE_BATCH - Ρ‚ΠΎΠ²Π° Π΅ СдинствСният Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ Π½Π°Ρ‡ΠΈΠ½ Π·Π° Ρ‡Π΅Ρ‚Π΅Π½Π΅ ΠΈ Π½ΡƒΠ»ΠΈΡ€Π°Π½Π΅ Π½Π° всички стойности ΠΎΡ‚ ΠΊΠ°Ρ€Ρ‚Π°Ρ‚Π°

НС всички ΠΎΡ‚ Ρ‚Π΅Π·ΠΈ ΠΊΠΎΠΌΠ°Π½Π΄ΠΈ работят Π·Π° всички Ρ‚ΠΈΠΏΠΎΠ²Π΅ ΠΊΠ°Ρ€Ρ‚ΠΈ, Π½ΠΎ ΠΊΠ°Ρ‚ΠΎ цяло Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚Π° с Π΄Ρ€ΡƒΠ³ΠΈ Ρ‚ΠΈΠΏΠΎΠ²Π΅ ΠΊΠ°Ρ€Ρ‚ΠΈ ΠΎΡ‚ потрСбитСлското пространство ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° Ρ‚ΠΎΡ‡Π½ΠΎ ΡΡŠΡ‰Π°Ρ‚Π° ΠΊΠ°Ρ‚ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚Π° с Ρ…Π΅Ρˆ Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ.

Π’ ΠΈΠΌΠ΅Ρ‚ΠΎ Π½Π° Ρ€Π΅Π΄Π°, Π½Π΅ΠΊΠ° Π·Π°Π²ΡŠΡ€ΡˆΠΈΠΌ Π½Π°ΡˆΠΈΡ‚Π΅ СкспСримСнти с Ρ…Π΅Ρˆ Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ. ΠŸΠΎΠΌΠ½ΠΈΡ‚Π΅ Π»ΠΈ, Ρ‡Π΅ ΡΡŠΠ·Π΄Π°Π΄ΠΎΡ…ΠΌΠ΅ Ρ‚Π°Π±Π»ΠΈΡ†Π°, която ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΡŠΠ΄ΡŠΡ€ΠΆΠ° Π΄ΠΎ Ρ‡Π΅Ρ‚ΠΈΡ€ΠΈ ΠΊΠ»ΡŽΡ‡Π°? НСка Π΄ΠΎΠ±Π°Π²ΠΈΠΌ ΠΎΡ‰Π΅ няколко Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚Π°:

$ 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 dump id 114
key: 01 00 00 00  value: 01 00 00 00
key: 02 00 00 00  value: 01 00 00 00
key: 04 00 00 00  value: 01 00 00 00
key: 03 00 00 00  value: 01 00 00 00
Found 4 elements

НСка сС ΠΎΠΏΠΈΡ‚Π°ΠΌΠ΅ Π΄Π° Π΄ΠΎΠ±Π°Π²ΠΈΠΌ ΠΎΡ‰Π΅ Π΅Π΄ΠΈΠ½:

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

ΠžΡ‡Π°ΠΊΠ²Π°Π½ΠΎ Π½Π΅ успяхмС. НСка Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ Π³Ρ€Π΅ΡˆΠΊΠ°Ρ‚Π° ΠΏΠΎ-ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ:

$ 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 +++

Всичко Π΅ Π½Π°Ρ€Π΅Π΄: ΠΊΠ°ΠΊΡ‚ΠΎ сС ΠΎΡ‡Π°ΠΊΠ²Π°, Π΅ΠΊΠΈΠΏΡŠΡ‚ BPF_MAP_UPDATE_ELEM ΠΎΠΏΠΈΡ‚Π²Π° Π΄Π° създадС Π½ΠΎΠ², ΠΏΠ΅Ρ‚ΠΈ, ΠΊΠ»ΡŽΡ‡, Π½ΠΎ сС срива E2BIG.

Π’Π°ΠΊΠ° Ρ‡Π΅ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° създавамС ΠΈ Π·Π°Ρ€Π΅ΠΆΠ΄Π°ΠΌΠ΅ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ, ΠΊΠ°ΠΊΡ‚ΠΎ ΠΈ Π΄Π° създавамС ΠΈ управлявамС ΠΊΠ°Ρ€Ρ‚ΠΈ ΠΎΡ‚ потрСбитСлското пространство. Π‘Π΅Π³Π° Π΅ Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ Π΄Π° Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΠΊΠ°Ρ€Ρ‚ΠΈ ΠΎΡ‚ самитС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ Π½Π° BPF. МоТСм Π΄Π° Π³ΠΎΠ²ΠΎΡ€ΠΈΠΌ Π·Π° Ρ‚ΠΎΠ²Π° Π½Π° Π΅Π·ΠΈΠΊΠ° Π½Π° Ρ‚Ρ€ΡƒΠ΄Π½ΠΈ Π·Π° Ρ‡Π΅Ρ‚Π΅Π½Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ Π² машинни ΠΌΠ°ΠΊΡ€ΠΎ ΠΊΠΎΠ΄ΠΎΠ²Π΅, Π½ΠΎ Π²ΡΡŠΡ‰Π½ΠΎΡΡ‚ Π΅ дошло Π²Ρ€Π΅ΠΌΠ΅Ρ‚ΠΎ Π΄Π° ΠΏΠΎΠΊΠ°ΠΆΠ΅ΠΌ ΠΊΠ°ΠΊ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅ Π²ΡΡŠΡ‰Π½ΠΎΡΡ‚ сС ΠΏΠΈΡˆΠ°Ρ‚ ΠΈ ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ°Ρ‚ - ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ libbpf.

(Π—Π° Ρ‡ΠΈΡ‚Π°Ρ‚Π΅Π»ΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ са Π½Π΅Π΄ΠΎΠ²ΠΎΠ»Π½ΠΈ ΠΎΡ‚ липсата Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π½Π° ниско Π½ΠΈΠ²ΠΎ: Ρ‰Π΅ Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€Π°ΠΌΠ΅ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ ΠΊΠ°Ρ€Ρ‚ΠΈ ΠΈ ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, създадСни с libbpf ΠΈ Π΄Π° Π²ΠΈ ΠΊΠ°ΠΆΠ° ΠΊΠ°ΠΊΠ²ΠΎ сС случва Π½Π° Π½ΠΈΠ²ΠΎ инструкции. Π—Π° Ρ‡ΠΈΡ‚Π°Ρ‚Π΅Π»ΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ са Π½Π΅Π΄ΠΎΠ²ΠΎΠ»Π½ΠΈ ΠΌΠ½ΠΎΠ³ΠΎ, Π΄ΠΎΠ±Π°Π²ΠΈΡ…ΠΌΠ΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π½Π° ΡΡŠΠΎΡ‚Π²Π΅Ρ‚Π½ΠΎΡ‚ΠΎ място Π² статията.)

ПисанС Π½Π° BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° libbpf

ΠŸΠΈΡΠ°Π½Π΅Ρ‚ΠΎ Π½Π° BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° машинни ΠΊΠΎΠ΄ΠΎΠ²Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС интСрСсно само Π·Π° ΠΏΡŠΡ€Π²ΠΈ ΠΏΡŠΡ‚ ΠΈ слСд Ρ‚ΠΎΠ²Π° Π½Π°ΡΡ‚ΡŠΠΏΠ²Π° насищанС. Π’ Ρ‚ΠΎΠ·ΠΈ ΠΌΠΎΠΌΠ΅Π½Ρ‚ трябва Π΄Π° насочитС Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅Ρ‚ΠΎ си към llvm, ΠΊΠΎΠΉΡ‚ΠΎ ΠΈΠΌΠ° Π±Π΅ΠΊΠ΅Π½Π΄ Π·Π° Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π΅ Π½Π° ΠΊΠΎΠ΄ Π·Π° BPF Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π°Ρ‚Π°, ΠΊΠ°ΠΊΡ‚ΠΎ ΠΈ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° libbpf, ΠΊΠΎΠ΅Ρ‚ΠΎ Π²ΠΈ позволява Π΄Π° ΠΏΠΈΡˆΠ΅Ρ‚Π΅ потрСбитСлската страна Π½Π° BPF прилоТСнията ΠΈ Π΄Π° Π·Π°Ρ€Π΅ΠΆΠ΄Π°Ρ‚Π΅ ΠΊΠΎΠ΄Π° Π½Π° BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅, Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½ΠΈ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° llvm/clang.

Π’ΡΡŠΡ‰Π½ΠΎΡΡ‚, ΠΊΠ°ΠΊΡ‚ΠΎ Ρ‰Π΅ Π²ΠΈΠ΄ΠΈΠΌ Π² Ρ‚Π°Π·ΠΈ ΠΈ слСдващитС статии, libbpf Π²ΡŠΡ€ΡˆΠΈ доста Ρ€Π°Π±ΠΎΡ‚Π° Π±Π΅Π· Π½Π΅Π³ΠΎ (ΠΈΠ»ΠΈ ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΈ инструмСнти - iproute2, libbcc, libbpf-go, ΠΈ Ρ‚.Π½.) Π΅ нСвъзмоТно Π΄Π° сС ΠΆΠΈΠ²Π΅Π΅. Π•Π΄Π½Π° ΠΎΡ‚ убийствСнитС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π½Π° ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° libbpf Π΅ BPF CO-RE (Compile Once, Run Everywhere) - ΠΏΡ€ΠΎΠ΅ΠΊΡ‚, ΠΊΠΎΠΉΡ‚ΠΎ Π²ΠΈ позволява Π΄Π° ΠΏΠΈΡˆΠ΅Ρ‚Π΅ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ са прСносими ΠΎΡ‚ Π΅Π΄Π½ΠΎ ядро ​​на Π΄Ρ€ΡƒΠ³ΠΎ, с Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ Π·Π° изпълнСниС Π½Π° Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ API (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΊΠΎΠ³Π°Ρ‚ΠΎ структурата Π½Π° ядрото сС ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈ ΠΎΡ‚ вСрсия към вСрсия). Π—Π° Π΄Π° ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Ρ€Π°Π±ΠΎΡ‚ΠΈΡ‚Π΅ с CO-RE, Π²Π°ΡˆΠ΅Ρ‚ΠΎ ядро ​​трябва Π΄Π° бъдС ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€Π°Π½ΠΎ с ΠΏΠΎΠ΄Π΄Ρ€ΡŠΠΆΠΊΠ° Π½Π° BTF (Π½ΠΈΠ΅ описвамС ΠΊΠ°ΠΊ Π΄Π° Π½Π°ΠΏΡ€Π°Π²ΠΈΡ‚Π΅ Ρ‚ΠΎΠ²Π° Π² Ρ€Π°Π·Π΄Π΅Π»Π° Π˜Π½ΡΡ‚Ρ€ΡƒΠΌΠ΅Π½Ρ‚ΠΈ Π·Π° Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ°. ΠœΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚Π΅ Π΄Π°Π»ΠΈ Π²Π°ΡˆΠ΅Ρ‚ΠΎ ядро ​​С ΠΈΠ·Π³Ρ€Π°Π΄Π΅Π½ΠΎ с BTF ΠΈΠ»ΠΈ Π½Π΅ ΠΌΠ½ΠΎΠ³ΠΎ просто - Ρ‡Ρ€Π΅Π· Π½Π°Π»ΠΈΡ‡ΠΈΠ΅Ρ‚ΠΎ Π½Π° слСдния Ρ„Π°ΠΉΠ»:

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

Π’ΠΎΠ·ΠΈ Ρ„Π°ΠΉΠ» ΡΡŠΡ…Ρ€Π°Π½ΡΠ²Π° информация Π·Π° всички Ρ‚ΠΈΠΏΠΎΠ²Π΅ Π΄Π°Π½Π½ΠΈ, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½ΠΈ Π² ядрото ΠΈ сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° във всички наши ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΈ Π·Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ libbpf. Π©Π΅ Π³ΠΎΠ²ΠΎΡ€ΠΈΠΌ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ Π·Π° CO-RE Π² слСдващата статия, Π½ΠΎ Π² Ρ‚Π°Π·ΠΈ - просто си ΠΈΠ·Π³Ρ€Π°Π΄Π΅Ρ‚Π΅ ядро ​​с Π½Π΅Π³ΠΎ CONFIG_DEBUG_INFO_BTF.

Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° libbpf ΠΆΠΈΠ²Π΅Π΅ Ρ‚ΠΎΡ‡Π½ΠΎ Π² дирСкторията tools/lib/bpf ядрото ΠΈ Π½Π΅Π³ΠΎΠ²ΠΎΡ‚ΠΎ Ρ€Π°Π·Π²ΠΈΡ‚ΠΈΠ΅ сС ΠΈΠ·Π²ΡŠΡ€ΡˆΠ²Π° Ρ‡Ρ€Π΅Π· пощСнския списък [email protected]. Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‚ΠΎΠ²Π° сС ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ° ΠΎΡ‚Π΄Π΅Π»Π½ΠΎ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ Π·Π° Π½ΡƒΠΆΠ΄ΠΈΡ‚Π΅ Π½Π° прилоТСния, ΠΆΠΈΠ²Π΅Π΅Ρ‰ΠΈ извън ядрото https://github.com/libbpf/libbpf Π² която Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°Ρ‚Π° Π½Π° ядрото Π΅ ΠΎΠ³Π»Π΅Π΄Π°Π»Π½Π° Π·Π° Π΄ΠΎΡΡ‚ΡŠΠΏ Π·Π° Ρ‡Π΅Ρ‚Π΅Π½Π΅ ΠΏΠΎΠ²Π΅Ρ‡Π΅ ΠΈΠ»ΠΈ ΠΏΠΎ-ΠΌΠ°Π»ΠΊΠΎ Ρ‚Π°ΠΊΠ°Π²Π°, ΠΊΠ°ΠΊΠ²Π°Ρ‚ΠΎ Π΅.

Π’ Ρ‚ΠΎΠ·ΠΈ Ρ€Π°Π·Π΄Π΅Π» Ρ‰Π΅ Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΡΡŠΠ·Π΄Π°Π΄Π΅Ρ‚Π΅ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚, ΠΊΠΎΠΉΡ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° libbpf, Π½Π΅ΠΊΠ° напишСм няколко (ΠΏΠΎΠ²Π΅Ρ‡Π΅ ΠΈΠ»ΠΈ ΠΏΠΎ-ΠΌΠ°Π»ΠΊΠΎ бСзсмислСни) тСстови ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ ΠΈ Π΄Π° Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€Π°ΠΌΠ΅ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚ΠΈ всичко. Π’ΠΎΠ²Π° Ρ‰Π΅ Π½ΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈ ΠΏΠΎ-лСсно Π΄Π° обясним Π² слСдващитС Ρ€Π°Π·Π΄Π΅Π»ΠΈ ΠΊΠ°ΠΊ Ρ‚ΠΎΡ‡Π½ΠΎ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅ взаимодСйстват с ΠΊΠ°Ρ€Ρ‚ΠΈ, ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈΡ†ΠΈ Π½Π° ядрото, BTF ΠΈ Ρ‚.Π½.

ОбикновСно ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΈΡ‚Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ libbpf Π΄ΠΎΠ±Π°Π²ΠΈΡ‚Π΅ GitHub Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ ΠΊΠ°Ρ‚ΠΎ git ΠΏΠΎΠ΄ΠΌΠΎΠ΄ΡƒΠ», Ρ‰Π΅ Π½Π°ΠΏΡ€Π°Π²ΠΈΠΌ ΡΡŠΡ‰ΠΎΡ‚ΠΎ:

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

ΠžΡ‚ΠΈΠ²Π°ΠΌ Π΄ΠΎ libbpf ΠΌΠ½ΠΎΠ³ΠΎ просто:

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

БлСдващият Π½ΠΈ ΠΏΠ»Π°Π½ Π² Ρ‚ΠΎΠ·ΠΈ Ρ€Π°Π·Π΄Π΅Π» Π΅ слСдният: Ρ‰Π΅ напишСм BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° ΠΊΠ°Ρ‚ΠΎ BPF_PROG_TYPE_XDP, ΡΡŠΡ‰ΠΎΡ‚ΠΎ ΠΊΠ°Ρ‚ΠΎ Π² ΠΏΡ€Π΅Π΄ΠΈΡˆΠ½ΠΈΡ ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π½ΠΎ Π² C, Π½ΠΈΠ΅ Π³ΠΎ ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€Π°ΠΌΠ΅ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° clangΠΈ Π½Π°ΠΏΠΈΡˆΠ΅Ρ‚Π΅ ΠΏΠΎΠΌΠΎΡ‰Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°, която Ρ‰Π΅ Π³ΠΎ Π·Π°Ρ€Π΅Π΄ΠΈ Π² ядрото. Π’ слСдващитС Ρ€Π°Π·Π΄Π΅Π»ΠΈ Ρ‰Π΅ Ρ€Π°Π·ΡˆΠΈΡ€ΠΈΠΌ Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΠΈΡ‚Π΅ ΠΊΠ°ΠΊΡ‚ΠΎ Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° BPF, Ρ‚Π°ΠΊΠ° ΠΈ Π½Π° асистСнтската ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€: създаванС Π½Π° ΠΏΡŠΠ»Π½ΠΎΡ†Π΅Π½Π½ΠΎ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° libbpf

ΠšΠ°Ρ‚ΠΎ Π½Π°Ρ‡Π°Π»ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ Ρ„Π°ΠΉΠ»Π° /sys/kernel/btf/vmlinux, ΠΊΠΎΠ΅Ρ‚ΠΎ бСшС спомСнато ΠΏΠΎ-Π³ΠΎΡ€Π΅, ΠΈ ΡΡŠΠ·Π΄Π°ΠΉΡ‚Π΅ Π½Π΅Π³ΠΎΠ² Π΅ΠΊΠ²ΠΈΠ²Π°Π»Π΅Π½Ρ‚ ΠΏΠΎΠ΄ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π° Π½Π° Π·Π°Π³Π»Π°Π²Π΅Π½ Ρ„Π°ΠΉΠ»:

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

Π’ΠΎΠ·ΠΈ Ρ„Π°ΠΉΠ» Ρ‰Π΅ ΡΡŠΡ…Ρ€Π°Π½ΡΠ²Π° всички структури ΠΎΡ‚ Π΄Π°Π½Π½ΠΈ, Π½Π°Π»ΠΈΡ‡Π½ΠΈ Π² Π½Π°ΡˆΠ΅Ρ‚ΠΎ ядро, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π΅Ρ‚ΠΎ ΠΊΠ°ΠΊ IPv4 Ρ…Π΅Π΄ΡŠΡ€ΡŠΡ‚ Π΅ Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π°Π½ Π² ядрото:

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

Π‘Π΅Π³Π° Ρ‰Π΅ напишСм Π½Π°ΡˆΠ°Ρ‚Π° BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Π½Π° C:

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

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

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

Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‡Π΅ Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° сС ΠΎΠΊΠ°Π·Π° ΠΌΠ½ΠΎΠ³ΠΎ проста, всС ΠΏΠ°ΠΊ трябва Π΄Π° ΠΎΠ±ΡŠΡ€Π½Π΅ΠΌ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° ΠΌΠ½ΠΎΠ³ΠΎ подробности. ΠŸΡŠΡ€Π²ΠΎ, ΠΏΡŠΡ€Π²ΠΈΡΡ‚ Π·Π°Π³Π»Π°Π²Π΅Π½ Ρ„Π°ΠΉΠ», ΠΊΠΎΠΉΡ‚ΠΎ Π²ΠΊΠ»ΡŽΡ‡Π²Π°ΠΌΠ΅, Π΅ vmlinux.h, ΠΊΠΎΠΉΡ‚ΠΎ Ρ‚ΠΎΠΊΡƒ-Ρ‰ΠΎ Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Ρ…ΠΌΠ΅ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° bpftool btf dump - сСга Π½Π΅ Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΄Π° инсталирамС ΠΏΠ°ΠΊΠ΅Ρ‚Π° kernel-headers, Π·Π° Π΄Π° Ρ€Π°Π·Π±Π΅Ρ€Π΅ΠΌ ΠΊΠ°ΠΊ ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π°Ρ‚ структуритС Π½Π° ядрото. БлСдният Π·Π°Π³Π»Π°Π²Π΅Π½ Ρ„Π°ΠΉΠ» ΠΈΠ΄Π²Π° ΠΏΡ€ΠΈ нас ΠΎΡ‚ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°Ρ‚Π° libbpf. Π‘Π΅Π³Π° Π½ΠΈ трябва само Π·Π° Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π°Π½Π΅ Π½Π° макроса SEC, ΠΊΠΎΠΉΡ‚ΠΎ ΠΈΠ·ΠΏΡ€Π°Ρ‰Π° Π·Π½Π°ΠΊΠ° Π² ΡΡŠΠΎΡ‚Π²Π΅Ρ‚Π½ΠΈΡ Ρ€Π°Π·Π΄Π΅Π» Π½Π° ELF обСктния Ρ„Π°ΠΉΠ». ΠΠ°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° сС ΡΡŠΠ΄ΡŠΡ€ΠΆΠ° Π² Ρ€Π°Π·Π΄Π΅Π»Π° xdp/simple, ΠΊΡŠΠ΄Π΅Ρ‚ΠΎ ΠΏΡ€Π΅Π΄ΠΈ Π½Π°ΠΊΠ»ΠΎΠ½Π΅Π½Π°Ρ‚Π° Ρ‡Π΅Ρ€Ρ‚Π° Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π°ΠΌΠ΅ Π²ΠΈΠ΄Π° Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° BPF - Ρ‚ΠΎΠ²Π° Π΅ конвСнцията, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π° Π² libbpf, въз основа Π½Π° ΠΈΠΌΠ΅Ρ‚ΠΎ Π½Π° Ρ€Π°Π·Π΄Π΅Π»Π°, Ρ‚ΠΎΠΉ Ρ‰Π΅ Π·Π°ΠΌΠ΅Π½ΠΈ правилния Ρ‚ΠΈΠΏ ΠΏΡ€ΠΈ стартиранС bpf(2). Π‘Π°ΠΌΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Π½Π° БНЀ Π΅ C - ΠΌΠ½ΠΎΠ³ΠΎ проста ΠΈ сС ΡΡŠΡΡ‚ΠΎΠΈ ΠΎΡ‚ Π΅Π΄ΠΈΠ½ Ρ€Π΅Π΄ return XDP_PASS. И накрая, ΠΎΡ‚Π΄Π΅Π»Π΅Π½ Ρ€Π°Π·Π΄Π΅Π» "license" ΡΡŠΠ΄ΡŠΡ€ΠΆΠ° ΠΈΠΌΠ΅Ρ‚ΠΎ Π½Π° Π»ΠΈΡ†Π΅Π½Π·Π°.

МоТСм Π΄Π° ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€Π°ΠΌΠ΅ Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° llvm/clang, вСрсия >= 10.0.0 ΠΈΠ»ΠΈ ΠΎΡ‰Π΅ ΠΏΠΎ-Π΄ΠΎΠ±Ρ€Π΅, ΠΏΠΎ-висока (Π²ΠΈΠΆΡ‚Π΅ Ρ€Π°Π·Π΄Π΅Π»Π° Π˜Π½ΡΡ‚Ρ€ΡƒΠΌΠ΅Π½Ρ‚ΠΈ Π·Π° Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ°):

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

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

Π‘Ρ€Π΅Π΄ интСрСснитС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ: посочвамС Ρ†Π΅Π»Π΅Π²Π°Ρ‚Π° Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π° -target bpf ΠΈ ΠΏΡŠΡ‚Ρ към Π·Π°Π³Π»Π°Π²ΠΊΠΈΡ‚Π΅ libbpf, ΠΊΠΎΠΉΡ‚ΠΎ наскоро инсталирахмС. Π‘ΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ°, Π½Π΅ забравяйтС Π·Π° -O2, Π±Π΅Π· Ρ‚Π°Π·ΠΈ опция ΠΌΠΎΠΆΠ΅ Π΄Π° Π²ΠΈ ΠΎΡ‡Π°ΠΊΠ²Π°Ρ‚ ΠΈΠ·Π½Π΅Π½Π°Π΄ΠΈ Π² Π±ΡŠΠ΄Π΅Ρ‰Π΅. НСка Π΄Π° ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅ΠΌ нашия ΠΊΠΎΠ΄, успяхмС Π»ΠΈ Π΄Π° напишСм ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π°, която искахмС?

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

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

Disassembly of section xdp/simple:

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

Π”Π°, ΠΏΡ€ΠΎΡ€Π°Π±ΠΎΡ‚ΠΈ! Π‘Π΅Π³Π° ΠΈΠΌΠ°ΠΌΠ΅ Π΄Π²ΠΎΠΈΡ‡Π΅Π½ Ρ„Π°ΠΉΠ» с ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° ΠΈ искамС Π΄Π° създадСм ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, ΠΊΠΎΠ΅Ρ‚ΠΎ Ρ‰Π΅ Π³ΠΎ Π·Π°Ρ€Π΅Π΄ΠΈ Π² ядрото. Π—Π° Ρ†Π΅Π»Ρ‚Π° Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°Ρ‚Π° libbpf Π½ΠΈ ΠΏΡ€Π΅Π΄Π»Π°Π³Π° Π΄Π²Π΅ ΠΎΠΏΡ†ΠΈΠΈ – ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° API ΠΎΡ‚ ΠΏΠΎ-ниско Π½ΠΈΠ²ΠΎ ΠΈΠ»ΠΈ API ΠΎΡ‚ ΠΏΠΎ-високо Π½ΠΈΠ²ΠΎ. Π©Π΅ ΠΎΡ‚ΠΈΠ΄Π΅ΠΌ ΠΏΠΎ втория Π½Π°Ρ‡ΠΈΠ½, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ искамС Π΄Π° сС Π½Π°ΡƒΡ‡ΠΈΠΌ ΠΊΠ°ΠΊ Π΄Π° пишСм, Π·Π°Ρ€Π΅ΠΆΠ΄Π°ΠΌΠ΅ ΠΈ ΡΠ²ΡŠΡ€Π·Π²Π°ΠΌΠ΅ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ с ΠΌΠΈΠ½ΠΈΠΌΠ°Π»Π½ΠΈ усилия Π·Π° послСдващото ΠΈΠΌ ΠΈΠ·ΡƒΡ‡Π°Π²Π°Π½Π΅.

ΠŸΡŠΡ€Π²ΠΎ, трябва Π΄Π° Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°ΠΌΠ΅ β€žΡΠΊΠ΅Π»Π΅Ρ‚Π°β€œ Π½Π° Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° ΠΎΡ‚ нСйния Π΄Π²ΠΎΠΈΡ‡Π΅Π½ Ρ„Π°ΠΉΠ», ΠΊΠ°Ρ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΡΡŠΡ‰Π°Ρ‚Π° ΠΏΠΎΠΌΠΎΡ‰Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° bpftool β€” ΡˆΠ²Π΅ΠΉΡ†Π°Ρ€ΡΠΊΠΈΡΡ‚ Π½ΠΎΠΆ Π½Π° свСта Π½Π° BPF (ΠΊΠΎΠ΅Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΏΡ€ΠΈΠ΅ΠΌΠ΅ Π±ΡƒΠΊΠ²Π°Π»Π½ΠΎ, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Π”Π°Π½ΠΈΠ΅Π» Π‘ΠΎΡ€ΠΊΠΌΠ°Π½, Π΅Π΄ΠΈΠ½ ΠΎΡ‚ ΡΡŠΠ·Π΄Π°Ρ‚Π΅Π»ΠΈΡ‚Π΅ ΠΈ ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ°Ρ‰ΠΈΡ‚Π΅ BPF, Π΅ ΡˆΠ²Π΅ΠΉΡ†Π°Ρ€Π΅Ρ†):

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

Π’ΡŠΠ² Ρ„Π°ΠΉΠ»Π° xdp-simple.skel.h ΡΡŠΠ΄ΡŠΡ€ΠΆΠ° двоичния ΠΊΠΎΠ΄ Π½Π° Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π·Π° ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ - Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅, ΠΏΡ€ΠΈΠΊΠ°Ρ‡Π²Π°Π½Π΅, ΠΈΠ·Ρ‚Ρ€ΠΈΠ²Π°Π½Π΅ Π½Π° нашия ΠΎΠ±Π΅ΠΊΡ‚. Π’ нашия прост случай Ρ‚ΠΎΠ²Π° ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° прСсилСно, Π½ΠΎ Ρ€Π°Π±ΠΎΡ‚ΠΈ ΠΈ Π² случай, Ρ‡Π΅ обСктният Ρ„Π°ΠΉΠ» ΡΡŠΠ΄ΡŠΡ€ΠΆΠ° ΠΌΠ½ΠΎΠ³ΠΎ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ ΠΈ ΠΊΠ°Ρ€Ρ‚ΠΈ ΠΈ Π·Π° Π΄Π° Π·Π°Ρ€Π΅Π΄ΠΈΠΌ Ρ‚ΠΎΠ·ΠΈ гигантски ELF, Π½ΠΈΠ΅ просто трябва Π΄Π° Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°ΠΌΠ΅ скСлСта ΠΈ Π΄Π° ΠΈΠ·Π²ΠΈΠΊΠ°ΠΌΠ΅ Π΅Π΄Π½Π° ΠΈΠ»ΠΈ Π΄Π²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΎΡ‚ пСрсонализираното ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, ΠΊΠΎΠ΅Ρ‚ΠΎ ΠΏΠΈΡˆΠ°Ρ‚ Π”Π° ΠΏΡ€ΠΎΠ΄ΡŠΠ»ΠΆΠΈΠΌ сСга.

Π‘Ρ‚Ρ€ΠΎΠ³ΠΎ ΠΏΠΎΠ³Π»Π΅Π΄Π½Π°Ρ‚ΠΎ, Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Π·Π° Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅ Π΅ Ρ‚Ρ€ΠΈΠ²ΠΈΠ°Π»Π½Π°:

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

Π’ΡƒΠΊ struct xdp_simple_bpf Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π°Π½ΠΈ във Ρ„Π°ΠΉΠ»Π° xdp-simple.skel.h ΠΈ описва нашия ΠΎΠ±Π΅ΠΊΡ‚Π΅Π½ Ρ„Π°ΠΉΠ»:

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

Π’ΡƒΠΊ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Π²ΠΈΠ΄ΠΈΠΌ слСди ΠΎΡ‚ API Π½Π° ниско Π½ΠΈΠ²ΠΎ: структурата struct bpf_program *simple ΠΈ struct bpf_link *simple. ΠŸΡŠΡ€Π²Π°Ρ‚Π° структура ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎ описва Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°, написана Π² Ρ€Π°Π·Π΄Π΅Π»Π° xdp/simple, Π° Π²Ρ‚ΠΎΡ€Π°Ρ‚Π° описва ΠΊΠ°ΠΊ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° сС ΡΠ²ΡŠΡ€Π·Π²Π° с ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΠΊΠ° Π½Π° ΡΡŠΠ±ΠΈΡ‚ΠΈΠ΅Ρ‚ΠΎ.

Ѐункция xdp_simple_bpf__open_and_load, отваря ELF ΠΎΠ±Π΅ΠΊΡ‚, Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€Π° Π³ΠΎ, създава всички структури ΠΈ подструктури (освСн ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π°, ELF ΡΡŠΠ΄ΡŠΡ€ΠΆΠ° ΠΈ Π΄Ρ€ΡƒΠ³ΠΈ Ρ€Π°Π·Π΄Π΅Π»ΠΈ - Π΄Π°Π½Π½ΠΈ, Π΄Π°Π½Π½ΠΈ само Π·Π° Ρ‡Π΅Ρ‚Π΅Π½Π΅, информация Π·Π° отстраняванС Π½Π° Π³Ρ€Π΅ΡˆΠΊΠΈ, Π»ΠΈΡ†Π΅Π½Π· ΠΈ Ρ‚.Π½.) ΠΈ слСд Ρ‚ΠΎΠ²Π° Π³ΠΎ Π·Π°Ρ€Π΅ΠΆΠ΄Π° Π² ядрото с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° систСма ΠΎΠ±Π°Π΄Π΅Ρ‚Π΅ сС bpf, ΠΊΠΎΠ΅Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΠΌ Ρ‡Ρ€Π΅Π· ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€Π°Π½Π΅ ΠΈ изпълнСниС Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π°:

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

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

НСка сСга Π΄Π° Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‰Π° bpftool. НСка Π½Π°ΠΌΠ΅Ρ€ΠΈΠΌ нСйния ID:

# 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)

ΠΈ dump (ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΡΡŠΠΊΡ€Π°Ρ‚Π΅Π½Π° Ρ„ΠΎΡ€ΠΌΠ° Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄Π°Ρ‚Π° bpftool prog dump xlated):

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

НСщо Π½ΠΎΠ²ΠΎ! ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° ΠΎΡ‚ΠΏΠ΅Ρ‡Π°Ρ‚Π° части ΠΎΡ‚ нашия ΠΈΠ·Ρ…ΠΎΠ΄Π΅Π½ Ρ„Π°ΠΉΠ» Π½Π° C. Π’ΠΎΠ²Π° бСшС Π½Π°ΠΏΡ€Π°Π²Π΅Π½ΠΎ ΠΎΡ‚ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°Ρ‚Π° libbpf, ΠΊΠΎΠΉΡ‚ΠΎ Π½Π°ΠΌΠ΅Ρ€ΠΈ Ρ€Π°Π·Π΄Π΅Π»Π° Π·Π° отстраняванС Π½Π° Π³Ρ€Π΅ΡˆΠΊΠΈ Π² двоичния Ρ„Π°ΠΉΠ», ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€Π° Π³ΠΎ Π² BTF ΠΎΠ±Π΅ΠΊΡ‚, Π·Π°Ρ€Π΅Π΄ΠΈ Π³ΠΎ Π² ядрото с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° BPF_BTF_LOAD, ΠΈ слСд Ρ‚ΠΎΠ²Π° посочи рСзултантния Ρ„Π°ΠΉΠ»ΠΎΠ² дСскриптор ΠΏΡ€ΠΈ Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅ Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° с ΠΊΠΎΠΌΠ°Π½Π΄Π°Ρ‚Π° BPG_PROG_LOAD.

ΠŸΠΎΠΌΠΎΡ‰Π½ΠΈΡ†ΠΈ Π½Π° ядрото

BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° ΠΈΠ·ΠΏΡŠΠ»Π½ΡΠ²Π°Ρ‚ β€žΠ²ΡŠΠ½ΡˆΠ½ΠΈβ€œ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ - ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈΡ†ΠΈ Π½Π° ядрото. Π’Π΅Π·ΠΈ ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ позволяват Π½Π° BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅ Π΄Π° ΠΈΠΌΠ°Ρ‚ Π΄ΠΎΡΡ‚ΡŠΠΏ Π΄ΠΎ структуритС Π½Π° ядрото, Π΄Π° управляват ΠΊΠ°Ρ€Ρ‚ΠΈ ΠΈ ΡΡŠΡ‰ΠΎ Π΄Π° ΠΊΠΎΠΌΡƒΠ½ΠΈΠΊΠΈΡ€Π°Ρ‚ с β€žΡ€Π΅Π°Π»Π½ΠΈΡ ΡΠ²ΡΡ‚β€œ - Π΄Π° ΡΡŠΠ·Π΄Π°Π²Π°Ρ‚ ΠΏΠ΅Ρ€Ρ„ ΡΡŠΠ±ΠΈΡ‚ΠΈΡ, Π΄Π° ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΠΈΡ€Π°Ρ‚ Ρ…Π°Ρ€Π΄ΡƒΠ΅Ρ€Π° (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ прСнасочванС Π½Π° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ) ΠΈ Ρ‚.Π½.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€: bpf_get_smp_processor_id

Π’ Ρ€Π°ΠΌΠΊΠΈΡ‚Π΅ Π½Π° ΠΏΠ°Ρ€Π°Π΄ΠΈΠ³ΠΌΠ°Ρ‚Π° β€žΡƒΡ‡Π΅Π½Π΅ Ρ‡Ρ€Π΅Π· ΠΏΡ€ΠΈΠΌΠ΅Ρ€β€œ, Π½Π΅ΠΊΠ° Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ Π΅Π΄Π½Π° ΠΎΡ‚ ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈΡ‚Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, bpf_get_smp_processor_id(), ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈ във Ρ„Π°ΠΉΠ» kernel/bpf/helpers.c. Π’Ρ€ΡŠΡ‰Π° Π½ΠΎΠΌΠ΅Ρ€Π° Π½Π° процСсора, Π½Π° ΠΊΠΎΠΉΡ‚ΠΎ Ρ€Π°Π±ΠΎΡ‚ΠΈ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π°, която Π³ΠΎ Π΅ ΠΈΠ·Π²ΠΈΠΊΠ°Π»Π°. Но Π½Π΅ сС интСрСсувамС Ρ‚ΠΎΠ»ΠΊΠΎΠ²Π° ΠΎΡ‚ Π½Π΅Π³ΠΎΠ²Π°Ρ‚Π° сСмантика, ΠΊΠΎΠ»ΠΊΠΎΡ‚ΠΎ ΠΎΡ‚ Ρ„Π°ΠΊΡ‚Π°, Ρ‡Π΅ ΠΈΠ·ΠΏΡŠΠ»Π½Π΅Π½ΠΈΠ΅Ρ‚ΠΎ ΠΌΡƒ ΠΎΡ‚Π½Π΅ΠΌΠ° Π΅Π΄ΠΈΠ½ Ρ€Π΅Π΄:

BPF_CALL_0(bpf_get_smp_processor_id)
{
    return smp_processor_id();
}

Π”Π΅Ρ„ΠΈΠ½ΠΈΡ†ΠΈΠΈΡ‚Π΅ Π½Π° ΠΏΠΎΠΌΠΎΡ‰Π½Π°Ρ‚Π° функция Π½Π° BPF са ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΈ Π½Π° Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ†ΠΈΠΈΡ‚Π΅ Π½Π° систСмнитС повиквания Π½Π° Linux. Π’ΡƒΠΊ Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π΅ Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π°Π½Π° функция, която няма Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΈ. (Ѐункция, която ΠΏΡ€ΠΈΠ΅ΠΌΠ°, Π΄Π° Ρ€Π΅Ρ‡Π΅ΠΌ, Ρ‚Ρ€ΠΈ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π°, сС Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π° с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° макроса BPF_CALL_3. ΠœΠ°ΠΊΡΠΈΠΌΠ°Π»Π½ΠΈΡΡ‚ Π±Ρ€ΠΎΠΉ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΈ Π΅ ΠΏΠ΅Ρ‚.) Π’ΠΎΠ²Π° ΠΎΠ±Π°Ρ‡Π΅ Π΅ само ΠΏΡŠΡ€Π²Π°Ρ‚Π° част ΠΎΡ‚ дСфиницията. Π’Ρ‚ΠΎΡ€Π°Ρ‚Π° част Π΅ Π΄Π° сС Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π° структурата Π½Π° Ρ‚ΠΈΠΏΠ° struct bpf_func_proto, ΠΊΠΎΠΉΡ‚ΠΎ ΡΡŠΠ΄ΡŠΡ€ΠΆΠ° описаниС Π½Π° ΠΏΠΎΠΌΠΎΡ‰Π½Π°Ρ‚Π° функция, която Π²Π΅Ρ€ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΡŠΡ‚ Ρ€Π°Π·Π±ΠΈΡ€Π°:

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

РСгистриранС Π½Π° ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ

Π—Π° Π΄Π° ΠΌΠΎΠ³Π°Ρ‚ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ ΠΎΡ‚ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ Ρ‚ΠΈΠΏ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ Ρ‚Π°Π·ΠΈ функция, Ρ‚Π΅ трябва Π΄Π° я рСгистрират, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° Ρ‚ΠΈΠΏΠ° BPF_PROG_TYPE_XDP функция Π΅ Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π°Π½Π° Π² ядрото xdp_func_proto, ΠΊΠΎΠΉΡ‚ΠΎ опрСдСля ΠΎΡ‚ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Π° Π½Π° ΠΏΠΎΠΌΠΎΡ‰Π½Π°Ρ‚Π° функция Π΄Π°Π»ΠΈ XDP ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ° Ρ‚Π°Π·ΠΈ функция ΠΈΠ»ΠΈ Π½Π΅. ΠΠ°ΡˆΠ°Ρ‚Π° функция Π΅ ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ°:

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

Нови Ρ‚ΠΈΠΏΠΎΠ²Π΅ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ са "Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π°Π½ΠΈ" във Ρ„Π°ΠΉΠ»Π° include/linux/bpf_types.h с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° макрос BPF_PROG_TYPE. Π”Π΅Ρ„ΠΈΠ½ΠΈΡ€Π°Π½ Π² ΠΊΠ°Π²ΠΈΡ‡ΠΊΠΈ, Π·Π°Ρ‰ΠΎΡ‚ΠΎ Ρ‚ΠΎΠ²Π° Π΅ логичСска дСфиниция, Π° Π² Ρ‚Π΅Ρ€ΠΌΠΈΠ½ΠΈΡ‚Π΅ Π½Π° Π΅Π·ΠΈΠΊΠ° C дСфиницията Π½Π° цял Π½Π°Π±ΠΎΡ€ ΠΎΡ‚ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΈ структури сС срСща Π½Π° Π΄Ρ€ΡƒΠ³ΠΈ мСста. По-спСциално във Ρ„Π°ΠΉΠ»Π° kernel/bpf/verifier.c всички Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ†ΠΈΠΈ ΠΎΡ‚ Ρ„Π°ΠΉΠ»Π° bpf_types.h сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ Π·Π° създаванС Π½Π° масив ΠΎΡ‚ структури bpf_verifier_ops[]:

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

ВоСст, Π·Π° всСки Ρ‚ΠΈΠΏ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° сС Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π° ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π» към структура ΠΎΡ‚ Π΄Π°Π½Π½ΠΈ Π½Π° Ρ‚ΠΈΠΏΠ° struct bpf_verifier_ops, ΠΊΠΎΠΉΡ‚ΠΎ сС ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€Π° със стойността _name ## _verifier_ops, Ρ‚.Π΅. xdp_verifier_ops Π·Π° xdp. Π‘Ρ‚Ρ€ΡƒΠΊΡ‚ΡƒΡ€Π° xdp_verifier_ops ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΎ ΠΎΡ‚ във Ρ„Π°ΠΉΠ» net/core/filter.c ΠΊΠ°ΠΊΡ‚ΠΎ слСдва:

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

Π’ΡƒΠΊ Π²ΠΈΠΆΠ΄Π°ΠΌΠ΅ ΠΏΠΎΠ·Π½Π°Ρ‚Π°Ρ‚Π° Π½ΠΈ функция xdp_func_proto, ΠΊΠΎΠΉΡ‚ΠΎ Ρ‰Π΅ стартира Π²Π΅Ρ€ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Π° всСки ΠΏΡŠΡ‚, ΠΊΠΎΠ³Π°Ρ‚ΠΎ срСщнС прСдизвикатСлство някакъв Π²ΠΈΠ΄ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π² BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°, Π²ΠΈΠΆΡ‚Π΅ verifier.c.

НСка Π΄Π° Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΊΠ°ΠΊ Π΅Π΄Π½Π° Ρ…ΠΈΠΏΠΎΡ‚Π΅Ρ‚ΠΈΡ‡Π½Π° BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° функцията bpf_get_smp_processor_id. Π—Π° Π΄Π° Π½Π°ΠΏΡ€Π°Π²ΠΈΠΌ Ρ‚ΠΎΠ²Π°, прСнаписвамС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° ΠΎΡ‚ ΠΏΡ€Π΅Π΄ΠΈΡˆΠ½ΠΈΡ Π½ΠΈ Ρ€Π°Π·Π΄Π΅Π», ΠΊΠ°ΠΊΡ‚ΠΎ слСдва:

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

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

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

Π‘ΠΈΠΌΠ²ΠΎΠ» bpf_get_smp_processor_id ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΎ ΠΎΡ‚ Π² <bpf/bpf_helper_defs.h> Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° libbpf ΠΊΠ°Ρ‚ΠΎ

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

Ρ‚ΠΎΠ²Π° Π΅, bpf_get_smp_processor_id Π΅ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π» Π½Π° функция, чиято стойност Π΅ 8, ΠΊΡŠΠ΄Π΅Ρ‚ΠΎ 8 Π΅ стойността BPF_FUNC_get_smp_processor_id Ρ‚ΠΈΠΏΠ° enum bpf_fun_id, ΠΊΠΎΠΉΡ‚ΠΎ Π΅ Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π°Π½ Π·Π° нас във Ρ„Π°ΠΉΠ»Π° vmlinux.h (Ρ„Π°ΠΉΠ» bpf_helper_defs.h Π² ядрото сС Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π° ΠΎΡ‚ скрипт, Ρ‚Π°ΠΊΠ° Ρ‡Π΅ β€žΠΌΠ°Π³ΠΈΡ‡Π΅ΡΠΊΠΈΡ‚Π΅β€œ числа са ΠΎΠΊ). Π’Π°Π·ΠΈ функция Π½Π΅ ΠΏΡ€ΠΈΠ΅ΠΌΠ° Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΈ ΠΈ Π²Ρ€ΡŠΡ‰Π° стойност ΠΎΡ‚ Ρ‚ΠΈΠΏ __u32. ΠšΠΎΠ³Π°Ρ‚ΠΎ Π³ΠΎ стартирамС Π² Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°, clang Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π° инструкция BPF_CALL "правилният Π²ΠΈΠ΄" НСка ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€Π°ΠΌΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° ΠΈ Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ сСкцията xdp/simple:

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

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

Disassembly of section xdp/simple:

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

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

Π’ ΠΏΡŠΡ€Π²ΠΈΡ Ρ€Π΅Π΄ Π²ΠΈΠΆΠ΄Π°ΠΌΠ΅ инструкции call, ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚ΡŠΡ€ IMM ΠΊΠΎΠ΅Ρ‚ΠΎ Π΅ Ρ€Π°Π²Π½ΠΎ Π½Π° 8, ΠΈ SRC_REG - Π½ΡƒΠ»Π°. Π‘ΠΏΠΎΡ€Π΅Π΄ ABI споразумСниСто, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½ΠΎ ΠΎΡ‚ Π²Π΅Ρ€ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Π°, Ρ‚ΠΎΠ²Π° Π΅ ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅ Π½Π° ΠΏΠΎΠΌΠΎΡ‰Π½Π° функция Π½ΠΎΠΌΠ΅Ρ€ осСм. Π‘Π»Π΅Π΄ ΠΊΠ°Ρ‚ΠΎ сС стартира, Π»ΠΎΠ³ΠΈΠΊΠ°Ρ‚Π° Π΅ проста. Π’ΡŠΡ€Π½Π°Ρ‚Π° стойност ΠΎΡ‚ Ρ€Π΅Π³ΠΈΡΡ‚ΡŠΡ€Π° r0 ΠΊΠΎΠΏΠΈΡ€Π°Π½ΠΎ Π² r1 ΠΈ Π½Π° Ρ€Π΅Π΄ΠΎΠ²Π΅ 2,3 сС ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ²Π° Π² Ρ‚ΠΈΠΏ u32 β€” Π³ΠΎΡ€Π½ΠΈΡ‚Π΅ 32 Π±ΠΈΡ‚Π° сС изчистват. На Ρ€Π΅Π΄ΠΎΠ²Π΅ 4,5,6,7 Π²Ρ€ΡŠΡ‰Π°ΠΌΠ΅ 2 (XDP_PASS) ΠΈΠ»ΠΈ 1 (XDP_DROP) Π² зависимост ΠΎΡ‚ Ρ‚ΠΎΠ²Π° Π΄Π°Π»ΠΈ ΠΏΠΎΠΌΠΎΡ‰Π½Π°Ρ‚Π° функция ΠΎΡ‚ Ρ€Π΅Π΄ 0 Π΅ Π²ΡŠΡ€Π½Π°Π»Π° Π½ΡƒΠ»Π΅Π²Π° ΠΈΠ»ΠΈ Π½Π΅Π½ΡƒΠ»Π΅Π²Π° стойност.

НСка сС тСствамС: Π·Π°Ρ€Π΅Π΄Π΅Ρ‚Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° ΠΈ ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅Ρ‚Π΅ ΠΈΠ·Ρ…ΠΎΠ΄Π° 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

Π”ΠΎΠ±Ρ€Π΅, Π²Π΅Ρ€ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΡŠΡ‚ Π½Π°ΠΌΠ΅Ρ€ΠΈ правилния ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈΠΊ Π½Π° ядрото.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€: ΠΏΡ€Π΅Π΄Π°Π²Π°Π½Π΅ Π½Π° Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΈ ΠΈ накрая изпълнСниС Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π°!

Всички ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π½Π° Π½ΠΈΠ²ΠΎ изпълнСниС ΠΈΠΌΠ°Ρ‚ ΠΏΡ€ΠΎΡ‚ΠΎΡ‚ΠΈΠΏ

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

ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈΡ‚Π΅ Π½Π° ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈΡ‚Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ сС ΠΏΡ€Π΅Π΄Π°Π²Π°Ρ‚ Π² рСгистритС r1-r5ΠΈ стойността сС Π²Ρ€ΡŠΡ‰Π° Π² Ρ€Π΅Π³ΠΈΡΡ‚ΡŠΡ€Π° r0. Няма Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ ΠΏΡ€ΠΈΠ΅ΠΌΠ°Ρ‚ ΠΏΠΎΠ²Π΅Ρ‡Π΅ ΠΎΡ‚ ΠΏΠ΅Ρ‚ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π° ΠΈ Π½Π΅ сС ΠΎΡ‡Π°ΠΊΠ²Π° ΠΏΠΎΠ΄Π΄Ρ€ΡŠΠΆΠΊΠ° Π·Π° тях Π΄Π° бъдС Π΄ΠΎΠ±Π°Π²Π΅Π½Π° Π² Π±ΡŠΠ΄Π΅Ρ‰Π΅.

НСка Π΄Π° Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ новия ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈΠΊ Π½Π° ядрото ΠΈ ΠΊΠ°ΠΊ BPF ΠΏΡ€Π΅Π΄Π°Π²Π° ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈ. Π”Π° ΠΏΡ€Π΅Π½Π°ΠΏΠΈΡˆΠ΅ΠΌ xdp-simple.bpf.c ΠΊΠ°ΠΊΡ‚ΠΎ слСдва (останалитС Ρ€Π΅Π΄ΠΎΠ²Π΅ Π½Π΅ са ΠΏΡ€ΠΎΠΌΠ΅Π½Π΅Π½ΠΈ):

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

ΠΠ°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° ΠΎΡ‚ΠΏΠ΅Ρ‡Π°Ρ‚Π²Π° Π½ΠΎΠΌΠ΅Ρ€Π° Π½Π° процСсора, Π½Π° ΠΊΠΎΠΉΡ‚ΠΎ Ρ€Π°Π±ΠΎΡ‚ΠΈ. НСка Π³ΠΎ ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€Π°ΠΌΠ΅ ΠΈ Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΊΠΎΠ΄Π°:

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

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

Π’ Ρ€Π΅Π΄ΠΎΠ²Π΅ 0-7 записвамС Π½ΠΈΠ·Π° running on CPU%un, Π° слСд Ρ‚ΠΎΠ²Π° Π½Π° Ρ€Π΅Π΄ 8 изпълнявамС познатия bpf_get_smp_processor_id. На Ρ€Π΅Π΄ΠΎΠ²Π΅ 9-12 подготвямС ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈΡ‚Π΅ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΈ bpf_printk - рСгистри r1, r2, r3. Π—Π°Ρ‰ΠΎ са Ρ‚Ρ€ΠΈ, Π° Π½Π΅ Π΄Π²Π΅? Π·Π°Ρ‰ΠΎΡ‚ΠΎ bpf_printkΡ‚ΠΎΠ²Π° Π΅ ΠΎΠ±Π²ΠΈΠ²ΠΊΠ° Π½Π° макроси ΠΎΠΊΠΎΠ»ΠΎ истинския ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈΠΊ bpf_trace_printk, ΠΊΠΎΠΉΡ‚ΠΎ трябва Π΄Π° ΠΏΡ€Π΅Π΄Π°Π΄Π΅ Ρ€Π°Π·ΠΌΠ΅Ρ€Π° Π½Π° форматиращия Π½ΠΈΠ·.

НСка сСга Π΄ΠΎΠ±Π°Π²ΠΈΠΌ няколко Ρ€Π΅Π΄Π° към xdp-simple.cΡ‚Π°ΠΊΠ° Ρ‡Π΅ Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Π΄Π° сС ΡΠ²ΡŠΡ€ΠΆΠ΅ с интСрфСйса lo ΠΈ наистина Π·Π°ΠΏΠΎΡ‡Π½Π°!

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

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

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

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

cleanup:
    xdp_simple_bpf__destroy(obj);
}

Π’ΡƒΠΊ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ функцията bpf_set_link_xdp_fd, ΠΊΠΎΠΉΡ‚ΠΎ ΡΠ²ΡŠΡ€Π·Π²Π° BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ ΠΎΡ‚ Ρ‚ΠΈΠΏ XDP към ΠΌΡ€Π΅ΠΆΠΎΠ²ΠΈ интСрфСйси. Π’Π²ΡŠΡ€Π΄ΠΎ ΠΊΠΎΠ΄ΠΈΡ€Π°Ρ…ΠΌΠ΅ Π½ΠΎΠΌΠ΅Ρ€Π° Π½Π° интСрфСйса lo, ΠΊΠΎΠ΅Ρ‚ΠΎ Π²ΠΈΠ½Π°Π³ΠΈ Π΅ 1. ИзпълнявамС функцията Π΄Π²Π° ΠΏΡŠΡ‚ΠΈ, Π·Π° Π΄Π° ΠΎΡ‚ΠΊΠ°Ρ‡ΠΈΠΌ ΠΏΡŠΡ€Π²ΠΎ старата ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°, Π°ΠΊΠΎ Π΅ Π±ΠΈΠ»Π° ΠΏΡ€ΠΈΠΊΠ°Ρ‡Π΅Π½Π°. Π—Π°Π±Π΅Π»Π΅ΠΆΠ΅Ρ‚Π΅, Ρ‡Π΅ сСга нямамС Π½ΡƒΠΆΠ΄Π° ΠΎΡ‚ прСдизвикатСлство pause ΠΈΠ»ΠΈ Π±Π΅Π·ΠΊΡ€Π°Π΅Π½ Ρ†ΠΈΠΊΡŠΠ»: Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Π·Π° Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅ Ρ‰Π΅ ΠΈΠ·Π»Π΅Π·Π΅, Π½ΠΎ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° BPF няма Π΄Π° бъдС ΡƒΠ±ΠΈΡ‚Π°, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Π΅ ΡΠ²ΡŠΡ€Π·Π°Π½Π° към ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΠΊΠ° Π½Π° ΡΡŠΠ±ΠΈΡ‚ΠΈΠ΅. Π‘Π»Π΅Π΄ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ изтСглянС ΠΈ ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅, ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° Ρ‰Π΅ сС стартира Π·Π° всСки пристигащ ΠΌΡ€Π΅ΠΆΠΎΠ² ΠΏΠ°ΠΊΠ΅Ρ‚ lo.

НСка ΠΈΠ·Ρ‚Π΅Π³Π»ΠΈΠΌ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° ΠΈ Π΄Π° Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ интСрфСйса 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

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π°, която ΠΈΠ·Ρ‚Π΅Π³Π»ΠΈΡ…ΠΌΠ΅, ΠΈΠΌΠ° ID 669 ΠΈ Π²ΠΈΠΆΠ΄Π°ΠΌΠ΅ ΡΡŠΡ‰ΠΈΡ ID Π½Π° интСрфСйса lo. Π©Π΅ ΠΈΠ·ΠΏΡ€Π°Ρ‚ΠΈΠΌ няколко ΠΏΠ°ΠΊΠ΅Ρ‚Π° Π½Π° 127.0.0.1 (заявка + ΠΎΡ‚Π³ΠΎΠ²ΠΎΡ€):

$ ping -c1 localhost

Π° сСга Π½Π΅ΠΊΠ° Π΄Π° Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π° виртуалния Ρ„Π°ΠΉΠ» Π·Π° отстраняванС Π½Π° Π³Ρ€Π΅ΡˆΠΊΠΈ /sys/kernel/debug/tracing/trace_pipe, Π² ΠΊΠΎΠΉΡ‚ΠΎ bpf_printk пишС ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡΡ‚Π° си:

# 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

Бяха забСлязани Π΄Π²Π° ΠΏΠ°ΠΊΠ΅Ρ‚Π° lo ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π΅Π½ Π½Π° CPU0 - ΠΏΡŠΡ€Π²Π°Ρ‚Π° Π½ΠΈ ΠΏΡŠΠ»Π½ΠΎΡ†Π΅Π½Π½Π° бСзсмислСна BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Ρ€Π°Π±ΠΎΡ‚ΠΈ!

ЗаслуТава Π΄Π° сС ΠΎΡ‚Π±Π΅Π»Π΅ΠΆΠΈ, Ρ‡Π΅ bpf_printk НС Π΅ Π·Π° Π½ΠΈΡ‰ΠΎ, Ρ‡Π΅ пишС във Ρ„Π°ΠΉΠ»Π° Π·Π° отстраняванС Π½Π° Π³Ρ€Π΅ΡˆΠΊΠΈ: Ρ‚ΠΎΠ²Π° Π½Π΅ Π΅ Π½Π°ΠΉ-ΡƒΡΠΏΠ΅ΡˆΠ½ΠΈΡΡ‚ ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈΠΊ Π·Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π² производството, Π½ΠΎ Π½Π°ΡˆΠ°Ρ‚Π° Ρ†Π΅Π» бСшС Π΄Π° ΠΏΠΎΠΊΠ°ΠΆΠ΅ΠΌ Π½Π΅Ρ‰ΠΎ просто.

Π”ΠΎΡΡ‚ΡŠΠΏ Π΄ΠΎ ΠΊΠ°Ρ€Ρ‚ΠΈ ΠΎΡ‚ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ

ΠŸΡ€ΠΈΠΌΠ΅Ρ€: ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° ΠΊΠ°Ρ€Ρ‚Π° ΠΎΡ‚ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° BPF

Π’ ΠΏΡ€Π΅Π΄ΠΈΡˆΠ½ΠΈΡ‚Π΅ Ρ€Π°Π·Π΄Π΅Π»ΠΈ Π½Π°ΡƒΡ‡ΠΈΡ…ΠΌΠ΅ ΠΊΠ°ΠΊ Π΄Π° създавамС ΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΠΊΠ°Ρ€Ρ‚ΠΈ ΠΎΡ‚ потрСбитСлското пространство, Π° сСга Π½Π΅ΠΊΠ° Π΄Π° Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ частта ΠΎΡ‚ ядрото. НСка Π·Π°ΠΏΠΎΡ‡Π½Π΅ΠΌ, ΠΊΠ°ΠΊΡ‚ΠΎ ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ, с ΠΏΡ€ΠΈΠΌΠ΅Ρ€. НСка ΠΏΡ€Π΅Π½Π°ΠΏΠΈΡˆΠ΅ΠΌ Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° xdp-simple.bpf.c ΠΊΠ°ΠΊΡ‚ΠΎ слСдва:

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

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

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

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

    *val += 1;

    return XDP_PASS;
}

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

Π’ Π½Π°Ρ‡Π°Π»ΠΎΡ‚ΠΎ Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° Π΄ΠΎΠ±Π°Π²ΠΈΡ…ΠΌΠ΅ дСфиниция Π½Π° ΠΊΠ°Ρ€Ρ‚Π° woo: Π’ΠΎΠ²Π° Π΅ масив ΠΎΡ‚ 8 Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚Π°, ΠΊΠΎΠΉΡ‚ΠΎ ΡΡŠΡ…Ρ€Π°Π½ΡΠ²Π° стойности ΠΊΠ°Ρ‚ΠΎ u64 (Π² C Π±ΠΈΡ…ΠΌΠ΅ Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π°Π»ΠΈ Ρ‚Π°ΠΊΡŠΠ² масив ΠΊΠ°Ρ‚ΠΎ u64 woo[8]). Π’ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° "xdp/simple" ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π°ΠΌΠ΅ тСкущия Π½ΠΎΠΌΠ΅Ρ€ Π½Π° процСсора Π² ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²Π° key ΠΈ слСд Ρ‚ΠΎΠ²Π° с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° ΠΏΠΎΠΌΠΎΡ‰Π½Π°Ρ‚Π° функция bpf_map_lookup_element ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π°ΠΌΠ΅ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π» към ΡΡŠΠΎΡ‚Π²Π΅Ρ‚Π½ΠΈΡ запис Π² масива, ΠΊΠΎΠΉΡ‚ΠΎ ΡƒΠ²Π΅Π»ΠΈΡ‡Π°Π²Π°ΠΌΠ΅ с Π΅Π΄ΠΈΠ½ΠΈΡ†Π°. ΠŸΡ€Π΅Π²Π΅Π΄Π΅Π½ΠΎ Π½Π° руски: Π½ΠΈΠ΅ изчислявамС статистика Π·Π° Ρ‚ΠΎΠ²Π° ΠΊΠΎΠΉ процСсор Π΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΈΠ» входящитС ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ. НСка сС ΠΎΠΏΠΈΡ‚Π°ΠΌΠ΅ Π΄Π° стартирамС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π°:

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

НСка ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΠΌ Π΄Π°Π»ΠΈ Π΅ ΡΠ²ΡŠΡ€Π·Π°Π½Π° с 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 108

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

Π‘Π΅Π³Π° Π½Π΅ΠΊΠ° Π΄Π° Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π° масива:

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

ΠŸΠΎΡ‡Ρ‚ΠΈ всички процСси бяха ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π΅Π½ΠΈ Π½Π° CPU7. Π’ΠΎΠ²Π° Π½Π΅ Π΅ Π²Π°ΠΆΠ½ΠΎ Π·Π° нас, основното Π΅, Ρ‡Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° Ρ€Π°Π±ΠΎΡ‚ΠΈ ΠΈ Π½ΠΈΠ΅ Ρ€Π°Π·Π±ΠΈΡ€Π°ΠΌΠ΅ ΠΊΠ°ΠΊ Π΄Π° ΠΈΠΌΠ°ΠΌΠ΅ Π΄ΠΎΡΡ‚ΡŠΠΏ Π΄ΠΎ ΠΊΠ°Ρ€Ρ‚ΠΈ ΠΎΡ‚ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ - ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ Ρ…Π΅Π»ΠΏΠ΅Ρ€ΠΎΠ² bpf_mp_*.

ΠœΠΈΡΡ‚ΠΈΡ‡Π΅Π½ индСкс

Π’Π°ΠΊΠ° Ρ‡Π΅ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ Π΄ΠΎΡΡ‚ΡŠΠΏ Π΄ΠΎ ΠΊΠ°Ρ€Ρ‚Π°Ρ‚Π° ΠΎΡ‚ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° BPF, ΠΊΠ°Ρ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ обаТдания ΠΊΠ°Ρ‚ΠΎ

val = bpf_map_lookup_elem(&woo, &key);

къдС ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° ΠΏΠΎΠΌΠΎΡ‰Π½Π°Ρ‚Π° функция

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

Π½ΠΎ ΠΌΠΈΠ½Π°Π²Π°ΠΌΠ΅ ΠΏΠΎΠΊΡ€Π°ΠΉ ΠΏΠΎΠΊΠ°Π·Π°Π»Π΅Ρ† &woo към Π½Π΅Π½Π°Π·ΠΎΠ²Π°Π½Π° структура struct { ... }...

Ако ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅ΠΌ асСмблСра Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π°, Π²ΠΈΠΆΠ΄Π°ΠΌΠ΅, Ρ‡Π΅ стойността &woo Π²ΡΡŠΡ‰Π½ΠΎΡΡ‚ Π½Π΅ Π΅ Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π°Π½ (Ρ€Π΅Π΄ 4):

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

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

Disassembly of section xdp/simple:

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

ΠΈ сС ΡΡŠΠ΄ΡŠΡ€ΠΆΠ° Π² прСмСствания:

$ 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

Но Π°ΠΊΠΎ ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅ΠΌ Π²Π΅Ρ‡Π΅ Π·Π°Ρ€Π΅Π΄Π΅Π½Π°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°, Π²ΠΈΠΆΠ΄Π°ΠΌΠ΅ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π» към ΠΏΡ€Π°Π²ΠΈΠ»Π½Π°Ρ‚Π° ΠΊΠ°Ρ€Ρ‚Π° (Ρ€Π΅Π΄ 4):

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

По Ρ‚ΠΎΠ·ΠΈ Π½Π°Ρ‡ΠΈΠ½ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Π·Π°ΠΊΠ»ΡŽΡ‡ΠΈΠΌ, Ρ‡Π΅ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° Π½Π° стартиранС Π½Π° Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Π·Π° Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅, Π²Ρ€ΡŠΠ·ΠΊΠ°Ρ‚Π° към &woo бСшС Π·Π°ΠΌΠ΅Π½Π΅Π½ с Π½Π΅Ρ‰ΠΎ с Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° libbpf. ΠŸΡŠΡ€Π²ΠΎ Ρ‰Π΅ Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΈΠ·Ρ…ΠΎΠ΄Π° strace:

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

НиС Π²ΠΈΠΆΠ΄Π°ΠΌΠ΅ Ρ‚ΠΎΠ²Π° libbpf създадС ΠΊΠ°Ρ€Ρ‚Π° woo ΠΈ слСд Ρ‚ΠΎΠ²Π° ΠΈΠ·Ρ‚Π΅Π³Π»ΠΈ Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° simple. НСка Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΏΠΎ-ΠΎΡ‚Π±Π»ΠΈΠ·ΠΎ ΠΊΠ°ΠΊ Π·Π°Ρ€Π΅ΠΆΠ΄Π°ΠΌΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π°:

  • ΠΎΠ±Π°Π΄Π΅Ρ‚Π΅ сС xdp_simple_bpf__open_and_load ΠΎΡ‚ Ρ„Π°ΠΉΠ» xdp-simple.skel.h
  • ΠΊΠΎΠ΅Ρ‚ΠΎ причинява xdp_simple_bpf__load ΠΎΡ‚ Ρ„Π°ΠΉΠ» xdp-simple.skel.h
  • ΠΊΠΎΠ΅Ρ‚ΠΎ причинява bpf_object__load_skeleton ΠΎΡ‚ Ρ„Π°ΠΉΠ» libbpf/src/libbpf.c
  • ΠΊΠΎΠ΅Ρ‚ΠΎ причинява bpf_object__load_xattr Π½Π° libbpf/src/libbpf.c

ΠŸΠΎΡΠ»Π΅Π΄Π½Π°Ρ‚Π° функция, Π½Π°Ρ€Π΅Π΄ с Π΄Ρ€ΡƒΠ³ΠΈ Π½Π΅Ρ‰Π°, Ρ‰Π΅ ΠΈΠ·Π²ΠΈΠΊΠ° bpf_object__create_maps, ΠΊΠΎΠΉΡ‚ΠΎ създава ΠΈΠ»ΠΈ отваря ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π°Ρ‰ΠΈ ΠΊΠ°Ρ€Ρ‚ΠΈ, ΠΏΡ€Π΅Π²Ρ€ΡŠΡ‰Π°ΠΉΠΊΠΈ Π³ΠΈ във Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΈ дСскриптори. (Π’ΡƒΠΊ Π²ΠΈΠΆΠ΄Π°ΠΌΠ΅ BPF_MAP_CREATE Π² ΠΈΠ·Ρ…ΠΎΠ΄Π° strace.) Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° сС ΠΈΠ·Π²ΠΈΠΊΠ²Π° функцията bpf_object__relocate ΠΈ тя Π΅ Ρ‚Π°Π·ΠΈ, която Π½ΠΈ интСрСсува, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ ΠΏΠΎΠΌΠ½ΠΈΠΌ ΠΊΠ°ΠΊΠ²ΠΎ смС Π²ΠΈΠ΄Π΅Π»ΠΈ woo Π² Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π° Π·Π° прСмСстванС. ИзслСдвайки Π³ΠΎ, Π² ΠΊΡ€Π°ΠΉΠ½Π° смСтка сС ΠΎΠ·ΠΎΠ²Π°Π²Π°ΠΌΠ΅ във функцията bpf_program__relocate, ΠΊΠΎΠΉΡ‚ΠΎ Π·Π°Π½ΠΈΠΌΠ°Π²Π° сС с прСмСстванС Π½Π° ΠΊΠ°Ρ€Ρ‚ΠΈ:

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

Π’Π°ΠΊΠ° Ρ‡Π΅ ΠΏΡ€ΠΈΠ΅ΠΌΠ°ΠΌΠ΅ Π½Π°ΡˆΠΈΡ‚Π΅ инструкции

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

ΠΈ Π·Π°ΠΌΠ΅Π½Π΅Ρ‚Π΅ Ρ€Π΅Π³ΠΈΡΡ‚ΡŠΡ€Π° ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ Π² Π½Π΅Π³ΠΎ с BPF_PSEUDO_MAP_FDΠΈ ΠΏΡŠΡ€Π²ΠΈΡ IMM към файловия дСскриптор Π½Π° Π½Π°ΡˆΠ°Ρ‚Π° ΠΊΠ°Ρ€Ρ‚Π° ΠΈ, Π°ΠΊΠΎ Π΅ Ρ€Π°Π²Π΅Π½ Π½Π°, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, 0xdeadbeef, Ρ‚ΠΎΠ³Π°Π²Π° Π² Ρ€Π΅Π·ΡƒΠ»Ρ‚Π°Ρ‚ Ρ‰Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ инструкцията

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

Π•Ρ‚ΠΎ ΠΊΠ°ΠΊ информацията Π·Π° ΠΊΠ°Ρ€Ρ‚Π°Ρ‚Π° сС ΠΏΡ€Π΅Ρ…Π²ΡŠΡ€Π»Ρ към ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Π° Π·Π°Ρ€Π΅Π΄Π΅Π½Π° BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°. Π’ Ρ‚ΠΎΠ·ΠΈ случай ΠΊΠ°Ρ€Ρ‚Π°Ρ‚Π° ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС създадСна с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° BPF_MAP_CREATE, ΠΈ ΠΎΡ‚Π²ΠΎΡ€Π΅Π½ с ID с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° BPF_MAP_GET_FD_BY_ID.

ΠžΠ±Ρ‰ΠΎ ΠΏΡ€ΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ libbpf Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΡŠΠΌΡŠΡ‚ Π΅ слСдният:

  • ΠΏΠΎ Π²Ρ€Π΅ΠΌΠ΅ Π½Π° ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€Π°Π½Π΅Ρ‚ΠΎ сС ΡΡŠΠ·Π΄Π°Π²Π°Ρ‚ записи Π² Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π° Π·Π° прСмСстванС Π·Π° Π²Ρ€ΡŠΠ·ΠΊΠΈ към ΠΊΠ°Ρ€Ρ‚ΠΈ
  • libbpf отваря ΠΊΠ½ΠΈΠ³Π°Ρ‚Π° с ΠΎΠ±Π΅ΠΊΡ‚ΠΈ ELF, Π½Π°ΠΌΠΈΡ€Π° всички ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½ΠΈ ΠΊΠ°Ρ€Ρ‚ΠΈ ΠΈ създава Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΈ дСскриптори Π·Π° тях
  • Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΈΡ‚Π΅ дСскриптори сС Π·Π°Ρ€Π΅ΠΆΠ΄Π°Ρ‚ Π² ядрото ΠΊΠ°Ρ‚ΠΎ част ΠΎΡ‚ инструкцията LD64

ΠšΠ°ΠΊΡ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° си прСдставитС, прСдстои ΠΎΡ‰Π΅ Π½Π΅Ρ‰ΠΎ ΠΈ Ρ‰Π΅ трябва Π΄Π° ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅ΠΌ Π² ΡΡŠΡ‰ΠΈΠ½Π°Ρ‚Π°. Π—Π° щастиС ΠΈΠΌΠ°ΠΌΠ΅ прСдстава - записали смС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅Ρ‚ΠΎ BPF_PSEUDO_MAP_FD Π² Ρ€Π΅Π³ΠΈΡΡ‚ΡŠΡ€Π° Π½Π° ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΠΊΠ° ΠΈ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Π³ΠΎ Π·Π°Ρ€ΠΎΠ²ΠΈΠΌ, ΠΊΠΎΠ΅Ρ‚ΠΎ Ρ‰Π΅ Π½ΠΈ ΠΎΡ‚Π²Π΅Π΄Π΅ Π΄ΠΎ свСтая свСтия - kernel/bpf/verifier.c, ΠΊΡŠΠ΄Π΅Ρ‚ΠΎ функция с ΠΎΡ‚Π»ΠΈΡ‡ΠΈΡ‚Π΅Π»Π½ΠΎ ΠΈΠΌΠ΅ замСства Ρ„Π°ΠΉΠ»ΠΎΠ² дСскриптор с адрСса Π½Π° структура ΠΎΡ‚ Ρ‚ΠΈΠΏ struct bpf_map:

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

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

(ΠΏΡŠΠ»Π½ΠΈΡΡ‚ ΠΊΠΎΠ΄ ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС Π½Π°ΠΌΠ΅Ρ€Π΅Π½ ΠΏΠΎ ссылкС). Π’Π°ΠΊΠ° Ρ‡Π΅ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Ρ€Π°Π·ΡˆΠΈΡ€ΠΈΠΌ нашия Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΡŠΠΌ:

  • Π΄ΠΎΠΊΠ°Ρ‚ΠΎ Π·Π°Ρ€Π΅ΠΆΠ΄Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π°, Π²Π΅Ρ€ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΡŠΡ‚ провСрява ΠΏΡ€Π°Π²ΠΈΠ»Π½ΠΎΡ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° ΠΊΠ°Ρ€Ρ‚Π°Ρ‚Π° ΠΈ записва адрСса Π½Π° ΡΡŠΠΎΡ‚Π²Π΅Ρ‚Π½Π°Ρ‚Π° структура struct bpf_map

ΠšΠΎΠ³Π°Ρ‚ΠΎ изтСглятС двоичния Ρ„Π°ΠΉΠ» Π½Π° ELF, ΠΊΠ°Ρ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ libbpf Има ΠΎΡ‰Π΅ ΠΌΠ½ΠΎΠ³ΠΎ Π½Π΅Ρ‰Π°, Π½ΠΎ Ρ‰Π΅ обсъдим Ρ‚ΠΎΠ²Π° Π² Π΄Ρ€ΡƒΠ³ΠΈ статии.

Π—Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅ Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ ΠΈ ΠΊΠ°Ρ€Ρ‚ΠΈ Π±Π΅Π· libbpf

ΠšΠ°ΠΊΡ‚ΠΎ бСшС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΎ, Π΅Ρ‚ΠΎ Π΅Π΄ΠΈΠ½ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° Ρ‡ΠΈΡ‚Π°Ρ‚Π΅Π»ΠΈΡ‚Π΅, ΠΊΠΎΠΈΡ‚ΠΎ искат Π΄Π° знаят ΠΊΠ°ΠΊ Π΄Π° ΡΡŠΠ·Π΄Π°Π΄Π°Ρ‚ ΠΈ зарСдят ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°, която ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° ΠΊΠ°Ρ€Ρ‚ΠΈ, Π±Π΅Π· Ρ‡ΡƒΠΆΠ΄Π° ΠΏΠΎΠΌΠΎΡ‰ libbpf. Π’ΠΎΠ²Π° ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС ΠΏΠΎΠ»Π΅Π·Π½ΠΎ, ΠΊΠΎΠ³Π°Ρ‚ΠΎ Ρ€Π°Π±ΠΎΡ‚ΠΈΡ‚Π΅ Π² срСда, Π·Π° която Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΡΡŠΠ·Π΄Π°Π²Π°Ρ‚Π΅ зависимости, ΠΈΠ»ΠΈ Π΄Π° Π·Π°ΠΏΠ°Π·Π²Π°Ρ‚Π΅ всСки Π±ΠΈΡ‚, ΠΈΠ»ΠΈ Π΄Π° ΠΏΠΈΡˆΠ΅Ρ‚Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° ΠΊΠ°Ρ‚ΠΎ ply, ΠΊΠΎΠΉΡ‚ΠΎ Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π° BPF Π΄Π²ΠΎΠΈΡ‡Π΅Π½ ΠΊΠΎΠ΄ Π² Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅.

Π—Π° Π΄Π° улСсним слСдванСто Π½Π° Π»ΠΎΠ³ΠΈΠΊΠ°Ρ‚Π°, Ρ‰Π΅ ΠΏΡ€Π΅Π½Π°ΠΏΠΈΡˆΠ΅ΠΌ нашия ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° Ρ‚Π΅Π·ΠΈ Ρ†Π΅Π»ΠΈ xdp-simple. ΠŸΡŠΠ»Π½ΠΈΡΡ‚ ΠΈ Π»Π΅ΠΊΠΎ Ρ€Π°Π·ΡˆΠΈΡ€Π΅Π½ ΠΊΠΎΠ΄ Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π°, обсъТдана Π² Ρ‚ΠΎΠ·ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС Π½Π°ΠΌΠ΅Ρ€Π΅Π½Π° Ρ‚ΡƒΠΊ ΡΡŠΡ‰Π½ΠΎΡΡ‚.

Π›ΠΎΠ³ΠΈΠΊΠ°Ρ‚Π° Π½Π° Π½Π°ΡˆΠ΅Ρ‚ΠΎ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π΅ слСдната:

  • ΡΡŠΠ·Π΄Π°ΠΉΡ‚Π΅ Ρ‚ΠΈΠΏΠΎΠ²Π° ΠΊΠ°Ρ€Ρ‚Π° BPF_MAP_TYPE_ARRAY ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ ΠΊΠΎΠΌΠ°Π½Π΄Π°Ρ‚Π° BPF_MAP_CREATE,
  • ΡΡŠΠ·Π΄Π°ΠΉΡ‚Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°, която ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Ρ‚Π°Π·ΠΈ ΠΊΠ°Ρ€Ρ‚Π°,
  • ΡΠ²ΡŠΡ€ΠΆΠ΅Ρ‚Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° към интСрфСйса lo,

ΠΊΠΎΠ΅Ρ‚ΠΎ сС ΠΏΡ€Π΅Π²Π΅ΠΆΠ΄Π° Π½Π° Ρ‡ΠΎΠ²Π΅ΡˆΠΊΠΈ ΠΊΠ°Ρ‚ΠΎ

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

Π’ΡƒΠΊ map_create създава ΠΊΠ°Ρ€Ρ‚Π° ΠΏΠΎ ΡΡŠΡ‰ΠΈΡ Π½Π°Ρ‡ΠΈΠ½, ΠΊΠ°ΠΊΡ‚ΠΎ Π½Π°ΠΏΡ€Π°Π²ΠΈΡ…ΠΌΠ΅ Π² ΠΏΡŠΡ€Π²ΠΈΡ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° систСмното ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅ bpf - β€žΡΠ΄Ρ€ΠΎΡ‚ΠΎ, моля, Π½Π°ΠΏΡ€Π°Π²Π΅Ρ‚Π΅ ΠΌΠΈ Π½ΠΎΠ²Π° ΠΊΠ°Ρ€Ρ‚Π° ΠΏΠΎΠ΄ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π° Π½Π° масив ΠΎΡ‚ 8 Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚Π° ΠΊΠ°Ρ‚ΠΎ __u64 ΠΈ ΠΌΠΈ Π²ΡŠΡ€Π½Π΅Ρ‚Π΅ файловия дСскриптор":

static int map_create()
{
    union bpf_attr attr;

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

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° ΡΡŠΡ‰ΠΎ Π΅ лСсна Π·Π° Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅:

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

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

Π‘Π»ΠΎΠΆΠ½Π°Ρ‚Π° част prog_load Π΅ дСфиницията Π½Π° Π½Π°ΡˆΠ°Ρ‚Π° BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° ΠΊΠ°Ρ‚ΠΎ масив ΠΎΡ‚ структури struct bpf_insn insns[]. Но Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°, която ΠΈΠΌΠ°ΠΌΠ΅ Π² C, ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΈΠ·ΠΌΠ°ΠΌΠΈΠΌ ΠΌΠ°Π»ΠΊΠΎ:

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

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

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

ΠžΠ±Ρ‰ΠΎ трябва Π΄Π° напишСм 14 инструкции ΠΏΠΎΠ΄ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π° Π½Π° структури ΠΊΠ°Ρ‚ΠΎ struct bpf_insn (ΡΡŠΠ²Π΅Ρ‚: Π²Π·Π΅ΠΌΠ΅Ρ‚Π΅ дъмпа ΠΎΡ‚Π³ΠΎΡ€Π΅, ΠΏΡ€ΠΎΡ‡Π΅Ρ‚Π΅Ρ‚Π΅ ΠΎΡ‚Π½ΠΎΠ²ΠΎ сСкцията с инструкции, ΠΎΡ‚Π²ΠΎΡ€Π΅Ρ‚Π΅ linux/bpf.h ΠΈ linux/bpf_common.h ΠΈ сС ΠΎΠΏΠΈΡ‚Π°ΠΉΡ‚Π΅ Π΄Π° ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚Π΅ struct bpf_insn insns[] сам):

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Π£ΠΏΡ€Π°ΠΆΠ½Π΅Π½ΠΈΠ΅ Π·Π° Ρ‚Π΅Π·ΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ Π½Π΅ са написали Ρ‚ΠΎΠ²Π° сами - Π½Π°ΠΌΠ΅Ρ€Π΅Ρ‚Π΅ map_fd.

Π’ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° Π½ΠΈ остава ΠΎΡ‰Π΅ Π΅Π΄Π½Π° Π½Π΅Ρ€Π°Π·ΠΊΡ€ΠΈΡ‚Π° част - xdp_attach. Π—Π° съТалСниС, ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ ΠΊΠ°Ρ‚ΠΎ XDP Π½Π΅ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ ΡΠ²ΡŠΡ€Π·Π°Π½ΠΈ Ρ‡Ρ€Π΅Π· систСмно ΠΏΠΎΠ²ΠΈΠΊΠ²Π°Π½Π΅ bpf. Π₯ΠΎΡ€Π°Ρ‚Π°, създали BPF ΠΈ XDP, бяха ΠΎΡ‚ ΠΎΠ½Π»Π°ΠΉΠ½ общността Π½Π° Linux, ΠΊΠΎΠ΅Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π²Π°, Ρ‡Π΅ са ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π»ΠΈ Π½Π°ΠΉ-познатия Π·Π° тях (Π½ΠΎ Π½Π΅ ΠΈ Π·Π° Π½ΠΎΡ€ΠΌΠ°Π»Π½ΠΎ Ρ…ΠΎΡ€Π°) интСрфСйс Π·Π° взаимодСйствиС с ядрото: netlink Π³Π½Π΅Π·Π΄Π°, Π’ΠΈΠΆΡ‚Π΅ ΡΡŠΡ‰ΠΎ RFC3549. Най-простият Π½Π°Ρ‡ΠΈΠ½ Π·Π° изпълнСниС xdp_attach ΠΊΠΎΠΏΠΈΡ€Π° ΠΊΠΎΠ΄ ΠΎΡ‚ libbpf, Π° ΠΈΠΌΠ΅Π½Π½ΠΎ ΠΎΡ‚ Ρ„Π°ΠΉΠ»Π° netlink.c, ΠΊΠΎΠ΅Ρ‚ΠΎ Π½Π°ΠΏΡ€Π°Π²ΠΈΡ…ΠΌΠ΅, ΠΊΠ°Ρ‚ΠΎ Π³ΠΎ ΡΡŠΠΊΡ€Π°Ρ‚ΠΈΡ…ΠΌΠ΅ ΠΌΠ°Π»ΠΊΠΎ:

Π”ΠΎΠ±Ρ€Π΅ дошли Π² свСта Π½Π° 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;
}

Π§Π΅Ρ‚Π΅ΠΌ ΠΎΡ‚ Ρ‚ΠΎΠ·ΠΈ сокСт:

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

И накрая, Π΅Ρ‚ΠΎ Π½Π°ΡˆΠ°Ρ‚Π° функция, която отваря сокСт ΠΈ ΠΈΠ·ΠΏΡ€Π°Ρ‰Π° спСциално ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅ Π΄ΠΎ Π½Π΅Π³ΠΎ, ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Ρ‰ΠΎ Ρ„Π°ΠΉΠ»ΠΎΠ² дСскриптор:

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

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

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

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

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

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

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

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

cleanup:
    close(sock);
    return ret;
}

И Ρ‚Π°ΠΊΠ°, всичко Π΅ Π³ΠΎΡ‚ΠΎΠ²ΠΎ Π·Π° тСстванС:

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

Π”Π° Π²ΠΈΠ΄ΠΈΠΌ Π΄Π°Π»ΠΈ Π½Π°ΡˆΠ°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° сС Π΅ ΡΠ²ΡŠΡ€Π·Π°Π»Π° с 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

НСка ΠΈΠ·ΠΏΡ€Π°Ρ‚ΠΈΠΌ ping ΠΈ ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅ΠΌ ΠΊΠ°Ρ€Ρ‚Π°Ρ‚Π°:

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

Π£Ρ€Π°, всичко Ρ€Π°Π±ΠΎΡ‚ΠΈ. ΠžΠ±ΡŠΡ€Π½Π΅Ρ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, ΠΌΠ΅ΠΆΠ΄Ρƒ Π΄Ρ€ΡƒΠ³ΠΎΡ‚ΠΎ, Ρ‡Π΅ Π½Π°ΡˆΠ°Ρ‚Π° ΠΊΠ°Ρ€Ρ‚Π° ΠΎΡ‚Π½ΠΎΠ²ΠΎ сС ΠΏΠΎΠΊΠ°Π·Π²Π° ΠΏΠΎΠ΄ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π° Π½Π° Π±Π°ΠΉΡ‚ΠΎΠ²Π΅. Π’ΠΎΠ²Π° сС дълТи Π½Π° Ρ„Π°ΠΊΡ‚Π°, Ρ‡Π΅ Π·Π° Ρ€Π°Π·Π»ΠΈΠΊΠ° ΠΎΡ‚ libbpf Π½Π΅ Π·Π°Ρ€Π΅Π΄ΠΈΡ…ΠΌΠ΅ информация Π·Π° Ρ‚ΠΈΠΏΠ° (BTF). Но Ρ‰Π΅ Π³ΠΎΠ²ΠΎΡ€ΠΈΠΌ ΠΏΠΎΠ²Π΅Ρ‡Π΅ Π·Π° Ρ‚ΠΎΠ²Π° слСдващия ΠΏΡŠΡ‚.

Π˜Π½ΡΡ‚Ρ€ΡƒΠΌΠ΅Π½Ρ‚ΠΈ Π·Π° Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ°

Π’ Ρ‚ΠΎΠ·ΠΈ Ρ€Π°Π·Π΄Π΅Π» Ρ‰Π΅ Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ минималния Π½Π°Π±ΠΎΡ€ ΠΎΡ‚ инструмСнти Π·Π° Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΡ†ΠΈ Π½Π° BPF.

Най-ΠΎΠ±Ρ‰ΠΎ ΠΊΠ°Π·Π°Π½ΠΎ, Π½Π΅ сС Π½ΡƒΠΆΠ΄Π°Π΅Ρ‚Π΅ ΠΎΡ‚ Π½ΠΈΡ‰ΠΎ спСциално, Π·Π° Π΄Π° Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΈΡ‚Π΅ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ - BPF Ρ€Π°Π±ΠΎΡ‚ΠΈ Π½Π° всяко ΠΏΡ€ΠΈΠ»ΠΈΡ‡Π½ΠΎ дистрибутивно ядро ​​и ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅ сС ΠΈΠ·Π³Ρ€Π°ΠΆΠ΄Π°Ρ‚ с clang, ΠΊΠΎΠΈΡ‚ΠΎ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ доставСни ΠΎΡ‚ ΠΎΠΏΠ°ΠΊΠΎΠ²ΠΊΠ°Ρ‚Π°. Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‚ΠΎΠ²Π°, ΠΏΠΎΡ€Π°Π΄ΠΈ Ρ„Π°ΠΊΡ‚Π°, Ρ‡Π΅ BPF Π΅ Π² процСс Π½Π° Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ°, ядрото ΠΈ инструмСнтитС Π½Π΅ΠΏΡ€Π΅ΠΊΡŠΡΠ½Π°Ρ‚ΠΎ сС промСнят, Π°ΠΊΠΎ Π½Π΅ искатС Π΄Π° ΠΏΠΈΡˆΠ΅Ρ‚Π΅ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ старомодни ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΈ ΠΎΡ‚ 2019 Π³., Ρ‚ΠΎΠ³Π°Π²Π° Ρ‰Π΅ трябва Π΄Π° ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€Π°Ρ‚Π΅

  • llvm/clang
  • pahole
  • Π½Π΅ΠΉΠ½ΠΎΡ‚ΠΎ ядро
  • bpftool

(Π—Π° справка, Ρ‚ΠΎΠ·ΠΈ Ρ€Π°Π·Π΄Π΅Π» ΠΈ всички ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΈ Π² статията бяха изпълнСни Π½Π° Debian 10.)

llvm/звън

BPF Π΅ приятСлски настроСн към LLVM ΠΈ Π²ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‡Π΅ напослСдък ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅ Π·Π° BPF ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€Π°Π½ΠΈ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° gcc, цялата Ρ‚Π΅ΠΊΡƒΡ‰Π° Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° сС ΠΈΠ·Π²ΡŠΡ€ΡˆΠ²Π° Π·Π° LLVM. Π—Π°Ρ‚ΠΎΠ²Π°, Π½Π° ΠΏΡŠΡ€Π²ΠΎ място, Ρ‰Π΅ ΠΈΠ·Π³Ρ€Π°Π΄ΠΈΠΌ Ρ‚Π΅ΠΊΡƒΡ‰Π°Ρ‚Π° вСрсия clang ΠΎΡ‚ 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
... ΠΌΠ½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ спустя
$

Π‘Π΅Π³Π° ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΠΌ Π΄Π°Π»ΠΈ всичко Π΅ ΡΡŠΠ±Ρ€Π°Π½ΠΎ ΠΏΡ€Π°Π²ΠΈΠ»Π½ΠΎ:

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

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

(Π˜Π½ΡΡ‚Ρ€ΡƒΠΊΡ†ΠΈΠΈ Π·Π° сглобяванС clang Π²Π·Π΅Ρ‚ΠΎ ΠΎΡ‚ ΠΌΠ΅Π½ ΠΎΡ‚ bpf_devel_QA.)

Няма Π΄Π° инсталирамС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅, ΠΊΠΎΠΈΡ‚ΠΎ Ρ‚ΠΎΠΊΡƒ-Ρ‰ΠΎ ΡΡŠΠ·Π΄Π°Π΄ΠΎΡ…ΠΌΠ΅, Π° вмСсто Ρ‚ΠΎΠ²Π° просто Ρ‰Π΅ Π³ΠΈ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ PATH, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€:

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

(Π’ΠΎΠ²Π° ΠΌΠΎΠΆΠ΅ Π΄Π° сС Π΄ΠΎΠ±Π°Π²ΠΈ към .bashrc ΠΈΠ»ΠΈ Π² ΠΎΡ‚Π΄Π΅Π»Π΅Π½ Ρ„Π°ΠΉΠ». Π›ΠΈΡ‡Π½ΠΎ Π°Π· добавям Ρ‚Π°ΠΊΠΈΠ²Π° Π½Π΅Ρ‰Π° към ~/bin/activate-llvm.sh ΠΈ ΠΊΠΎΠ³Π°Ρ‚ΠΎ трябва Π³ΠΎ правя . activate-llvm.sh.)

ΠŸΠ°Ρ…ΠΎΠ»Π΅ ΠΈ Π‘Π’Π€

ΠŸΠΎΠ»Π΅Π·Π½ΠΎΡΡ‚ pahole ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½ΠΈ ΠΏΡ€ΠΈ ΠΈΠ·Π³Ρ€Π°ΠΆΠ΄Π°Π½Π΅ Π½Π° ядрото Π·Π° създаванС Π½Π° информация Π·Π° отстраняванС Π½Π° Π³Ρ€Π΅ΡˆΠΊΠΈ във Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ BTF. Π’ Ρ‚Π°Π·ΠΈ статия няма Π΄Π° Π½Π°Π²Π»ΠΈΠ·Π°ΠΌΠ΅ Π² подробности относно BTF тСхнологията, освСн Ρ„Π°ΠΊΡ‚Π°, Ρ‡Π΅ Π΅ ΡƒΠ΄ΠΎΠ±Π½Π° ΠΈ искамС Π΄Π° я ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅. Π’Π°ΠΊΠ° Ρ‡Π΅, Π°ΠΊΠΎ Π²ΡŠΠ·Π½Π°ΠΌΠ΅Ρ€ΡΠ²Π°Ρ‚Π΅ Π΄Π° ΠΈΠ·Π³Ρ€Π°Π΄ΠΈΡ‚Π΅ Π²Π°ΡˆΠ΅Ρ‚ΠΎ ядро, ΠΈΠ·Π³Ρ€Π°Π΄Π΅Ρ‚Π΅ ΠΏΡŠΡ€Π²ΠΎ pahole (Π±Π΅Π· pahole няма Π΄Π° ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΈΠ·Π³Ρ€Π°Π΄ΠΈΡ‚Π΅ ядрото с опцията 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

Π―Π΄Ρ€Π° Π·Π° СкспСримСнтиранС с BPF

ΠšΠΎΠ³Π°Ρ‚ΠΎ ΠΏΡ€ΠΎΡƒΡ‡Π²Π°ΠΌ Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΠΈΡ‚Π΅ Π½Π° BPF, искам Π΄Π° сглобя собствСно ядро. Π’ΠΎΠ²Π°, Π½Π°ΠΉ-ΠΎΠ±Ρ‰ΠΎ ΠΊΠ°Π·Π°Π½ΠΎ, Π½Π΅ Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Ρ‰Π΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€Π°Ρ‚Π΅ ΠΈ Π·Π°Ρ€Π΅ΠΆΠ΄Π°Ρ‚Π΅ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ Π² ядрото Π½Π° дистрибуцията, Π½ΠΎ Π½Π°Π»ΠΈΡ‡ΠΈΠ΅Ρ‚ΠΎ Π½Π° собствСно ядро ​​ви позволява Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ Π½Π°ΠΉ-Π½ΠΎΠ²ΠΈΡ‚Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π½Π° BPF, ΠΊΠΎΠΈΡ‚ΠΎ Ρ‰Π΅ сС появят във Π²Π°ΡˆΠ°Ρ‚Π° дистрибуция Π² Π½Π°ΠΉ-добрия случай слСд мСсСци , ΠΈΠ»ΠΈ, ΠΊΠ°ΠΊΡ‚ΠΎ Π² случая с някои инструмСнти Π·Π° отстраняванС Π½Π° Π³Ρ€Π΅ΡˆΠΊΠΈ, ΠΈΠ·ΠΎΠ±Ρ‰ΠΎ няма Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈΡ€Π°Π½ΠΈ Π² ΠΎΠ±ΠΎΠ·Ρ€ΠΈΠΌΠΎ Π±ΡŠΠ΄Π΅Ρ‰Π΅. Π‘ΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ°, собствСното ΠΌΡƒ ядро ​​кара Π΄Π° сС чувства Π²Π°ΠΆΠ½ΠΎ Π΄Π° сС СкспСримСнтира с ΠΊΠΎΠ΄Π°.

Π—Π° Π΄Π° ΠΈΠ·Π³Ρ€Π°Π΄ΠΈΡ‚Π΅ ядро, Π²ΠΈ трябва, ΠΏΡŠΡ€Π²ΠΎ, самото ядро ​​и Π²Ρ‚ΠΎΡ€ΠΎ, ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΎΠ½Π΅Π½ Ρ„Π°ΠΉΠ» Π½Π° ядрото. Π—Π° Π΄Π° СкспСримСнтирамС с BPF, ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ обичайния ванилия ядро ΠΈΠ»ΠΈ Π΅Π΄Π½ΠΎ ΠΎΡ‚ ядрата Π·Π° Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ°. Π˜ΡΡ‚ΠΎΡ€ΠΈΡ‡Π΅ΡΠΊΠΈ ΠΏΠΎΠ³Π»Π΅Π΄Π½Π°Ρ‚ΠΎ, Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ°Ρ‚Π° Π½Π° BPF сС ΠΈΠ·Π²ΡŠΡ€ΡˆΠ²Π° Π² Ρ€Π°ΠΌΠΊΠΈΡ‚Π΅ Π½Π° ΠΌΡ€Π΅ΠΆΠΎΠ²Π°Ρ‚Π° общност Π½Π° Linux ΠΈ слСдоватСлно всички ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈ Ρ€Π°Π½ΠΎ ΠΈΠ»ΠΈ късно ΠΏΡ€Π΅ΠΌΠΈΠ½Π°Π²Π°Ρ‚ ΠΏΡ€Π΅Π· Π”Π΅ΠΉΠ²ΠΈΠ΄ ΠœΠΈΠ»ΡŠΡ€, ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ°Ρ‰ΠΈΡ ΠΌΡ€Π΅ΠΆΠ°Ρ‚Π° Π½Π° Linux. Π’ зависимост ΠΎΡ‚ тяхното СстСство - Ρ€Π΅Π΄Π°ΠΊΡ†ΠΈΠΈ ΠΈΠ»ΠΈ Π½ΠΎΠ²ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ - ΠΌΡ€Π΅ΠΆΠΎΠ²ΠΈΡ‚Π΅ ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈ ΠΏΠΎΠΏΠ°Π΄Π°Ρ‚ Π² Π΅Π΄Π½ΠΎ ΠΎΡ‚ Π΄Π²Π΅Ρ‚Π΅ ядра - net ΠΈΠ»ΠΈ net-next. ΠŸΡ€ΠΎΠΌΠ΅Π½ΠΈΡ‚Π΅ Π·Π° BPF сС разпрСдСлят ΠΏΠΎ ΡΡŠΡ‰ΠΈΡ Π½Π°Ρ‡ΠΈΠ½ ΠΌΠ΅ΠΆΠ΄Ρƒ bpf ΠΈ bpf-next, ΠΊΠΎΠΈΡ‚ΠΎ слСд Ρ‚ΠΎΠ²Π° сС обСдиняват ΡΡŠΠΎΡ‚Π²Π΅Ρ‚Π½ΠΎ Π² net ΠΈ net-next. Π—Π° ΠΏΠΎΠ²Π΅Ρ‡Π΅ подробности Π²ΠΆ bpf_devel_QA ΠΈ netdev-Π§Π—Π’. Π’Π°ΠΊΠ° Ρ‡Π΅ ΠΈΠ·Π±Π΅Ρ€Π΅Ρ‚Π΅ ядро β€‹β€‹Π²ΡŠΠ· основа Π½Π° вашия вкус ΠΈ Π½ΡƒΠΆΠ΄ΠΈΡ‚Π΅ ΠΎΡ‚ стабилност Π½Π° систСмата, Π²ΡŠΡ€Ρ…Ρƒ която тСстватС (*-next ядрата са Π½Π°ΠΉ-нСстабилнитС ΠΎΡ‚ ΠΈΠ·Π±Ρ€ΠΎΠ΅Π½ΠΈΡ‚Π΅).

Извън ΠΎΠ±Ρ…Π²Π°Ρ‚Π° Π½Π° Ρ‚Π°Π·ΠΈ статия Π΅ Π΄Π° Π³ΠΎΠ²ΠΎΡ€ΠΈΠΌ Π·Π° Ρ‚ΠΎΠ²Π° ΠΊΠ°ΠΊ Π΄Π° управляватС ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΎΠ½Π½ΠΈΡ‚Π΅ Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ Π½Π° ядрото - ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π° сС, Ρ‡Π΅ ΠΈΠ»ΠΈ Π²Π΅Ρ‡Π΅ Π·Π½Π°Π΅Ρ‚Π΅ ΠΊΠ°ΠΊ Π΄Π° Π½Π°ΠΏΡ€Π°Π²ΠΈΡ‚Π΅ Ρ‚ΠΎΠ²Π°, ΠΈΠ»ΠΈ Π³ΠΎΡ‚ΠΎΠ² Π΄Π° ΡƒΡ‡ΠΈ сам ΠΏΠΎ сСбС си. Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‚ΠΎΠ²Π°, слСдващитС инструкции трябва Π΄Π° са ΠΏΠΎΠ²Π΅Ρ‡Π΅ ΠΈΠ»ΠΈ ΠΏΠΎ-ΠΌΠ°Π»ΠΊΠΎ Π΄ΠΎΡΡ‚Π°Ρ‚ΡŠΡ‡Π½ΠΈ, Π·Π° Π΄Π° Π²ΠΈ осигурят Ρ€Π°Π±ΠΎΡ‚Π΅Ρ‰Π° систСма с Π°ΠΊΡ‚ΠΈΠ²ΠΈΡ€Π°Π½ BPF.

Π˜Π·Ρ‚Π΅Π³Π»Π΅Ρ‚Π΅ Π΅Π΄Π½ΠΎ ΠΎΡ‚ Π³ΠΎΡ€Π½ΠΈΡ‚Π΅ ядра:

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

Π‘ΡŠΠ·Π΄Π°ΠΉΡ‚Π΅ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»Π½Π° Ρ€Π°Π±ΠΎΡ‚Π΅Ρ‰Π° конфигурация Π½Π° ядрото:

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

АктивирайтС BPF ΠΎΠΏΡ†ΠΈΠΈΡ‚Π΅ във Ρ„Π°ΠΉΠ»Π° .config ΠΏΠΎ ваш ΠΈΠ·Π±ΠΎΡ€ (Π½Π°ΠΉ-вСроятно CONFIG_BPF Π²Π΅Ρ‡Π΅ Ρ‰Π΅ бъдС Π°ΠΊΡ‚ΠΈΠ²ΠΈΡ€Π°Π½, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ systemd Π³ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°). Π•Ρ‚ΠΎ списък с ΠΎΠΏΡ†ΠΈΠΈ ΠΎΡ‚ ядрото, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½ΠΈ Π·Π° Ρ‚Π°Π·ΠΈ статия:

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

Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° ΠΌΠΎΠΆΠ΅ΠΌ лСсно Π΄Π° сглобим ΠΈ инсталирамС ΠΌΠΎΠ΄ΡƒΠ»ΠΈΡ‚Π΅ ΠΈ ядрото (ΠΌΠ΅ΠΆΠ΄Ρƒ Π΄Ρ€ΡƒΠ³ΠΎΡ‚ΠΎ, ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° сглобитС ядрото, ΠΊΠ°Ρ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ новосглобСния clangдобавяйки CC=clang):

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

ΠΈ рСстартирайтС с Π½ΠΎΠ²ΠΎΡ‚ΠΎ ядро ​​(ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌ Π·Π° Ρ‚ΠΎΠ²Π° kexec ΠΎΡ‚ ΠΏΠ°ΠΊΠ΅Ρ‚ 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

Най-чСсто ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π°Ρ‚Π° ΠΏΠΎΠΌΠΎΡ‰Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Π² статията Ρ‰Π΅ бъдС ΠΏΠΎΠΌΠΎΡ‰Π½Π°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° bpftool, доставСн ΠΊΠ°Ρ‚ΠΎ част ΠΎΡ‚ ядрото Π½Π° Linux. Π’ΠΎΠΉ Π΅ написан ΠΈ ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ°Π½ ΠΎΡ‚ BPF Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΡ†ΠΈ Π·Π° BPF Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΡ†ΠΈ ΠΈ ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π·Π° ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½Π° всички Π²ΠΈΠ΄ΠΎΠ²Π΅ BPF ΠΎΠ±Π΅ΠΊΡ‚ΠΈ - Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅ Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ, създаванС ΠΈ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€Π°Π½Π΅ Π½Π° ΠΊΠ°Ρ€Ρ‚ΠΈ, изслСдванС Π½Π° ΠΆΠΈΠ²ΠΎΡ‚Π° Π½Π° BPF СкосистСмата ΠΈ Ρ‚.Π½. МоТС Π΄Π° сС Π½Π°ΠΌΠ΅Ρ€ΠΈ докумСнтация ΠΏΠΎΠ΄ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π° Π½Π° ΠΈΠ·Ρ…ΠΎΠ΄Π½ΠΈ ΠΊΠΎΠ΄ΠΎΠ²Π΅ Π·Π° страници с Ρ€ΡŠΠΊΠΎΠ²ΠΎΠ΄ΡΡ‚Π²ΠΎ Π² ΡΡŠΡ€Ρ†Π΅Π²ΠΈΠ½Π°Ρ‚Π° ΠΈΠ»ΠΈ Π²Π΅Ρ‡Π΅ ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€Π°Π½, ΠΌΡ€Π΅ΠΆΠ°.

Към ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° Π½Π° писанС Π½Π° Ρ‚Π°Π·ΠΈ статия bpftool ΠΈΠ΄Π²Π° Π³ΠΎΡ‚ΠΎΠ² само Π·Π° RHEL, Fedora ΠΈ Ubuntu (Π²ΠΈΠΆΡ‚Π΅ Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Ρ‚Π°Π·ΠΈ Ρ‚Π΅ΠΌΠ°, ΠΊΠΎΠΉΡ‚ΠΎ Ρ€Π°Π·ΠΊΠ°Π·Π²Π° Π½Π΅Π΄ΠΎΠ²ΡŠΡ€ΡˆΠ΅Π½Π°Ρ‚Π° история Π½Π° ΠΎΠΏΠ°ΠΊΠΎΠ²ΠΊΠ°Ρ‚Π° bpftool Π² Π”Π΅Π±ΠΈΠ°Π½). Но Π°ΠΊΠΎ Π²Π΅Ρ‡Π΅ стС ΠΈΠ·Π³Ρ€Π°Π΄ΠΈΠ»ΠΈ Π²Π°ΡˆΠ΅Ρ‚ΠΎ ядро, Ρ‚ΠΎΠ³Π°Π²Π° ΠΈΠ·Π³Ρ€Π°Π΄Π΅Ρ‚Π΅ bpftool лСсно ΠΊΠ°Ρ‚ΠΎ ΠΏΠ°ΠΉ:

$ 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  ]

$

(Ρ‚ΡƒΠΊ ${linux} - Ρ‚ΠΎΠ²Π° Π΅ Π²Π°ΡˆΠ°Ρ‚Π° дирСктория Π½Π° ядрото.) Π‘Π»Π΅Π΄ изпълнСниС Π½Π° Ρ‚Π΅Π·ΠΈ ΠΊΠΎΠΌΠ°Π½Π΄ΠΈ bpftool Ρ‰Π΅ Π±ΡŠΠ΄Π°Ρ‚ ΡΡŠΠ±Ρ€Π°Π½ΠΈ Π² дирСктория ${linux}/tools/bpf/bpftool ΠΈ ΠΌΠΎΠΆΠ΅ Π΄Π° сС Π΄ΠΎΠ±Π°Π²ΠΈ към ΠΏΡŠΡ‚Ρ (ΠΏΡ€Π΅Π΄ΠΈ всичко към потрСбитСля root) ΠΈΠ»ΠΈ просто ΠΊΠΎΠΏΠΈΡ€Π°ΠΉΡ‚Π΅ Π² /usr/local/sbin.

ΡΡŠΠ±ΠΈΡ€Π°ΠΌ bpftool Π½Π°ΠΉ-Π΄ΠΎΠ±Ρ€Π΅ Π΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ послСдното clang, сглобСн ΠΏΠΎ описания ΠΏΠΎ-Π³ΠΎΡ€Π΅ Π½Π°Ρ‡ΠΈΠ½ ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€Π΅Ρ‚Π΅ Π΄Π°Π»ΠΈ Π΅ сглобСн ΠΏΡ€Π°Π²ΠΈΠ»Π½ΠΎ - ΠΊΠ°Ρ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΊΠΎΠΌΠ°Π½Π΄Π°Ρ‚Π°

$ 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
...

ΠΊΠΎΠ΅Ρ‚ΠΎ Ρ‰Π΅ ΠΏΠΎΠΊΠ°ΠΆΠ΅ ΠΊΠΎΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π½Π° BPF са Π°ΠΊΡ‚ΠΈΠ²ΠΈΡ€Π°Π½ΠΈ във Π²Π°ΡˆΠ΅Ρ‚ΠΎ ядро.

ΠœΠ΅ΠΆΠ΄Ρƒ Π΄Ρ€ΡƒΠ³ΠΎΡ‚ΠΎ, ΠΏΡ€Π΅Π΄ΠΈΡˆΠ½Π°Ρ‚Π° ΠΊΠΎΠΌΠ°Π½Π΄Π° ΠΌΠΎΠΆΠ΅ Π΄Π° сС изпълни ΠΊΠ°Ρ‚ΠΎ

# bpftool f p k

Π’ΠΎΠ²Π° сС ΠΏΡ€Π°Π²ΠΈ ΠΏΠΎ аналогия с ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈΡ‚Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ ΠΎΡ‚ ΠΏΠ°ΠΊΠ΅Ρ‚Π° iproute2, ΠΊΡŠΠ΄Π΅Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅ΠΌ Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π΄Π° ΠΊΠ°ΠΆΠ΅ΠΌ ip a s eth0 вмСсто ip addr show dev eth0.

Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

BPF Π²ΠΈ позволява Π΄Π° ΠΎΠ±ΡƒΠ΅Ρ‚Π΅ Π±ΡŠΠ»Ρ…Π°, Π·Π° Π΄Π° ΠΈΠ·ΠΌΠ΅Ρ€ΠΈΡ‚Π΅ Π΅Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π½ΠΎ ΠΈ Π΄Π° ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈΡ‚Π΅ Π² Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅ функционалността Π½Π° ядрото. БистСмата сС ΠΎΠΊΠ°Π·Π° ΠΌΠ½ΠΎΠ³ΠΎ ΡƒΡΠΏΠ΅ΡˆΠ½Π°, Π² Π½Π°ΠΉ-Π΄ΠΎΠ±Ρ€ΠΈΡ‚Π΅ Ρ‚Ρ€Π°Π΄ΠΈΡ†ΠΈΠΈ Π½Π° UNIX: прост ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΡŠΠΌ, ΠΊΠΎΠΉΡ‚ΠΎ Π²ΠΈ позволява Π΄Π° (ΠΏΡ€Π΅)ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ€Π°Ρ‚Π΅ ядрото, ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈ Π½Π° ΠΎΠ³Ρ€ΠΎΠΌΠ΅Π½ Π±Ρ€ΠΎΠΉ Ρ…ΠΎΡ€Π° ΠΈ ΠΎΡ€Π³Π°Π½ΠΈΠ·Π°Ρ†ΠΈΠΈ Π΄Π° СкспСримСнтират. И Π²ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‡Π΅ СкспСримСнтитС, ΠΊΠ°ΠΊΡ‚ΠΎ ΠΈ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° самата BPF инфраструктура, Π΄Π°Π»Π΅Ρ‡ Π½Π΅ са Π·Π°Π²ΡŠΡ€ΡˆΠ΅Π½ΠΈ, систСмата Π²Π΅Ρ‡Π΅ ΠΈΠΌΠ° стабилСн ABI, ΠΊΠΎΠΉΡ‚ΠΎ Π²ΠΈ позволява Π΄Π° ΠΈΠ·Π³Ρ€Π°Π΄ΠΈΡ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π½Π° ΠΈ Π½Π°ΠΉ-Π²Π°ΠΆΠ½ΠΎΡ‚ΠΎ Π΅Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π½Π° бизнСс Π»ΠΎΠ³ΠΈΠΊΠ°.

Π‘ΠΈΡ… искал Π΄Π° ΠΎΡ‚Π±Π΅Π»Π΅ΠΆΠ°, Ρ‡Π΅ спорСд ΠΌΠ΅Π½ тСхнологията стана Ρ‚ΠΎΠ»ΠΊΠΎΠ²Π° популярна, Π·Π°Ρ‰ΠΎΡ‚ΠΎ ΠΎΡ‚ Π΅Π΄Π½Π° страна ΠΌΠΎΠΆΠ΅ играя (Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π°Ρ‚Π° Π½Π° Π΅Π΄Π½Π° машина ΠΌΠΎΠΆΠ΅ Π΄Π° сС Ρ€Π°Π·Π±Π΅Ρ€Π΅ Π³ΠΎΡ€Π΅-Π΄ΠΎΠ»Ρƒ Π·Π° Π΅Π΄Π½Π° Π²Π΅Ρ‡Π΅Ρ€), Π° ΠΎΡ‚ Π΄Ρ€ΡƒΠ³Π° страна, Π·Π° Ρ€Π΅ΡˆΠ°Π²Π°Π½Π΅ Π½Π° ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ Π½Π΅ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ Ρ€Π΅ΡˆΠ΅Π½ΠΈ (красиво) ΠΏΡ€Π΅Π΄ΠΈ Π½Π΅ΠΉΠ½Π°Ρ‚Π° поява. Π’Π΅Π·ΠΈ Π΄Π²Π° ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° Π·Π°Π΅Π΄Π½ΠΎ ΠΊΠ°Ρ€Π°Ρ‚ Ρ…ΠΎΡ€Π°Ρ‚Π° Π΄Π° СкспСримСнтират ΠΈ мСчтаят, ΠΊΠΎΠ΅Ρ‚ΠΎ Π²ΠΎΠ΄ΠΈ Π΄ΠΎ появата Π½Π° всС ΠΏΠΎ-ΠΈΠ½ΠΎΠ²Π°Ρ‚ΠΈΠ²Π½ΠΈ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ.

Π’Π°Π·ΠΈ статия, ΠΌΠ°ΠΊΠ°Ρ€ ΠΈ Π½Π΅ особСно ΠΊΡ€Π°Ρ‚ΠΊΠ°, Π΅ само въвСдСниС Π² свСта Π½Π° BPF ΠΈ Π½Π΅ описва β€žΡ€Π°Π·ΡˆΠΈΡ€Π΅Π½ΠΈβ€œ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΈ Π²Π°ΠΆΠ½ΠΈ части ΠΎΡ‚ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π°Ρ‚Π°. ΠŸΠ»Π°Π½ΡŠΡ‚ Π·Π°Π½Π°ΠΏΡ€Π΅Π΄ Π΅ Π½Π΅Ρ‰ΠΎ ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎ: слСдващата статия Ρ‰Π΅ бъдС ΠΏΡ€Π΅Π³Π»Π΅Π΄ Π½Π° Ρ‚ΠΈΠΏΠΎΠ²Π΅Ρ‚Π΅ BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ (ΠΈΠΌΠ° 5.8 Ρ‚ΠΈΠΏΠ° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ, ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ°Π½ΠΈ Π² ядрото 30), слСд ΠΊΠΎΠ΅Ρ‚ΠΎ Π½Π°ΠΉ-накрая Ρ‰Π΅ Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΊΠ°ΠΊ Π΄Π° пишСм истински BPF прилоТСния, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ Π·Π° прослСдяванС Π½Π° ядрото ΠΊΠ°Ρ‚ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Ρ‚ΠΎΠ³Π°Π²Π° Π΅ Π²Ρ€Π΅ΠΌΠ΅ Π·Π° ΠΏΠΎ-Π·Π°Π΄ΡŠΠ»Π±ΠΎΡ‡Π΅Π½ курс ΠΏΠΎ BPF Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π°, послСдван ΠΎΡ‚ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΈ Π·Π° BPF ΠΌΡ€Π΅ΠΆΠΈ ΠΈ прилоТСния Π·Π° сигурност.

ΠŸΡ€Π΅Π΄ΠΈΡˆΠ½ΠΈ статии ΠΎΡ‚ Ρ‚Π°Π·ΠΈ сСрия

  1. BPF Π·Π° Π½Π°ΠΉ-ΠΌΠ°Π»ΠΊΠΈΡ‚Π΅, част Π½ΡƒΠ»Π°: класичСски BPF

Π’Ρ€ΡŠΠ·ΠΊΠΈ

  1. Π‘ΠΏΡ€Π°Π²ΠΎΡ‡Π½ΠΎ Ρ€ΡŠΠΊΠΎΠ²ΠΎΠ΄ΡΡ‚Π²ΠΎ Π·Π° BPF ΠΈ XDP β€” докумСнтация Π·Π° BPF ΠΎΡ‚ cilium, ΠΈΠ»ΠΈ ΠΏΠΎ-Ρ‚ΠΎΡ‡Π½ΠΎ ΠΎΡ‚ Daniel Borkman, Π΅Π΄ΠΈΠ½ ΠΎΡ‚ ΡΡŠΠ·Π΄Π°Ρ‚Π΅Π»ΠΈΡ‚Π΅ ΠΈ ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ°Ρ‰ΠΈΡ‚Π΅ BPF. Π’ΠΎΠ²Π° Π΅ Π΅Π΄Π½ΠΎ ΠΎΡ‚ ΠΏΡŠΡ€Π²ΠΈΡ‚Π΅ сСриозни описания, ΠΊΠΎΠ΅Ρ‚ΠΎ сС ΠΎΡ‚Π»ΠΈΡ‡Π°Π²Π° ΠΎΡ‚ останалитС с Ρ‚ΠΎΠ²Π°, Ρ‡Π΅ Π”Π°Π½ΠΈΠ΅Π» Π·Π½Π°Π΅ Ρ‚ΠΎΡ‡Π½ΠΎ ΠΊΠ°ΠΊΠ²ΠΎ пишС ΠΈ Ρ‚Π°ΠΌ няма Π³Ρ€Π΅ΡˆΠΊΠΈ. По-спСциално, Ρ‚ΠΎΠ·ΠΈ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ описва ΠΊΠ°ΠΊ Π΄Π° Ρ€Π°Π±ΠΎΡ‚ΠΈΡ‚Π΅ с BPF ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ ΠΎΡ‚ Ρ‚ΠΈΠΏΠ° XDP ΠΈ TC с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° Π΄ΠΎΠ±Ρ€Π΅ ΠΏΠΎΠ·Π½Π°Ρ‚Π°Ρ‚Π° ΠΏΠΎΠΌΠΎΡ‰Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° ip ΠΎΡ‚ ΠΏΠ°ΠΊΠ΅Ρ‚ iproute2.

  2. Documentation/networking/filter.txt β€” ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»Π΅Π½ Ρ„Π°ΠΉΠ» с докумСнтация Π·Π° класичСски ΠΈ слСд Ρ‚ΠΎΠ²Π° Ρ€Π°Π·ΡˆΠΈΡ€Π΅Π½ BPF. Π”ΠΎΠ±Ρ€ΠΎ Ρ‡Π΅Ρ‚ΠΈΠ²ΠΎ, Π°ΠΊΠΎ искатС Π΄Π° сС Π·Π°Π΄ΡŠΠ»Π±ΠΎΡ‡ΠΈΡ‚Π΅ Π² асСмблСрния Π΅Π·ΠΈΠΊ ΠΈ тСхничСскитС Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π½ΠΈ Π΄Π΅Ρ‚Π°ΠΉΠ»ΠΈ.

  3. Π‘Π»ΠΎΠ³ Π·Π° BPF ΠΎΡ‚ facebook. Актуализира сС рядко, Π½ΠΎ умСстно, ΠΊΠ°ΠΊΡ‚ΠΎ ΠΏΠΈΡˆΠ°Ρ‚ Ρ‚Π°ΠΌ АлСксСй Π‘Ρ‚Π°Ρ€ΠΎΠ²ΠΎΠΉΡ‚ΠΎΠ² (Π°Π²Ρ‚ΠΎΡ€ Π½Π° eBPF) ΠΈ Андрий Накрийко - (ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ°Ρ‰) libbpf).

  4. Π’Π°ΠΉΠ½ΠΈΡ‚Π΅ Π½Π° bpftool. Π—Π°Π±Π°Π²Π½Π° нишка Π² Twitter ΠΎΡ‚ Quentin Monnet с ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΈ ΠΈ Ρ‚Π°ΠΉΠ½ΠΈ Π·Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° bpftool.

  5. ΠŸΠΎΡ‚ΠΎΠΏΠ΅Ρ‚Π΅ сС Π² BPF: списък с ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΈ Π·Π° Ρ‡Π΅Ρ‚Π΅Π½Π΅. ΠžΠ³Ρ€ΠΎΠΌΠ΅Π½ (ΠΈ всС ΠΎΡ‰Π΅ ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ°Π½) списък с Π²Ρ€ΡŠΠ·ΠΊΠΈ към докумСнтация Π½Π° BPF ΠΎΡ‚ ΠšΡƒΠ΅Π½Ρ‚ΠΈΠ½ МонС.

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ: www.habr.com

ДобавянС Π½Π° Π½ΠΎΠ² ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€