Π Π½Π°ΡΠ°Π»Π΅ Π±ΡΠ»Π° ΡΠ΅Ρ
Π½ΠΎΠ»ΠΎΠ³ΠΈΡ ΠΈ Π½Π°Π·ΡΠ²Π°Π»Π°ΡΡ ΠΎΠ½Π° BPF. ΠΡ ΠΏΠΎΡΠΌΠΎΡΡΠ΅Π»ΠΈ Π½Π° Π½Π΅Π΅ Π²
ΠΡΡΠ±ΠΎ Π³ΠΎΠ²ΠΎΡΡ, BPF ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ Π·Π°ΠΏΡΡΠΊΠ°ΡΡ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ»ΡΠ½ΡΠΉ ΠΊΠΎΠ΄, ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΠ΅ΠΌΡΠΉ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Π΅ΠΌ, Π² ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²Π΅ ΡΠ΄ΡΠ° Linux ΠΈ Π½ΠΎΠ²Π°Ρ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ° ΠΎΠΊΠ°Π·Π°Π»Π°ΡΡ Π½Π°ΡΡΠΎΠ»ΡΠΊΠΎ ΡΠ΄Π°ΡΠ½ΠΎΠΉ, ΡΡΠΎ Π½Π°ΠΌ ΠΏΠΎΡΡΠ΅Π±ΡΠ΅ΡΡΡ Π΅ΡΠ΅ Ρ Π΄Π΅ΡΡΡΠΎΠΊ ΡΡΠ°ΡΠ΅ΠΉ, ΡΡΠΎΠ±Ρ ΠΎΠΏΠΈΡΠ°ΡΡ Π²ΡΠ΅ Π΅Π΅ ΠΏΡΠΈΠΌΠ΅Π½Π΅Π½ΠΈΡ. (ΠΠ΄ΠΈΠ½ΡΡΠ²Π΅Π½Π½ΠΎΠ΅ Ρ ΡΠ΅ΠΌ Π½Π΅ ΡΠΏΡΠ°Π²ΠΈΠ»ΠΈΡΡ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ, ΠΊΠ°ΠΊ Π²Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π²ΠΈΠ΄Π΅ΡΡ Π½Π° ΠΊΠΏΠ΄Π² Π½ΠΈΠΆΠ΅, ΡΡΠΎ Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΠ΅ΠΌ ΠΏΡΠΈΠ»ΠΈΡΠ½ΠΎΠ³ΠΎ Π»ΠΎΠ³ΠΎΡΠΈΠΏΠ°.)
Π ΡΡΠΎΠΉ ΡΡΠ°ΡΡΠ΅ ΠΎΠΏΠΈΡΡΠ²Π°Π΅ΡΡΡ ΡΡΡΠΎΠ΅Π½ΠΈΠ΅ Π²ΠΈΡΡΡΠ°Π»ΡΠ½ΠΎΠΉ ΠΌΠ°ΡΠΈΠ½Ρ BPF, ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΡ ΡΠ΄ΡΠ° Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ BPF, ΡΡΠ΅Π΄ΡΡΠ²Π° ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ, Π° ΡΠ°ΠΊΠΆΠ΅ ΠΊΡΠ°ΡΠΊΠΈΠΉ, ΠΎΡΠ΅Π½Ρ ΠΊΡΠ°ΡΠΊΠΈΠΉ, ΠΎΠ±Π·ΠΎΡ ΡΡΡΠ΅ΡΡΠ²ΡΡΡΠΈΡ
Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΠ΅ΠΉ, Ρ.Π΅. Π²ΡΡ ΡΠΎ, ΡΡΠΎ Π½Π°ΠΌ ΠΏΠΎΡΡΠ΅Π±ΡΠ΅ΡΡΡ Π² Π΄Π°Π»ΡΠ½Π΅ΠΉΡΠ΅ΠΌ Π΄Π»Ρ Π±ΠΎΠ»Π΅Π΅ Π³Π»ΡΠ±ΠΎΠΊΠΎΠ³ΠΎ ΠΈΠ·ΡΡΠ΅Π½ΠΈΡ ΠΏΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈΡ
ΠΏΡΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠΉ BPF.
ΠΡΠ°ΡΠΊΠΎΠ΅ ΡΠΎΠ΄Π΅ΡΠΆΠ°Π½ΠΈΠ΅ ΡΡΠ°ΡΡΠΈ
bpf(2)
.
ΠΠΈΡΠ΅ΠΌ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ BPF Ρ ΠΏΠΎΠΌΠΎΡΡΡ libbpf
.libbpf
. ΠΡ ΡΠΎΠ·Π΄Π°Π΄ΠΈΠΌ ΠΏΡΠΎΡΡΠ΅ΠΉΡΠΈΠΉ ΡΠΊΠ΅Π»Π΅Ρ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ BPF, ΠΊΠΎΡΠΎΡΡΠΉ ΠΌΡ Π±ΡΠ΄Π΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π² ΠΏΠΎΡΠ»Π΅Π΄ΡΡΡΠΈΡ
ΠΏΡΠΈΠΌΠ΅ΡΠ°Ρ
.
ΠΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π² Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΡ BPF
ΠΠ΅ΡΠ΅Π΄ ΡΠ΅ΠΌ ΠΊΠ°ΠΊ Π½Π°ΡΠ°ΡΡ ΡΠ°ΡΡΠΌΠ°ΡΡΠΈΠ²Π°ΡΡ Π°ΡΡ
ΠΈΡΠ΅ΠΊΡΡΡΡ BPF ΠΌΡ Π² ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΠΉ ΡΠ°Π· (ΠΎΠΉ Π»ΠΈ) ΡΠΎΡΠ»Π΅ΠΌΡΡ Π½Π°
ΠΠΎΠ²ΡΠΉ BPF Π±ΡΠ» ΡΠ°Π·ΡΠ°Π±ΠΎΡΠ°Π½ ΠΊΠ°ΠΊ ΠΎΡΠ²Π΅Ρ Π½Π° ΠΏΠΎΠ²ΡΠ΅ΠΌΠ΅ΡΡΠ½ΠΎΠ΅ ΡΠ°ΡΠΏΡΠΎΡΡΡΠ°Π½Π΅Π½ΠΈΠ΅ 64-Π±ΠΈΡΠ½ΡΡ ΠΌΠ°ΡΠΈΠ½, ΠΎΠ±Π»Π°ΡΠ½ΡΡ ΡΠ΅ΡΠ²ΠΈΡΠΎΠ² ΠΈ Π²ΠΎΠ·ΡΠΎΡΡΠΈΡ ΠΏΠΎΡΡΠ΅Π±Π½ΠΎΡΡΠ΅ΠΉ Π² ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠ°Ρ Π΄Π»Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ SDN (Software-defined networking). Π Π°Π·ΡΠ°Π±ΠΎΡΠ°Π½Π½ΡΠΉ ΡΠ΅ΡΠ΅Π²ΡΠΌΠΈ ΠΈΠ½ΠΆΠ΅Π½Π΅ΡΠ°ΠΌΠΈ ΡΠ΄ΡΠ° ΠΊΠ°ΠΊ ΡΡΠΎΠ²Π΅ΡΡΠ΅Π½ΡΡΠ²ΠΎΠ²Π°Π½Π½Π°Ρ Π·Π°ΠΌΠ΅Π½Π° ΠΊΠ»Π°ΡΡΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ BPF, Π½ΠΎΠ²ΡΠΉ BPF Π±ΡΠΊΠ²Π°Π»ΡΠ½ΠΎ ΡΠ΅ΡΠ΅Π· ΠΏΠΎΠ»Π³ΠΎΠ΄Π° Π½Π°ΡΠ΅Π» ΠΏΡΠΈΠΌΠ΅Π½Π΅Π½ΠΈΡ Π² Π½Π΅Π»Π΅Π³ΠΊΠΎΠΌ Π΄Π΅Π»Π΅ ΡΡΠ°ΡΡΠΈΡΠΎΠ²ΠΊΠΈ Linux ΡΠΈΡΡΠ΅ΠΌ, Π° ΡΠ΅ΠΉΡΠ°Ρ, ΡΠ΅ΡΠ΅Π· ΡΠ΅ΡΡΡ Π»Π΅Ρ ΠΏΠΎΡΠ»Π΅ ΠΏΠΎΡΠ²Π»Π΅Π½ΠΈΡ, Π½Π°ΠΌ ΠΏΠΎΡΡΠ΅Π±ΡΠ΅ΡΡΡ ΡΠ΅Π»Π°Ρ, ΡΠ»Π΅Π΄ΡΡΡΠ°Ρ, ΡΡΠ°ΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ Π΄Π»Ρ ΡΠΎΠ³ΠΎ, ΡΡΠΎΠ±Ρ ΠΏΠ΅ΡΠ΅ΡΠΈΡΠ»ΠΈΡΡ ΡΠ°Π·Π½ΡΠ΅ ΡΠΈΠΏΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌ.
ΠΠ΅Π‘ΡΠΡΠ ΠΠ°Π ΡΠΠ½ΠΠΈ
Π ΡΠ²ΠΎΠ΅ΠΉ ΠΎΡΠ½ΠΎΠ²Π΅ BPF β ΡΡΠΎ Π²ΠΈΡΡΡΠ°Π»ΡΠ½Π°Ρ ΠΌΠ°ΡΠΈΠ½Π°-ΠΏΠ΅ΡΠΎΡΠ½ΠΈΡΠ°, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡΡΠ°Ρ Π·Π°ΠΏΡΡΠΊΠ°ΡΡ Β«ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ»ΡΠ½ΡΠΉΒ» ΠΊΠΎΠ΄ Π² ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²Π΅ ΡΠ΄ΡΠ° Π±Π΅Π· ΡΡΠ΅ΡΠ±Π° Π΄Π»Ρ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΠΈ. ΠΡΠΎΠ³ΡΠ°ΠΌΠΌΡ BPF ΡΠΎΠ·Π΄Π°ΡΡΡΡ Π² ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²Π΅ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ, Π·Π°Π³ΡΡΠΆΠ°ΡΡΡΡ Π² ΡΠ΄ΡΠΎ ΠΈ ΠΏΠΎΠ΄ΡΠΎΠ΅Π΄ΠΈΠ½ΡΡΡΡΡ ΠΊ ΠΊΠ°ΠΊΠΎΠΌΡ-Π½ΠΈΠ±ΡΠ΄Ρ ΠΈΡΡΠΎΡΠ½ΠΈΠΊΡ ΡΠΎΠ±ΡΡΠΈΠΉ. Π‘ΠΎΠ±ΡΡΠΈΠ΅ΠΌ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, Π΄ΠΎΡΡΠ°Π²ΠΊΠ° ΠΏΠ°ΠΊΠ΅ΡΠ° Π½Π° ΡΠ΅ΡΠ΅Π²ΠΎΠΉ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ, Π·Π°ΠΏΡΡΠΊ ΠΊΠ°ΠΊΠΎΠΉ-Π½ΠΈΠ±ΡΠ΄Ρ ΡΡΠ½ΠΊΡΠΈΠΈ ΡΠ΄ΡΠ°, ΠΈ Ρ.ΠΏ. Π ΡΠ»ΡΡΠ°Π΅ ΠΏΠ°ΠΊΠ΅ΡΠ° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ΅ BPF Π±ΡΠ΄ΡΡ Π΄ΠΎΡΡΡΠΏΠ½Ρ Π΄Π°Π½Π½ΡΠ΅ ΠΈ ΠΌΠ΅ΡΠ°Π΄Π°Π½Π½ΡΠ΅ ΠΏΠ°ΠΊΠ΅ΡΠ° (Π½Π° ΡΡΠ΅Π½ΠΈΠ΅ ΠΈ, ΠΌΠΎΠΆΠ΅Ρ, Π½Π° Π·Π°ΠΏΠΈΡΡ, Π² Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΠΎΡ ΡΠΈΠΏΠ° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ), Π² ΡΠ»ΡΡΠ°Π΅ Π·Π°ΠΏΡΡΠΊΠ° ΡΡΠ½ΠΊΡΠΈΠΈ ΡΠ΄ΡΠ° β Π°ΡΠ³ΡΠΌΠ΅Π½ΡΡ ΡΡΠ½ΠΊΡΠΈΠΈ, Π²ΠΊΠ»ΡΡΠ°Ρ ΡΠΊΠ°Π·Π°ΡΠ΅Π»ΠΈ Π½Π° ΠΏΠ°ΠΌΡΡΡ ΡΠ΄ΡΠ°, ΠΈ Ρ.ΠΏ.
ΠΠ°Π²Π°ΠΉΡΠ΅ ΠΏΠΎΡΠΌΠΎΡΡΠΈΠΌ Π½Π° ΡΡΠΎΡ ΠΏΡΠΎΡΠ΅ΡΡ ΠΏΠΎΠ΄ΡΠΎΠ±Π½Π΅Π΅. ΠΠ»Ρ Π½Π°ΡΠ°Π»Π° ΡΠ°ΡΡΠΊΠ°ΠΆΠ΅ΠΌ ΠΏΡΠΎ ΠΏΠ΅ΡΠ²ΠΎΠ΅ ΠΎΡΠ»ΠΈΡΠΈΠ΅ ΠΎΡ ΠΊΠ»Π°ΡΡΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ BPF, ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ Π΄Π»Ρ ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ ΠΏΠΈΡΠ°Π»ΠΈΡΡ Π½Π° Π°ΡΡΠ΅ΠΌΠ±Π»Π΅ΡΠ΅. Π Π½ΠΎΠ²ΠΎΠΉ Π²Π΅ΡΡΠΈΠΈ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ° Π±ΡΠ»Π° Π΄ΠΎΠΏΠΎΠ»Π½Π΅Π½Π° ΡΠ°ΠΊ, ΡΡΠΎ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ ΡΡΠ°Π»ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΈΡΠ°ΡΡ Π½Π° ΡΠ·ΡΠΊΠ°Ρ Π²ΡΡΠΎΠΊΠΎΠ³ΠΎ ΡΡΠΎΠ²Π½Ρ, Π² ΠΏΠ΅ΡΠ²ΡΡ ΠΎΡΠ΅ΡΠ΅Π΄Ρ, ΠΊΠΎΠ½Π΅ΡΠ½ΠΎ, Π½Π° C. ΠΠ»Ρ ΡΡΠΎΠ³ΠΎ Π±ΡΠ» ΡΠ°Π·ΡΠ°Π±ΠΎΡΠ°Π½ Π±Π°ΠΊΠ΅Π½Π΄ Π΄Π»Ρ llvm, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡΡΠΈΠΉ Π³Π΅Π½Π΅ΡΠΈΡΠΎΠ²Π°ΡΡ Π±Π°ΠΉΡ-ΠΊΠΎΠ΄ Π΄Π»Ρ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΡ BPF.
ΠΡΡ
ΠΈΡΠ΅ΠΊΡΡΡΠ° BPF ΡΠ°Π·ΡΠ°Π±Π°ΡΡΠ²Π°Π»Π°ΡΡ, Π² ΡΠ°ΡΡΠ½ΠΎΡΡΠΈ, Π΄Π»Ρ ΡΠΎΠ³ΠΎ, ΡΡΠΎΠ±Ρ ΡΡΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎ Π²ΡΠΏΠΎΠ»Π½ΡΡΡΡΡ Π½Π° ΡΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ
ΠΌΠ°ΡΠΈΠ½Π°Ρ
. ΠΠ»Ρ ΡΠΎΠ³ΠΎ, ΡΡΠΎΠ±Ρ ΡΡΠΎ ΡΠ°Π±ΠΎΡΠ°Π»ΠΎ Π½Π° ΠΏΡΠ°ΠΊΡΠΈΠΊΠ΅, Π±Π°ΠΉΡ-ΠΊΠΎΠ΄ BPF, ΠΏΠΎΡΠ»Π΅ Π·Π°Π³ΡΡΠ·ΠΊΠΈ Π² ΡΠ΄ΡΠΎ ΡΡΠ°Π½ΡΠ»ΠΈΡΡΠ΅ΡΡΡ Π² Π½Π°ΡΠΈΠ²Π½ΡΠΉ ΠΊΠΎΠ΄ ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ° ΠΏΠΎΠ΄ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ΠΌ JIT compiler (Just In Time). ΠΠ°Π»Π΅Π΅, Π΅ΡΠ»ΠΈ Π²Ρ ΠΏΠΎΠΌΠ½ΠΈΡΠ΅, Π² ΠΊΠ»Π°ΡΡΠΈΡΠ΅ΡΠΊΠΎΠΌ BPF ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ° Π·Π°Π³ΡΡΠΆΠ°Π»Π°ΡΡ Π² ΡΠ΄ΡΠΎ ΠΈ ΠΏΡΠΈΡΠΎΠ΅Π΄ΠΈΠ½ΡΠ»Π°ΡΡ ΠΊ ΠΈΡΡΠΎΡΠ½ΠΈΠΊΡ ΡΠΎΠ±ΡΡΠΈΠΉ Π°ΡΠΎΠΌΠ°ΡΠ½ΠΎ β Π² ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ΅ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΡΠΈΡΡΠ΅ΠΌΠ½ΠΎΠ³ΠΎ Π²ΡΠ·ΠΎΠ²Π°. Π Π½ΠΎΠ²ΠΎΠΉ Π°ΡΡ
ΠΈΡΠ΅ΠΊΡΡΡΠ΅ ΡΡΠΎ ΠΏΡΠΎΠΈΡΡ
ΠΎΠ΄ΠΈΡ Π² Π΄Π²Π° ΡΡΠ°ΠΏΠ° β ΡΠ½Π°ΡΠ°Π»Π° ΠΊΠΎΠ΄ Π·Π°Π³ΡΡΠΆΠ°Π΅ΡΡΡ Π² ΡΠ΄ΡΠΎ ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ ΡΠΈΡΡΠ΅ΠΌΠ½ΠΎΠ³ΠΎ Π²ΡΠ·ΠΎΠ²Π° bpf(2)
, Π° Π·Π°ΡΠ΅ΠΌ, ΠΏΠΎΠ·Π΄Π½Π΅Π΅, ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ Π΄ΡΡΠ³ΠΈΡ
ΠΌΠ΅Ρ
Π°Π½ΠΈΠ·ΠΌΠΎΠ², ΡΠ°Π·Π½ΡΡ
Π² Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΠΎΡ ΡΠΈΠΏΠ° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ, ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ° ΠΏΠΎΠ΄ΡΠΎΠ΅Π΄ΠΈΠ½ΡΠ΅ΡΡΡ (attaches) ΠΊ ΠΈΡΡΠΎΡΠ½ΠΈΠΊΡ ΡΠΎΠ±ΡΡΠΈΠΉ.
Π’ΡΡ Ρ ΡΠΈΡΠ°ΡΠ΅Π»Ρ ΠΌΠΎΠΆΠ΅Ρ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡΡΡ Π²ΠΎΠΏΡΠΎΡ: Π° ΡΡΠΎ, ΡΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ Π±ΡΠ»ΠΎ? ΠΠ°ΠΊΠΈΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ Π³Π°ΡΠ°Π½ΡΠΈΡΡΠ΅ΡΡΡ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΡΠ°ΠΊΠΎΠ³ΠΎ ΠΊΠΎΠ΄Π°? ΠΠ΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ Π³Π°ΡΠ°Π½ΡΠΈΡΡΠ΅ΡΡΡ Π½Π°ΠΌ ΡΡΠ°ΠΏΠΎΠΌ Π·Π°Π³ΡΡΠ·ΠΊΠΈ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌ BPF ΠΏΠΎΠ΄ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ΠΌ Π²Π΅ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ (ΠΏΠΎ-Π°Π½Π³Π»ΠΈΠΉΡΠΊΠΈ ΡΡΠΎΡ ΡΡΠ°ΠΏ Π½Π°Π·ΡΠ²Π°Π΅ΡΡΡ verifier ΠΈ Ρ Π΄Π°Π»ΡΡΠ΅ Π±ΡΠ΄Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π°Π½Π³Π»ΠΈΠΉΡΠΊΠΎΠ΅ ΡΠ»ΠΎΠ²ΠΎ):
Verifier β ΡΡΠΎ ΡΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠΉ Π°Π½Π°Π»ΠΈΠ·Π°ΡΠΎΡ, ΠΊΠΎΡΠΎΡΡΠΉ Π³Π°ΡΠ°Π½ΡΠΈΡΡΠ΅Ρ, ΡΡΠΎ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ° Π½Π΅ Π½Π°ΡΡΡΠΈΡ Π½ΠΎΡΠΌΠ°Π»ΡΠ½ΡΠΉ Ρ ΠΎΠ΄ ΡΠ°Π±ΠΎΡΡ ΡΠ΄ΡΠ°. ΠΡΠΎ, ΠΊΡΡΠ°ΡΠΈ, Π½Π΅ ΠΎΠ·Π½Π°ΡΠ°Π΅Ρ, ΡΡΠΎ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ° Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ Π²ΠΌΠ΅ΡΠ°ΡΡΡΡ Π² ΡΠ°Π±ΠΎΡΡ ΡΠΈΡΡΠ΅ΠΌΡ β ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ BPF, Π² Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΠΎΡ ΡΠΈΠΏΠ°, ΠΌΠΎΠ³ΡΡ ΡΠΈΡΠ°ΡΡ ΠΈ ΠΏΠ΅ΡΠ΅ΠΏΠΈΡΡΠ²Π°ΡΡ ΡΡΠ°ΡΡΠΊΠΈ ΠΏΠ°ΠΌΡΡΠΈ ΡΠ΄ΡΠ°, Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΠΌΡΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΡ ΡΡΠ½ΠΊΡΠΈΠΉ, ΠΎΠ±ΡΠ΅Π·Π°ΡΡ, Π΄ΠΎΠΏΠΎΠ»Π½ΡΡΡ, ΠΏΠ΅ΡΠ΅ΠΏΠΈΡΡΠ²Π°ΡΡ ΠΈ Π΄Π°ΠΆΠ΅ ΠΏΠ΅ΡΠ΅ΡΡΠ»Π°ΡΡ ΡΠ΅ΡΠ΅Π²ΡΠ΅ ΠΏΠ°ΠΊΠ΅ΡΡ. Verifier Π³Π°ΡΠ°Π½ΡΠΈΡΡΠ΅Ρ, ΡΡΠΎ ΠΎΡ Π·Π°ΠΏΡΡΠΊΠ° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ BPF ΡΠ΄ΡΠΎ Π½Π΅ ΡΠ²Π°Π»ΠΈΡΡΡ ΠΈ ΡΡΠΎ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ°, ΠΊΠΎΡΠΎΡΠΎΠΉ ΠΏΠΎ ΠΏΡΠ°Π²ΠΈΠ»Π°ΠΌ Π΄ΠΎΡΡΡΠΏΠ½Ρ Π½Π° Π·Π°ΠΏΠΈΡΡ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, Π΄Π°Π½Π½ΡΠ΅ ΠΈΡΡ ΠΎΠ΄ΡΡΠ΅Π³ΠΎ ΠΏΠ°ΠΊΠ΅ΡΠ°, Π½Π΅ ΡΠΌΠΎΠΆΠ΅Ρ ΠΏΠ΅ΡΠ΅ΠΏΠΈΡΠ°ΡΡ ΠΏΠ°ΠΌΡΡΡ ΡΠ΄ΡΠ° Π²Π½Π΅ ΠΏΠ°ΠΊΠ΅ΡΠ°. Π§ΡΡΡ Π±ΠΎΠ»Π΅Π΅ ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎ ΠΌΡ ΠΏΠΎΡΠΌΠΎΡΡΠΈΠΌ Π½Π° verifier Π² ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠ΅ΠΌ ΡΠ°Π·Π΄Π΅Π»Π΅, ΠΏΠΎΡΠ»Π΅ ΡΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΏΠΎΠ·Π½Π°ΠΊΠΎΠΌΠΈΠΌΡΡ ΡΠΎ Π²ΡΠ΅ΠΌΠΈ ΠΎΡΡΠ°Π»ΡΠ½ΡΠΌΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°ΠΌΠΈ BPF.
ΠΡΠ°ΠΊ, ΡΡΠΎ ΠΌΡ ΡΠ·Π½Π°Π»ΠΈ ΠΊ ΡΡΠΎΠΌΡ ΠΌΠΎΠΌΠ΅Π½ΡΡ? ΠΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ ΠΏΠΈΡΠ΅Ρ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ Π½Π° ΡΠ·ΡΠΊΠ΅ C, Π·Π°Π³ΡΡΠΆΠ°Π΅Ρ Π΅Π΅ Π² ΡΠ΄ΡΠΎ ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ ΡΠΈΡΡΠ΅ΠΌΠ½ΠΎΠ³ΠΎ Π²ΡΠ·ΠΎΠ²Π° bpf(2)
, Π³Π΄Π΅ ΠΎΠ½Π° ΠΏΡΠΎΡ
ΠΎΠ΄ΠΈΡ ΠΏΡΠΎΠ²Π΅ΡΠΊΡ Π½Π° verifier ΠΈ ΡΡΠ°Π½ΡΠ»ΠΈΡΡΠ΅ΡΡΡ Π² Π½Π°ΡΠΈΠ²Π½ΡΠΉ Π±Π°ΠΉΡΠΊΠΎΠ΄. ΠΠ°ΡΠ΅ΠΌ ΡΠΎΡ ΠΆΠ΅ ΠΈΠ»ΠΈ Π΄ΡΡΠ³ΠΎΠΉ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ ΠΏΠΎΠ΄ΡΠΎΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ ΠΊ ΠΈΡΡΠΎΡΠ½ΠΈΠΊΡ ΡΠΎΠ±ΡΡΠΈΠΉ ΠΈ ΠΎΠ½Π° Π½Π°ΡΠΈΠ½Π°Π΅Ρ Π²ΡΠΏΠΎΠ»Π½ΡΡΡΡΡ. Π Π°Π·Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Π·Π°Π³ΡΡΠ·ΠΊΠΈ ΠΈ ΠΏΠΎΠ΄ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ Π½ΡΠΆΠ½ΠΎ ΠΏΠΎ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΠΌ ΠΏΡΠΈΡΠΈΠ½Π°ΠΌ. ΠΠΎ-ΠΏΠ΅ΡΠ²ΡΡ
, Π·Π°ΠΏΡΡΠΊ verifier β ΡΡΠΎ ΠΎΡΠ½ΠΎΡΠΈΡΠ΅Π»ΡΠ½ΠΎ Π΄ΠΎΡΠΎΠ³ΠΎ ΠΈ, Π·Π°Π³ΡΡΠΆΠ°Ρ ΠΎΠ΄Π½Ρ ΠΈ ΡΡ ΠΆΠ΅ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΠ°Π·, ΠΌΡ ΡΡΠ°ΡΠΈΠΌ ΠΊΠΎΠΌΠΏΡΡΡΠ΅ΡΠ½ΠΎΠ΅ Π²ΡΠ΅ΠΌΡ Π²ΠΏΡΡΡΡΡ. ΠΠΎ-Π²ΡΠΎΡΡΡ
, ΡΠΎ, ΠΊΠ°ΠΊ ΠΈΠΌΠ΅Π½Π½ΠΎ ΠΏΠΎΠ΄ΡΠΎΠ΅Π΄ΠΈΠ½ΡΠ΅ΡΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ°, Π·Π°Π²ΠΈΡΠΈΡ ΠΎΡ Π΅Π΅ ΡΠΈΠΏΠ° ΠΈ ΠΎΠ΄ΠΈΠ½ Β«ΡΠ½ΠΈΠ²Π΅ΡΡΠ°Π»ΡΠ½ΡΠΉΒ» ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ, ΡΠ°Π·ΡΠ°Π±ΠΎΡΠ°Π½Π½ΡΠΉ Π³ΠΎΠ΄ Π½Π°Π·Π°Π΄ ΠΌΠΎΠΆΠ΅Ρ Π½Π΅ ΠΏΠΎΠ΄ΠΎΠΉΡΠΈ Π΄Π»Ρ Π½ΠΎΠ²ΡΡ
ΡΠΈΠΏΠΎΠ² ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌ. (Π₯ΠΎΡΡ ΡΠ΅ΠΉΡΠ°Ρ, ΠΊΠΎΠ³Π΄Π° Π°ΡΡ
ΠΈΡΠ΅ΠΊΡΡΡΠ° ΡΡΠ°Π½ΠΎΠ²ΠΈΡΡΡ Π±ΠΎΠ»Π΅Π΅ Π·ΡΠ΅Π»ΠΎΠΉ, Π΅ΡΡΡ ΠΈΠ΄Π΅Ρ ΡΠ½ΠΈΡΠΈΡΠΈΡΠΎΠ²Π°ΡΡ ΡΡΠΎΡ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ Π½Π° ΡΡΠΎΠ²Π½Π΅ libbpf
.)
ΠΠ½ΠΈΠΌΠ°ΡΠ΅Π»ΡΠ½ΡΠΉ ΡΠΈΡΠ°ΡΠ΅Π»Ρ ΠΌΠΎΠΆΠ΅Ρ Π·Π°ΠΌΠ΅ΡΠΈΡΡ, ΡΡΠΎ ΠΌΡ Π΅ΡΠ΅ Π½Π΅ Π·Π°ΠΊΠΎΠ½ΡΠΈΠ»ΠΈ Ρ ΠΊΠ°ΡΡΠΈΠ½ΠΊΠ°ΠΌΠΈ. Π ΠΏΡΠ°Π²Π΄Π°, Π²ΡΠ΅ ΡΠΊΠ°Π·Π°Π½Π½ΠΎΠ΅ Π²ΡΡΠ΅ Π½Π΅ ΠΎΠ±ΡΡΡΠ½ΡΠ΅Ρ, ΡΠ΅ΠΌ BPF ΠΏΡΠΈΠ½ΡΠΈΠΏΠΈΠ°Π»ΡΠ½ΠΎ ΠΌΠ΅Π½ΡΠ΅Ρ ΠΊΠ°ΡΡΠΈΠ½Ρ ΠΏΠΎ ΡΡΠ°Π²Π½Π΅Π½ΠΈΡ Ρ ΠΊΠ»Π°ΡΡΠΈΡΠ΅ΡΠΊΠΈΠΌ BPF. ΠΠ²Π° Π½ΠΎΠ²ΡΠ΅ΡΡΠ²Π°, ΠΊΠΎΡΠΎΡΡΠ΅ ΡΡΡΠ΅ΡΡΠ²Π΅Π½Π½ΠΎ ΡΠ°ΡΡΠΈΡΡΡΡ Π³ΡΠ°Π½ΠΈΡΡ ΠΏΡΠΈΠΌΠ΅Π½ΠΈΠΌΠΎΡΡΠΈ β ΡΡΠΎ Π½Π°Π»ΠΈΡΠΈΠ΅ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΠ°Π·Π΄Π΅Π»ΡΠ΅ΠΌΡΡ ΠΏΠ°ΠΌΡΡΡ ΠΈ ΡΡΠ½ΠΊΡΠΈΠΈ-ΠΏΠΎΠΌΠΎΡΠ½ΠΈΠΊΠΈ ΡΠ΄ΡΠ° (kernel helpers). Π BPF ΡΠ°Π·Π΄Π΅Π»ΡΠ΅ΠΌΠ°Ρ ΠΏΠ°ΠΌΡΡΡ ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π° ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ ΡΠ°ΠΊ Π½Π°Π·ΡΠ²Π°Π΅ΠΌΡΡ maps β ΡΠ°Π·Π΄Π΅Π»ΡΠ΅ΠΌΡΡ ΡΡΡΡΠΊΡΡΡ Π΄Π°Π½Π½ΡΡ Ρ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½Π½ΡΠΌ API. Π’Π°ΠΊΠΎΠ΅ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ ΠΎΠ½ΠΈ ΠΏΠΎΠ»ΡΡΠΈΠ»ΠΈ, Π½Π°Π²Π΅ΡΠ½ΠΎΠ΅, ΠΏΠΎΡΠΎΠΌΡ, ΡΡΠΎ ΠΏΠ΅ΡΠ²ΡΠΌ ΠΏΠΎΡΠ²ΠΈΠ²ΡΠΈΠΌΡΡ ΡΠΈΠΏΠΎΠΌ map Π±ΡΠ»Π° Ρ ΡΡ-ΡΠ°Π±Π»ΠΈΡΠ°. ΠΠ°Π»ΡΡΠ΅ ΠΏΠΎΡΠ²ΠΈΠ»ΠΈΡΡ ΠΌΠ°ΡΡΠΈΠ²Ρ, Π»ΠΎΠΊΠ°Π»ΡΠ½ΡΠ΅ (per-CPU) Ρ ΡΡ-ΡΠ°Π±Π»ΠΈΡΡ ΠΈ Π»ΠΎΠΊΠ°Π»ΡΠ½ΡΠ΅ ΠΌΠ°ΡΡΠΈΠ²Ρ, Π΄Π΅ΡΠ΅Π²ΡΡ ΠΏΠΎΠΈΡΠΊΠ°, ΠΌΠ°ΠΏΡ, ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΠΈΠ΅ ΡΠΊΠ°Π·Π°ΡΠ΅Π»ΠΈ Π½Π° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ BPF ΠΈ ΠΌΠ½ΠΎΠ³ΠΎΠ΅ Π΄ΡΡΠ³ΠΎΠ΅. ΠΠ°ΠΌ ΡΠ΅ΠΉΡΠ°Ρ ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ΅Π½ ΡΠΎΡ ΡΠ°ΠΊΡ, ΡΡΠΎ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ BPF ΠΏΠΎΠ»ΡΡΠΈΠ»ΠΈ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ ΡΠΎΡ ΡΠ°Π½ΡΡΡ ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅ ΠΌΠ΅ΠΆΠ΄Ρ Π²ΡΠ·ΠΎΠ²Π°ΠΌΠΈ ΠΈ ΡΠ°Π·Π΄Π΅Π»ΡΡΡ Π΅Π³ΠΎ Ρ Π΄ΡΡΠ³ΠΈΠΌΠΈ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ°ΠΌΠΈ ΠΈ Ρ ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²ΠΎΠΌ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ.
ΠΠΎΡΡΡΠΏ ΠΊ maps ΠΎΡΡΡΠ΅ΡΡΠ²Π»ΡΠ΅ΡΡΡ ΠΈΠ· ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΡΠΊΠΈΡ
ΠΏΡΠΎΡΠ΅ΡΡΠΎΠ² ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ ΡΠΈΡΡΠ΅ΠΌΠ½ΠΎΠ³ΠΎ Π²ΡΠ·ΠΎΠ²Π° bpf(2)
, Π° ΠΈΠ· ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌ BPF, ΡΠ°Π±ΠΎΡΠ°ΡΡΠΈΡ
Π² ΡΠ΄ΡΠ΅ β ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ ΡΡΠ½ΠΊΡΠΈΠΉ-ΠΏΠΎΠΌΠΎΡΠ½ΠΈΠΊΠΎΠ². ΠΠΎΠ»Π΅Π΅ ΡΠΎΠ³ΠΎ, helpers ΡΡΡΠ΅ΡΡΠ²ΡΡΡ Π½Π΅ ΡΠΎΠ»ΡΠΊΠΎ Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ ΠΌΠ°ΠΏΠ°ΠΌΠΈ, Π½ΠΎ ΠΈ Π΄Π»Ρ Π΄ΠΎΡΡΡΠΏΠ° ΠΊ Π΄ΡΡΠ³ΠΈΠΌ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡΠΌ ΡΠ΄ΡΠ°. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ BPF ΠΌΠΎΠ³ΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΡΠ½ΠΊΡΠΈΠΈ-ΠΏΠΎΠΌΠΎΡΠ½ΠΈΠΊΠΈ Π΄Π»Ρ ΠΏΠ΅ΡΠ΅Π½Π°ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ ΠΏΠ°ΠΊΠ΅ΡΠΎΠ² Π½Π° Π΄ΡΡΠ³ΠΈΠ΅ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΡ, Π΄Π»Ρ Π³Π΅Π½Π΅ΡΠ°ΡΠΈΠΈ ΡΠΎΠ±ΡΡΠΈΠΉ ΠΏΠΎΠ΄ΡΠΈΡΡΠ΅ΠΌΡ perf, Π΄ΠΎΡΡΡΠΏΠ° ΠΊ ΡΡΡΡΠΊΡΡΡΠ°ΠΌ ΡΠ΄ΡΠ° ΠΈ Ρ.ΠΏ.
ΠΡΠΎΠ³ΠΎ, BPF ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΠ΅Ρ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ Π·Π°Π³ΡΡΠΆΠ°ΡΡ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ»ΡΠ½ΡΠΉ, Ρ.Π΅., ΠΏΡΠΎΡΠ΅Π΄ΡΠΈΠΉ ΠΏΡΠΎΠ²Π΅ΡΠΊΡ Π½Π° verifier, ΠΊΠΎΠ΄ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ Π² ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²ΠΎ ΡΠ΄ΡΠ°. ΠΡΠΎΡ ΠΊΠΎΠ΄ ΠΌΠΎΠΆΠ΅Ρ ΡΠΎΡ ΡΠ°Π½ΡΡΡ ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅ ΠΌΠ΅ΠΆΠ΄Ρ Π²ΡΠ·ΠΎΠ²Π°ΠΌΠΈ ΠΈ ΠΎΠ±ΠΌΠ΅Π½ΠΈΠ²Π°ΡΡΡΡ Π΄Π°Π½Π½ΡΠΌΠΈ Ρ ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²ΠΎΠΌ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ, Π° ΡΠ°ΠΊΠΆΠ΅ ΠΈΠΌΠ΅Π΅Ρ Π΄ΠΎΡΡΡΠΏ ΠΊ ΡΠ°Π·ΡΠ΅ΡΠ΅Π½Π½ΡΠΌ Π΄Π°Π½Π½ΠΎΠΌΡ ΡΠΈΠΏΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌ ΠΏΠΎΠ΄ΡΠΈΡΡΠ΅ΠΌΠ°ΠΌ ΡΠ΄ΡΠ°.
ΠΡΠΎ ΡΠΆΠ΅ ΠΏΠΎΡ ΠΎΠΆΠ΅ Π½Π° Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΠΈ, ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΠ΅ΠΌΡΠ΅ ΠΌΠΎΠ΄ΡΠ»ΡΠΌΠΈ ΡΠ΄ΡΠ°, ΠΏΠΎ ΡΡΠ°Π²Π½Π΅Π½ΠΈΡ Ρ ΠΊΠΎΡΠΎΡΡΠΌΠΈ Ρ 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
ΠΈ ΡΡΡΡΡΠΈΠΊ ΠΊΠΎΠΌΠ°Π½Π΄ (program counter). Π Π΅Π³ΠΈΡΡΡ r10
ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ ΡΠΊΠ°Π·Π°ΡΠ΅Π»Ρ Π½Π° ΡΡΠ΅ΠΊ (frame pointer) ΠΈ Π΄ΠΎΡΡΡΠΏΠ΅Π½ ΡΠΎΠ»ΡΠΊΠΎ Π΄Π»Ρ ΡΡΠ΅Π½ΠΈΡ. ΠΡΠΎΠ³ΡΠ°ΠΌΠΌΠ°ΠΌ Π²ΠΎ Π²ΡΠ΅ΠΌΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ Π΄ΠΎΡΡΡΠΏΠ΅Π½ ΡΡΠ΅ΠΊ Π² 512 Π±Π°ΠΉΡ ΠΈ Π½Π΅ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½Π½ΠΎΠ΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΡΠ°Π·Π΄Π΅Π»ΡΠ΅ΠΌΠΎΠΉ ΠΏΠ°ΠΌΡΡΠΈ Π² Π²ΠΈΠ΄Π΅ maps.
ΠΡΠΎΠ³ΡΠ°ΠΌΠΌΠ°ΠΌ BPF ΡΠ°Π·ΡΠ΅ΡΠ°Π΅ΡΡΡ Π·Π°ΠΏΡΡΠΊΠ°ΡΡ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½Π½ΡΠΉ Π² Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΠΎΡ ΡΠΈΠΏΠ° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ Π½Π°Π±ΠΎΡ ΡΡΠ½ΠΊΡΠΈΠΉ-ΠΏΠΎΠΌΠΎΡΠ½ΠΈΠΊΠΎΠ² (kernel helpers) ΠΈ, Ρ Π½Π΅Π΄Π°Π²Π½ΠΈΡ
ΠΏΠΎΡ, ΠΈ ΠΎΠ±ΡΡΠ½ΡΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ. ΠΠ°ΠΆΠ΄Π°Ρ Π²ΡΠ·ΡΠ²Π°Π΅ΠΌΠ°Ρ ΡΡΠ½ΠΊΡΠΈΡ ΠΌΠΎΠΆΠ΅Ρ ΠΏΡΠΈΠ½ΠΈΠΌΠ°ΡΡ Π΄ΠΎ ΠΏΡΡΠΈ Π°ΡΠ³ΡΠΌΠ΅Π½ΡΠΎΠ², ΠΏΠ΅ΡΠ΅Π΄Π°Π²Π°Π΅ΠΌΡΡ
Π² ΡΠ΅Π³ΠΈΡΡΡΠ°Ρ
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
struct __sk_buff
struct pt_regs
ΠΡΠ°ΠΊ, Ρ Π½Π°Ρ Π±ΡΠ» Π½Π°Π±ΠΎΡ ΡΠ΅Π³ΠΈΡΡΡΠΎΠ², kernel helpers, ΡΡΠ΅ΠΊ, ΡΠΊΠ°Π·Π°ΡΠ΅Π»Ρ Π½Π° ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡ ΠΈ ΡΠ°Π·Π΄Π΅Π»ΡΠ΅ΠΌΠ°Ρ ΠΏΠ°ΠΌΡΡΡ Π² Π²ΠΈΠ΄Π΅ maps. ΠΠ΅ ΡΠΎ, ΡΡΠΎΠ±Ρ Π²ΡΡ ΡΡΠΎ Π±ΡΠ»ΠΎ ΠΊΠ°ΡΠ΅Π³ΠΎΡΠΈΡΠ΅ΡΠΊΠΈ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ Π² ΠΏΠΎΠ΅Π·Π΄ΠΊΠ΅, Π½ΠΎ…
ΠΠ°Π²Π°ΠΉΡΠ΅ ΠΏΡΠΎΠ΄ΠΎΠ»ΠΆΠΈΠΌ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΠΈ ΡΠ°ΡΡΠΊΠ°ΠΆΠ΅ΠΌ ΠΏΡΠΎ ΡΠΈΡΡΠ΅ΠΌΡ ΠΊΠΎΠΌΠ°Π½Π΄ Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ ΡΡΠΈΠΌΠΈ ΠΎΠ±ΡΠ΅ΠΊΡΠ°ΠΌΠΈ. ΠΡΠ΅ (
ΠΠ΄Π΅ΡΡ Code
β ΡΡΠΎ ΠΊΠΎΠ΄ΠΈΡΠΎΠ²ΠΊΠ° ΠΈΠ½ΡΡΡΡΠΊΡΠΈΠΈ, Dst
/Src
βΒ ΡΡΠΎ ΠΊΠΎΠ΄ΠΈΡΠΎΠ²ΠΊΠΈ ΠΏΡΠΈΠ΅ΠΌΠ½ΠΈΠΊΠ° ΠΈ ΠΈΡΡΠΎΡΠ½ΠΈΠΊΠ°, ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²Π΅Π½Π½ΠΎ, Off
β 16-Π±ΠΈΡΠ½ΡΠΉ Π·Π½Π°ΠΊΠΎΠ²ΡΠΉ ΠΎΡΡΡΡΠΏ, Π° Imm
β ΡΡΠΎ 32-Π±ΠΈΡΠ½ΠΎΠ΅ Π·Π½Π°ΠΊΠΎΠ²ΠΎΠ΅ ΡΠ΅Π»ΠΎΠ΅ ΡΠΈΡΠ»ΠΎ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌΠΎΠ΅ Π² Π½Π΅ΠΊΠΎΡΠΎΡΡΡ
ΠΊΠΎΠΌΠ°Π½Π΄Π°Ρ
(Π°Π½Π°Π»ΠΎΠ³ ΠΊΠΎΠ½ΡΡΠ°Π½ΡΡ K ΠΈΠ· cBPF). ΠΠΎΠ΄ΠΈΡΠΎΠ²ΠΊΠ° Code
ΠΈΠΌΠ΅Π΅Ρ ΠΎΠ΄ΠΈΠ½ ΠΈΠ· Π΄Π²ΡΡ
Π²ΠΈΠ΄ΠΎΠ²:
ΠΠ»Π°ΡΡΡ ΠΈΠ½ΡΡΡΡΠΊΡΠΈΠΉ 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, Π° ΡΠ°ΠΊΠΆΠ΅ ΠΏΡΠΈ ΠΈΠ·ΡΡΠ΅Π½ΠΈΠΈ maps, Π²ΡΠ·ΠΎΠ²Π΅ ΡΡΠ½ΠΊΡΠΈΠΉ ΠΈ Ρ.ΠΏ.
ΠΠΎΠ³Π΄Π° ΠΌΡ Π±ΡΠ΄Π΅ΠΌ Π³ΠΎΠ²ΠΎΡΠΈΡΡ ΠΎΠ± ΠΈΠ½Π΄ΠΈΠ²ΠΈΠ΄ΡΠ°Π»ΡΠ½ΡΡ
ΠΈΠ½ΡΡΡΡΠΊΡΠΈΡΡ
, ΠΌΡ Π±ΡΠ΄Π΅ΠΌ ΡΡΡΠ»Π°ΡΡΡΡ Π½Π° ΡΠ°ΠΉΠ»Ρ ΡΠ΄ΡΠ° bpf.h
bpf_common.h
ΠΡΠΈΠΌΠ΅Ρ: Π΄ΠΈΠ·Π°ΡΡΠ΅ΠΌΠ±Π»ΠΈΡΡΠ΅ΠΌ 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
β ΡΡΠΎ s
(source), ΡΠΎ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ Π±Π΅ΡΠ΅ΡΡΡ ΠΈΠ· ΡΠ΅Π³ΠΈΡΡΡΠ°-ΠΈΡΡΠΎΡΠ½ΠΈΠΊΠ°, Π° Π΅ΡΠ»ΠΈ, ΠΊΠ°ΠΊ Π² Π½Π°ΡΠ΅ΠΌ ΡΠ»ΡΡΠ°Π΅, ΠΎΠ½ Π½Π΅ ΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½, ΡΠΎ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ Π±Π΅ΡΠ΅ΡΡΡ ΠΈΠ· ΠΏΠΎΠ»Ρ Imm
. Π’Π°ΠΊΠΈΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ, Π² ΠΏΠ΅ΡΠ²ΠΎΠΉ ΠΈ ΡΡΠ΅ΡΡΠ΅ΠΉ ΠΈΠ½ΡΡΡΡΠΊΡΠΈΡΡ
ΠΌΡ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΠΌ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΡ r0 = Imm
. ΠΠ°Π»Π΅Π΅, ΠΎΠΏΠ΅ΡΠ°ΡΠΈΡ 1 ΠΊΠ»Π°ΡΡΠ° JMP β ΡΡΠΎ S
ΡΠ°Π²Π΅Π½ Π½ΡΠ»Ρ, ΠΎΠ½Π° ΡΡΠ°Π²Π½ΠΈΠ²Π°Π΅Ρ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΡΠ΅Π³ΠΈΡΡΡΠ°-ΠΈΡΡΠΎΡΠ½ΠΈΠΊΠ° Ρ ΠΏΠΎΠ»Π΅ΠΌ Imm
. ΠΡΠ»ΠΈ Π·Π½Π°ΡΠ΅Π½ΠΈΡ ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡΡ, ΡΠΎ ΠΏΠ΅ΡΠ΅Ρ
ΠΎΠ΄ ΠΏΡΠΎΠΈΡΡ
ΠΎΠ΄ΠΈΡ Π½Π° PC + Off
, Π³Π΄Π΅ PC
, ΠΊΠ°ΠΊ Π²ΠΎΠ΄ΠΈΡΡΡ, ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ Π°Π΄ΡΠ΅Ρ ΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΉ ΠΈΠ½ΡΡΡΡΠΊΡΠΈΠΈ. ΠΠ°ΠΊΠΎΠ½Π΅Ρ, ΠΎΠΏΠ΅ΡΠ°ΡΠΈΡ 9 ΠΊΠ»Π°ΡΡΠ° JMP β ΡΡΠΎ 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
(Code = 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
, ΠΊΠΎΠ³Π΄Π° ΠΏΠΎΠ³ΠΎΠ²ΠΎΡΠΈΠΌ ΠΎ ΡΠ΅Π»ΠΎΠΊΠ°ΡΠΈΡΡ
ΠΈ ΡΠ°Π±ΠΎΡΠ΅ Ρ maps.
ΠΡΠΈΠΌΠ΅Ρ: Π΄ΠΈΠ·Π°ΡΡΠ΅ΠΌΠ±Π»ΠΈΡΡΠ΅ΠΌ 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
Π½Π΅ ΡΡΠ°Π½Π΅Ρ Π½ΡΠ»Π΅ΠΌ:
ΠΠΎΡΠ»Π΅ ΡΡΠΏΠ΅ΡΠ½ΠΎΠΉ Π·Π°Π³ΡΡΠ·ΠΊΠΈ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ ΠΌΡ ΠΎΠ±ΡΡΠ½ΠΎ ΠΏΡΠΈΡΠΎΠ΅Π΄ΠΈΠ½ΡΠ΅ΠΌ Π΅Π΅ ΠΊ ΠΊΠ°ΠΊΠΎΠΌΡ-Π½ΠΈΠ±ΡΠ΄Ρ Π³Π΅Π½Π΅ΡΠ°ΡΠΎΡΡ ΡΠΎΠ±ΡΡΠΈΠΉ. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΌΡ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠΎΡΠ°Π΄ΠΈΡΡ Π΅Π΅ Π½Π° ΡΠ΅ΡΠ΅Π²ΠΎΠΉ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ Π΄Π»Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ Π²Ρ
ΠΎΠ΄ΡΡΠΈΡ
ΠΏΠ°ΠΊΠ΅ΡΠΎΠ² ΠΈΠ»ΠΈ ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠΈΡΡ Π΅Π΅ ΠΊ ΠΊΠ°ΠΊΠΎΠΉ-Π½ΠΈΠ±ΡΠ΄Ρ tracepoint
Π² ΡΠ΄ΡΠ΅. Π ΡΡΠΎΡ ΠΌΠΎΠΌΠ΅Π½Ρ ΡΡΠ΅ΡΡΠΈΠΊ ΡΡΡΠ»ΠΎΠΊ ΡΠΎΠΆΠ΅ ΡΠ²Π΅Π»ΠΈΡΠΈΡΡΡ Π½Π° Π΅Π΄ΠΈΠ½ΠΈΡΡ ΠΈ ΠΌΡ ΡΠΌΠΎΠΆΠ΅ΠΌ Π·Π°ΠΊΡΡΡΡ ΡΠ°ΠΉΠ»ΠΎΠ²ΡΠΉ Π΄Π΅ΡΠΊΡΠΈΠΏΡΠΎΡ Π² ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ΅-Π·Π°Π³ΡΡΠ·ΡΠΈΠΊΠ΅.
Π§ΡΠΎ ΡΠ»ΡΡΠΈΡΡΡ Π΅ΡΠ»ΠΈ ΠΌΡ ΡΠ΅ΠΏΠ΅ΡΡ Π·Π°Π²Π΅ΡΡΠΈΠΌ ΡΠ°Π±ΠΎΡΡ Π·Π°Π³ΡΡΠ·ΡΠΈΠΊΠ°? ΠΡΠΎ Π·Π°Π²ΠΈΡΠΈΡ ΠΎΡ ΡΠΈΠΏΠ° Π³Π΅Π½Π΅ΡΠ°ΡΠΎΡΠ° ΡΠΎΠ±ΡΡΠΈΠΉ (hook). ΠΡΠ΅ ΡΠ΅ΡΠ΅Π²ΡΠ΅ Ρ ΡΠΊΠΈ Π±ΡΠ΄ΡΡ ΡΡΡΠ΅ΡΡΠ²ΠΎΠ²Π°ΡΡ ΠΏΠΎΡΠ»Π΅ Π·Π°Π²Π΅ΡΡΠ΅Π½ΠΈΡ Π·Π°Π³ΡΡΠ·ΡΠΈΠΊΠ°, ΡΡΠΎ, ΡΠ°ΠΊ Π½Π°Π·ΡΠ²Π°Π΅ΠΌΡΠ΅, Π³Π»ΠΎΠ±Π°Π»ΡΠ½ΡΠ΅ Ρ ΡΠΊΠΈ. Π, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ ΡΡΠ°ΡΡΠΈΡΠΎΠ²ΠΊΠΈ Π±ΡΠ΄ΡΡ ΠΎΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π΅Π½Ρ ΠΏΠΎΡΠ»Π΅ Π·Π°Π²Π΅ΡΡΠ΅Π½ΠΈΡ ΠΏΡΠΎΡΠ΅ΡΡΠ°, ΡΠΎΠ·Π΄Π°Π²ΡΠ΅Π³ΠΎ ΠΈΡ (ΠΈ ΠΏΠΎΡΡΠΎΠΌΡ Π½Π°Π·ΡΠ²Π°ΡΡΡΡ Π»ΠΎΠΊΠ°Π»ΡΠ½ΡΠΌΠΈ, ΠΎΡ Β«local to the processΒ»). Π’Π΅Ρ Π½ΠΈΡΠ΅ΡΠΊΠΈ, Π»ΠΎΠΊΠ°Π»ΡΠ½ΡΠ΅ Ρ ΡΠΊΠΈ Π²ΡΠ΅Π³Π΄Π° ΠΈΠΌΠ΅ΡΡ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠΈΠΉ ΡΠ°ΠΉΠ»ΠΎΠ²ΡΠΉ Π΄Π΅ΡΠΊΡΠΈΠΏΡΠΎΡ Π² ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²Π΅ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ ΠΈ ΠΏΠΎΡΡΠΎΠΌΡ Π·Π°ΠΊΡΡΠ²Π°ΡΡΡΡ Ρ Π·Π°ΠΊΡΡΡΠΈΠ΅ΠΌ ΠΏΡΠΎΡΠ΅ΡΡΠ°, Π° Π³Π»ΠΎΠ±Π°Π»ΡΠ½ΡΠ΅ βΒ Π½Π΅Ρ. ΠΠ° ΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΌ ΡΠΈΡΡΠ½ΠΊΠ΅ Ρ ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ ΠΊΡΠ°ΡΠ½ΡΡ ΠΊΡΠ΅ΡΡΠΈΠΊΠΎΠ² ΡΡΠ°ΡΠ°ΡΡΡ ΠΏΠΎΠΊΠ°Π·Π°ΡΡ ΠΊΠ°ΠΊ Π·Π°Π²Π΅ΡΡΠ΅Π½ΠΈΠ΅ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ-Π·Π°Π³ΡΡΠ·ΡΠΈΠΊΠ° Π²Π»ΠΈΡΠ΅Ρ Π½Π° Π²ΡΠ΅ΠΌΡ ΠΆΠΈΠ·Π½ΠΈ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² Π² ΡΠ»ΡΡΠ°Π΅ Π»ΠΎΠΊΠ°Π»ΡΠ½ΡΡ ΠΈ Π³Π»ΠΎΠ±Π°Π»ΡΠ½ΡΡ Ρ ΡΠΊΠΎΠ².
ΠΠ°ΡΠ΅ΠΌ ΡΡΡΠ΅ΡΡΠ²ΡΠ΅Ρ ΡΠ°Π·Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Π½Π° Π»ΠΎΠΊΠ°Π»ΡΠ½ΡΠ΅ ΠΈ Π³Π»ΠΎΠ±Π°Π»ΡΠ½ΡΠ΅ Ρ ΡΠΊΠΈ? ΠΠ°ΠΏΡΡΠΊ Π½Π΅ΠΊΠΎΡΠΎΡΡΡ ΡΠΈΠΏΠΎΠ² ΡΠ΅ΡΠ΅Π²ΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌ ΠΈΠΌΠ΅Π΅Ρ ΡΠΌΡΡΠ» ΠΈ Π±Π΅Π· userspace, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΏΡΠ΅Π΄ΡΡΠ°Π²ΡΡΠ΅ Π·Π°ΡΠΈΡΡ ΠΎΡ DDoS β Π·Π°Π³ΡΡΠ·ΡΠΈΠΊ ΠΏΡΠΎΠΏΠΈΡΡΠ²Π°Π΅Ρ ΠΏΡΠ°Π²ΠΈΠ»Π° ΠΈ ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠ°Π΅Ρ BPF ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ ΠΊ ΡΠ΅ΡΠ΅Π²ΠΎΠΌΡ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΡ, ΠΏΠΎΡΠ»Π΅ ΡΠ΅Π³ΠΎ Π·Π°Π³ΡΡΠ·ΡΠΈΠΊ ΠΌΠΎΠΆΠ΅Ρ ΠΏΠΎΠΉΡΠΈ ΠΈ ΡΠ±ΠΈΡΡΡΡ. Π‘ Π΄ΡΡΠ³ΠΎΠΉ ΡΡΠΎΡΠΎΠ½Ρ, ΠΏΡΠ΅Π΄ΡΡΠ°Π²ΡΡΠ΅ ΡΠ΅Π±Π΅ ΠΎΡΠ»Π°Π΄ΠΎΡΠ½ΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ ΡΡΠ°ΡΡΠΈΡΠΎΠ²ΠΊΠΈ, ΠΊΠΎΡΠΎΡΡΡ Π²Ρ Π½Π°ΠΏΠΈΡΠ°Π»ΠΈ Π½Π° ΠΊΠΎΠ»Π΅Π½ΠΊΠ΅ Π·Π° Π΄Π΅ΡΡΡΡ ΠΌΠΈΠ½ΡΡ βΒ ΠΏΠΎΡΠ»Π΅ Π΅Π΅ Π·Π°Π²Π΅ΡΡΠ΅Π½ΠΈΡ Π²Π°ΠΌ Π±Ρ Ρ ΠΎΡΠ΅Π»ΠΎΡΡ, ΡΡΠΎΠ±Ρ Π² ΡΠΈΡΡΠ΅ΠΌΠ΅ Π½Π΅ ΠΎΡΡΠ°Π²Π°Π»ΠΎΡΡ ΠΌΡΡΠΎΡΠ°, ΠΈ Π»ΠΎΠΊΠ°Π»ΡΠ½ΡΠ΅ Ρ ΡΠΊΠΈ ΡΡΠΎ Π³Π°ΡΠ°Π½ΡΠΈΡΡΡΡ.
Π‘ Π΄ΡΡΠ³ΠΎΠΉ ΡΡΠΎΡΠΎΠ½Ρ, ΠΏΡΠ΅Π΄ΡΡΠ°Π²ΡΡΠ΅, ΡΡΠΎ Π²Ρ Ρ
ΠΎΡΠΈΡΠ΅ ΠΏΠΎΠ΄ΡΠΎΠ΅Π΄ΠΈΠ½ΠΈΡΡΡΡ ΠΊ tracepoint Π² ΡΠ΄ΡΠ΅ ΠΈ ΡΠΎΠ±ΠΈΡΠ°ΡΡ ΡΡΠ°ΡΠΈΡΡΠΈΠΊΡ Π² ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ ΠΌΠ½ΠΎΠ³ΠΈΡ
Π»Π΅Ρ. Π ΡΡΠΎΠΌ ΡΠ»ΡΡΠ°Π΅ Π²Π°ΠΌ Π±Ρ Ρ
ΠΎΡΠ΅Π»ΠΎΡΡ Π·Π°Π²Π΅ΡΡΠΈΡΡ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΡΠΊΡΡ ΡΠ°ΡΡΡ ΠΈ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°ΡΡΡΡ ΠΊ ΡΡΠ°ΡΠΈΡΡΠΈΠΊΠ΅ Π²ΡΠ΅ΠΌΡ ΠΎΡ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ. Π’Π°ΠΊΡΡ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΠ΅Ρ ΡΠ°ΠΉΠ»ΠΎΠ²Π°Ρ ΡΠΈΡΡΠ΅ΠΌΠ° bpf. ΠΡΠΎ ΠΏΡΠ΅Π²Π΄ΠΎ-ΡΠ°ΠΉΠ»ΠΎΠ²Π°Ρ ΡΠΈΡΡΠ΅ΠΌΠ°, ΡΡΡΠ΅ΡΡΠ²ΡΡΡΠ°Ρ ΡΠΎΠ»ΡΠΊΠΎ Π² ΠΏΠ°ΠΌΡΡΠΈ, ΠΊΠΎΡΠΎΡΠ°Ρ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΡΠΎΠ·Π΄Π°Π²Π°ΡΡ ΡΠ°ΠΉΠ»Ρ, ΡΡΡΠ»Π°ΡΡΠΈΠ΅ΡΡ Π½Π° ΠΎΠ±ΡΠ΅ΠΊΡΡ BPF ΠΈ, ΡΠ΅ΠΌ ΡΠ°ΠΌΡΠΌ, ΡΠ²Π΅Π»ΠΈΡΠΈΠ²Π°ΡΡΠΈΠ΅ refcount
ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ². ΠΠΎΡΠ»Π΅ ΡΡΠΎΠ³ΠΎ Π·Π°Π³ΡΡΠ·ΡΠΈΠΊ ΠΌΠΎΠΆΠ΅Ρ Π·Π°Π²Π΅ΡΡΠΈΡΡ ΡΠ°Π±ΠΎΡΡ, Π° ΡΠΎΠ·Π΄Π°Π½Π½ΡΠ΅ ΠΈΠΌ ΠΎΠ±ΡΠ΅ΠΊΡΡ ΠΎΡΡΠ°Π½ΡΡΡΡ ΠΆΠΈΠ²Ρ.
Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΡΠ°ΠΉΠ»ΠΎΠ² Π² bpffs, ΡΡΡΠ»Π°ΡΡΠΈΡ ΡΡ Π½Π° ΠΎΠ±ΡΠ΅ΠΊΡΡ BPF Π½Π°Π·ΡΠ²Π°Π΅ΡΡΡ Β«Π·Π°ΠΊΡΠ΅ΠΏΠ»Π΅Π½ΠΈΠ΅Β» (Β«pinΒ», ΠΊΠ°ΠΊ Π² ΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΉ ΡΡΠ°Π·Π΅: Β«process can pin a BPF program or mapΒ»). Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΡΠ°ΠΉΠ»ΠΎΠ²ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² Π΄Π»Ρ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² 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
. ΠΡΠΈ ΡΡΠΎΠΌ Π²ΡΠ΅ Π°ΠΊΡΠΈΠ²Π½ΡΠ΅ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΡ ΡΡΠ°ΡΠΎΠΉ Π²Π΅ΡΡΠΈΠΈ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ Π·Π°ΠΊΠΎΠ½ΡΠ°Ρ ΡΠ²ΠΎΡ ΡΠ°Π±ΠΎΡΡ, Π° Π½ΠΎΠ²ΡΠ΅ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ ΡΠΎΠ±ΡΡΠΈΠΉ Π±ΡΠ΄ΡΡ ΡΠΎΠ·Π΄Π°Π²Π°ΡΡΡΡ ΡΠΆΠ΅ ΠΈΠ· Π½ΠΎΠ²ΠΎΠΉ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ, ΠΈ Β«Π°ΡΠΎΠΌΠ°ΡΠ½ΠΎΡΡΡΒ» ΠΎΠ·Π½Π°ΡΠ°Π΅Ρ Π·Π΄Π΅ΡΡ, ΡΡΠΎ Π½ΠΈ ΠΎΠ΄Π½ΠΎ ΡΠΎΠ±ΡΡΠΈΠ΅ Π½Π΅ Π±ΡΠ΄Π΅Ρ ΠΏΡΠΎΠΏΡΡΠ΅Π½ΠΎ.
ΠΡΠΈΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌ ΠΊ ΠΈΡΡΠΎΡΠ½ΠΈΠΊΠ°ΠΌ ΡΠΎΠ±ΡΡΠΈΠΉ
Π ΡΡΠΎΠΉ ΡΡΠ°ΡΡΠ΅ ΠΌΡ Π½Π΅ Π±ΡΠ΄Π΅ΠΌ ΠΎΡΠ΄Π΅Π»ΡΠ½ΠΎ ΠΎΠΏΠΈΡΡΠ²Π°ΡΡ ΠΏΠΎΠ΄ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌ ΠΊ ΠΈΡΡΠΎΡΠ½ΠΈΠΊΠ°ΠΌ ΡΠΎΠ±ΡΡΠΈΠΉ, ΡΠ°ΠΊ ΠΊΠ°ΠΊ ΡΡΠΎ ΠΈΠΌΠ΅Π΅Ρ ΡΠΌΡΡΠ» ΠΈΠ·ΡΡΠ°ΡΡ Π² ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ΅ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΠΎΠ³ΠΎ ΡΠΈΠΏΠ° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ. Π‘ΠΌ.
Π£ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ ΠΎΠ±ΡΠ΅ΠΊΡΠ°ΠΌΠΈ ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ ΡΠΈΡΡΠ΅ΠΌΠ½ΠΎΠ³ΠΎ Π²ΡΠ·ΠΎΠ²Π° bpf
ΠΡΠΎΠ³ΡΠ°ΠΌΠΌΡ BPF
ΠΡΠ΅ ΠΎΠ±ΡΠ΅ΠΊΡΡ BPF ΡΠΎΠ·Π΄Π°ΡΡΡΡ ΠΈ ΡΠΏΡΠ°Π²Π»ΡΡΡΡΡ ΠΈΠ· ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²Π° ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ ΡΠΈΡΡΠ΅ΠΌΠ½ΠΎΠ³ΠΎ Π²ΡΠ·ΠΎΠ²Π° bpf
, ΠΈΠΌΠ΅ΡΡΠ΅Π³ΠΎ ΡΠ»Π΅Π΄ΡΡΡΠΈΠΉ ΠΏΡΠΎΡΠΎΡΠΈΠΏ:
#include <linux/bpf.h>
int bpf(int cmd, union bpf_attr *attr, unsigned int size);
ΠΠ΄Π΅ΡΡ ΠΊΠΎΠΌΠ°Π½Π΄Π° cmd
β ΡΡΠΎ ΠΎΠ΄Π½ΠΎ ΠΈΠ· Π·Π½Π°ΡΠ΅Π½ΠΈΠΉ ΡΠΈΠΏΠ° enum bpf_cmd
attr
βΒ ΡΠΊΠ°Π·Π°ΡΠ΅Π»Ρ Π½Π° ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ Π΄Π»Ρ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΠΎΠΉ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ ΠΈ size
β ΡΠ°Π·ΠΌΠ΅Ρ ΠΎΠ±ΡΠ΅ΠΊΡΠ° ΠΏΠΎ ΡΠΊΠ°Π·Π°ΡΠ΅Π»Ρ, Ρ.Π΅. ΠΎΠ±ΡΡΠ½ΠΎ ΡΡΠΎ sizeof(*attr)
. Π ΡΠ΄ΡΠ΅ 5.8 ΡΠΈΡΡΠ΅ΠΌΠ½ΡΠΉ Π²ΡΠ·ΠΎΠ² bpf
ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅Ρ 34 ΡΠ°Π·Π»ΠΈΡΠ½ΡΡ
ΠΊΠΎΠΌΠ°Π½Π΄Ρ, Π° union bpf_attr
Π·Π°Π½ΠΈΠΌΠ°Π΅Ρ 200 ΡΡΡΠΎΡΠ΅ΠΊ. ΠΠΎ Π½Π°Ρ Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΡΡΠΎ ΠΏΡΠ³Π°ΡΡ, ΡΠ°ΠΊ ΠΊΠ°ΠΊ ΠΌΡ Π±ΡΠ΄Π΅ΠΌ Π·Π½Π°ΠΊΠΎΠΌΠΈΡΡΡΡ Ρ ΠΊΠΎΠΌΠ°Π½Π΄Π°ΠΌΠΈ ΠΈ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠ°ΠΌΠΈ Π½Π° ΠΏΡΠΎΡΡΠΆΠ΅Π½ΠΈΠΈ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΡ
ΡΡΠ°ΡΠ΅ΠΉ.
ΠΠ°ΡΠ½Π΅ΠΌ ΠΌΡ Ρ ΠΊΠΎΠΌΠ°Π½Π΄Ρ BPF_PROG_LOAD
, ΠΊΠΎΡΠΎΡΠ°Ρ ΡΠΎΠ·Π΄Π°Π΅Ρ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ BPF β Π±Π΅ΡΠ΅Ρ Π½Π°Π±ΠΎΡ ΠΈΠ½ΡΡΡΡΠΊΡΠΈΠΉ BPF ΠΈ Π·Π°Π³ΡΡΠΆΠ°Π΅Ρ Π΅Π³ΠΎ Π² ΡΠ΄ΡΠΎ. Π ΠΌΠΎΠΌΠ΅Π½Ρ Π·Π°Π³ΡΡΠ·ΠΊΠΈ Π·Π°ΠΏΡΡΠΊΠ°Π΅ΡΡΡ verifier, Π° ΠΏΠΎΡΠΎΠΌ JIT compiler ΠΈ, ΠΏΠΎΡΠ»Π΅ ΡΡΠΏΠ΅ΡΠ½ΠΎΠ³ΠΎ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ, ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΡΡΡ ΡΠ°ΠΉΠ»ΠΎΠ²ΡΠΉ Π΄Π΅ΡΠΊΡΠΈΠΏΡΠΎΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ. ΠΡ Π²ΠΈΠ΄Π΅Π»ΠΈ ΡΡΠΎ Ρ Π½ΠΈΠΌ ΠΏΡΠΎΠΈΡΡ
ΠΎΠ΄ΠΈΡ Π΄Π°Π»ΡΡΠ΅ Π² ΠΏΡΠ΅Π΄ΡΠ΄ΡΡΠ΅ΠΌ ΡΠ°Π·Π΄Π΅Π»Π΅
Π‘Π΅ΠΉΡΠ°Ρ ΠΌΡ Π½Π°ΠΏΠΈΡΠ΅ΠΌ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΡΠΊΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ, ΠΊΠΎΡΠΎΡΠ°Ρ Π±ΡΠ΄Π΅Ρ Π·Π°Π³ΡΡΠΆΠ°ΡΡ ΠΏΡΠΎΡΡΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ 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
ΡΠ΅ΠΉ Π³Π»ΠΎΠ±Π°Π»ΡΠ½ΡΠΉ ID ΡΠ°Π²Π΅Π½ 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 ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΎΡΠΎΠΌ, ΠΊΠΎΠ½Π΅ΡΠ½ΠΎ, Π½ΡΠΆΠ½Ρ.
Maps
ΠΡΠΎΠ³ΡΠ°ΠΌΠΌΡ BPF ΠΌΠΎΠ³ΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΡΡΡΠΊΡΡΡΠΈΡΠΎΠ²Π°Π½Π½ΡΠ΅ ΠΎΠ±Π»Π°ΡΡΠΈ ΠΏΠ°ΠΌΡΡΠΈ, Π΄ΠΎΡΡΡΠΏΠ½ΡΠ΅ ΠΊΠ°ΠΊ Π΄ΡΡΠ³ΠΈΠΌ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ°ΠΌ BPF, ΡΠ°ΠΊ ΠΈ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ°ΠΌ ΠΈΠ· ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²Π° ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ. ΠΡΠΈ ΠΎΠ±ΡΠ΅ΠΊΡΡ Π½Π°Π·ΡΠ²Π°ΡΡΡΡ maps ΠΈ Π² ΡΡΠΎΠΌ ΡΠ°Π·Π΄Π΅Π»Π΅ ΠΌΡ ΠΏΠΎΠΊΠ°ΠΆΠ΅ΠΌ ΠΊΠ°ΠΊ ΡΠΏΡΠ°Π²Π»ΡΡΡ ΠΈΠΌΠΈ ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ ΡΠΈΡΡΠ΅ΠΌΠ½ΠΎΠ³ΠΎ Π²ΡΠ·ΠΎΠ²Π° bpf
.
Π‘ΡΠ°Π·Ρ ΡΠΊΠ°ΠΆΠ΅ΠΌ, ΡΡΠΎ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΠΈ maps Π½Π΅ ΠΎΠ³ΡΠ°Π½ΠΈΡΠΈΠ²Π°ΡΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ Π΄ΠΎΡΡΡΠΏΠΎΠΌ ΠΊ ΠΎΠ±ΡΠ΅ΠΉ ΠΏΠ°ΠΌΡΡΠΈ. Π‘ΡΡΠ΅ΡΡΠ²ΡΡΡ ΠΌΠ°ΠΏΡ ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½ΠΎΠ³ΠΎ Π½Π°Π·Π½Π°ΡΠ΅Π½ΠΈΡ, ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΠΈΠ΅, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΡΠΊΠ°Π·Π°ΡΠ΅Π»ΠΈ Π½Π° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ BPF ΠΈΠ»ΠΈ ΡΠΊΠ°Π·Π°ΡΠ΅Π»ΠΈ Π½Π° ΡΠ΅ΡΠ΅Π²ΡΠ΅ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΡ, ΠΌΠ°ΠΏΡ Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ perf events ΠΈ Ρ.ΠΏ. ΠΠ΄Π΅ΡΡ ΠΌΡ ΠΎ Π½ΠΈΡ
Π³ΠΎΠ²ΠΎΡΠΈΡΡ Π½Π΅ Π±ΡΠ΄Π΅ΠΌ, ΡΡΠΎΠ±Ρ Π½Π΅ ΠΏΡΡΠ°ΡΡ ΡΠΈΡΠ°ΡΠ΅Π»Ρ. ΠΡΠΎΠΌΠ΅ ΡΡΠΎΠ³ΠΎ, ΠΌΡ ΠΈΠ³Π½ΠΎΡΠΈΡΡΠ΅ΠΌ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ ΡΠΈΠ½Ρ
ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΠΈ, ΡΠ°ΠΊ ΠΊΠ°ΠΊ ΡΡΠΎ Π½Π΅ Π²Π°ΠΆΠ½ΠΎ Π΄Π»Ρ Π½Π°ΡΠΈΡ
ΠΏΡΠΈΠΌΠ΅ΡΠΎΠ². ΠΠΎΠ»Π½ΡΠΉ ΡΠΏΠΈΡΠΎΠΊ Π΄ΠΎΡΡΡΠΏΠ½ΡΡ
ΡΠΈΠΏΠΎΠ² ΠΌΠ°ΠΏΠΎΠ² ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡΠΈ Π² <linux/bpf.h>
BPF_MAP_TYPE_HASH
.
ΠΡΠ»ΠΈ Π²Ρ ΡΠΎΠ·Π΄Π°Π΅ΡΠ΅ Ρ
ΡΡ-ΡΠ°Π±Π»ΠΈΡΡ, ΡΠΊΠ°ΠΆΠ΅ΠΌ, Π² C++, Π²Ρ ΡΠΊΠ°ΠΆΠ΅ΡΠ΅ unordered_map<int,long> woo
, ΡΡΠΎ ΠΏΠΎ-ΡΡΡΡΠΊΠΈ ΠΎΠ·Π½Π°ΡΠ°Π΅Ρ Β«ΠΌΠ½Π΅ Π½ΡΠΆΠ½Π° ΡΠ°Π±Π»ΠΈΡΠ° woo
Π½Π΅ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½Π½ΠΎΠ³ΠΎ ΡΠ°Π·ΠΌΠ΅ΡΠ°, Ρ ΠΊΠΎΡΠΎΡΠΎΠΉ ΠΊΠ»ΡΡΠΈ ΠΈΠΌΠ΅ΡΡ ΡΠΈΠΏ int
, Π° Π·Π½Π°ΡΠ΅Π½ΠΈΡ β ΡΠΈΠΏ long
Β». ΠΠ»Ρ ΡΠΎΠ³ΠΎ, ΡΡΠΎΠ±Ρ ΡΠΎΠ·Π΄Π°ΡΡ Ρ
ΡΡ-ΡΠ°Π±Π»ΠΈΡΡ BPF ΠΌΡ Π΄ΠΎΠ»ΠΆΠ½Ρ ΡΠ΄Π΅Π»Π°ΡΡ ΠΏΡΠΈΠΌΠ΅ΡΠ½ΠΎ ΡΠΎ ΠΆΠ΅ ΡΠ°ΠΌΠΎΠ΅, Ρ ΠΏΠΎΠΏΡΠ°Π²ΠΊΠΎΠΉ Π½Π° ΡΠΎ, ΡΡΠΎ Π½Π°ΠΌ ΠΏΡΠΈΠ΄Π΅ΡΡΡ ΡΠΊΠ°Π·Π°ΡΡ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡΠ½ΡΠΉ ΡΠ°Π·ΠΌΠ΅Ρ ΡΠ°Π±Π»ΠΈΡΡ, Π° Π²ΠΌΠ΅ΡΡΠΎ ΡΠΈΠΏΠΎΠ² ΠΊΠ»ΡΡΠ΅ΠΉ ΠΈ Π·Π½Π°ΡΠ΅Π½ΠΈΠΉ Π½Π°ΠΌ Π½ΡΠΆΠ½ΠΎ ΡΠΊΠ°Π·Π°ΡΡ ΠΈΡ
ΡΠ°Π·ΠΌΠ΅ΡΡ Π² Π±Π°ΠΉΡΠ°Ρ
. ΠΠ»Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΠΌΠ°ΠΏΠΎΠ² ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ ΠΊΠΎΠΌΠ°Π½Π΄Π° BPF_MAP_CREATE
ΡΠΈΡΡΠ΅ΠΌΠ½ΠΎΠ³ΠΎ Π²ΡΠ·ΠΎΠ²Π° bpf
. ΠΠ°Π²Π°ΠΉΡΠ΅ ΠΏΠΎΡΠΌΠΎΡΡΠΈΠΌ Π½Π° Π±ΠΎΠ»Π΅Π΅-ΠΌΠ΅Π½Π΅Π΅ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡΠ½ΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ, ΠΊΠΎΡΠΎΡΠ°Ρ ΡΠΎΠ·Π΄Π°Π΅Ρ map. ΠΠΎΡΠ»Π΅ ΠΏΡΠ΅Π΄ΡΠ΄ΡΡΠ΅ΠΉ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ, Π·Π°Π³ΡΡΠΆΠ°ΡΡΠ΅ΠΉ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ 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)
.
Π’Π΅ΠΏΠ΅ΡΡ ΠΎΡΠΏΡΠ°Π²ΠΈΠΌ Π½Π°ΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ Π² background ΠΈΠ»ΠΈ ΠΎΡΠΊΡΠΎΠ΅ΠΌ Π΄ΡΡΠ³ΠΎΠΉ ΡΠ΅ΡΠΌΠΈΠ½Π°Π» ΠΈ ΠΏΠΎΡΠΌΠΎΡΡΠΈΠΌ Π½Π° Π½Π°Ρ ΠΎΠ±ΡΠ΅ΠΊΡ ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ ΡΡΠΈΠ»ΠΈΡΡ bpftool
(ΠΌΡ ΠΌΠΎΠΆΠ΅ΠΌ ΠΎΡΠ»ΠΈΡΠΈΡΡ Π½Π°Ρ map ΠΎΡ Π΄ΡΡΠ³ΠΈΡ
ΠΏΠΎ Π΅Π³ΠΎ ΠΈΠΌΠ΅Π½ΠΈ):
$ sudo bpftool map
...
114: hash name woo flags 0x0
key 4B value 4B max_entries 4 memlock 4096B
...
Π§ΠΈΡΠ»ΠΎ 114 β ΡΡΠΎ Π³Π»ΠΎΠ±Π°Π»ΡΠ½ΡΠΉ ID Π½Π°ΡΠ΅Π³ΠΎ ΠΎΠ±ΡΠ΅ΠΊΡΠ°. ΠΡΠ±Π°Ρ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ° Π² ΡΠΈΡΡΠ΅ΠΌΠ΅ ΠΌΠΎΠΆΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΡΠΎΡ ID, ΡΡΠΎΠ±Ρ ΠΎΡΠΊΡΡΡΡ ΡΠΆΠ΅ ΡΡΡΠ΅ΡΡΠ²ΡΡΡΠΈΠΉ map ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ ΠΊΠΎΠΌΠ°Π½Π΄Ρ 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
Π‘Π½Π°ΡΠ°Π»Π° ΠΌΡ ΠΎΡΠΊΡΡΠ»ΠΈ ΠΌΠ°ΠΏ ΠΏΠΎ Π΅Π³ΠΎ Π³Π»ΠΎΠ±Π°Π»ΡΠ½ΠΎΠΌΡ ID ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ ΠΊΠΎΠΌΠ°Π½Π΄Ρ 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
: ΠΎΡΠΊΡΡΡΡ ΡΡΡΠ΅ΡΡΠ²ΡΡΡΠΈΠΉ ΠΌΠ°ΠΏ ΠΏΠΎ Π΅Π³ΠΎ Π³Π»ΠΎΠ±Π°Π»ΡΠ½ΠΎΠΌΡ IDBPF_MAP_LOOKUP_AND_DELETE_ELEM
: Π°ΡΠΎΠΌΠ°ΡΠ½ΠΎ ΠΎΠ±Π½ΠΎΠ²ΠΈΡΡ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΠΎΠ±ΡΠ΅ΠΊΡΠ° ΠΈ Π²Π΅ΡΠ½ΡΡΡ ΡΡΠ°ΡΠΎΠ΅BPF_MAP_FREEZE
: ΡΠ΄Π΅Π»Π°ΡΡ ΠΌΠ°ΠΏ Π½Π΅ΠΈΠ·ΠΌΠ΅Π½ΡΠ΅ΠΌΡΠΌ ΠΈΠ· userspace (ΡΡΡ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΡ Π½Π΅Π»ΡΠ·Ρ ΠΎΡΠΌΠ΅Π½ΠΈΡΡ)BPF_MAP_LOOKUP_BATCH
,BPF_MAP_LOOKUP_AND_DELETE_BATCH
,BPF_MAP_UPDATE_BATCH
,BPF_MAP_DELETE_BATCH
: ΠΌΠ°ΡΡΠΎΠ²ΡΠ΅ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ,BPF_MAP_LOOKUP_AND_DELETE_BATCH
βΒ ΡΡΠΎ Π΅Π΄ΠΈΠ½ΡΡΠ²Π΅Π½Π½ΡΠΉ Π½Π°Π΄Π΅ΠΆΠ½ΡΠΉ ΡΠΏΠΎΡΠΎΠ± ΠΏΡΠΎΡΠΈΡΠ°ΡΡ ΠΈ ΠΎΠ±Π½ΡΠ»ΠΈΡΡ Π²ΡΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΡ ΠΈΠ· ΠΌΠ°ΠΏΠ°
ΠΠ΅ Π²ΡΠ΅ ΠΈΠ· ΡΡΠΈΡ ΠΊΠΎΠΌΠ°Π½Π΄ ΡΠ°Π±ΠΎΡΠ°ΡΡ Π΄Π»Ρ Π²ΡΠ΅Ρ ΡΠΈΠΏΠΎΠ² ΠΌΠ°ΠΏΠΎΠ², Π½ΠΎ Π²ΠΎΠΎΠ±ΡΠ΅ ΡΠ°Π±ΠΎΡΠ° Ρ Π΄ΡΡΠ³ΠΈΠΌΠΈ ΡΠΈΠΏΠ°ΠΌΠΈ maps ΠΈΠ· ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²Π° ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ Π²ΡΠ³Π»ΡΠ΄ΠΈΡ ΡΠΎΡΠ½ΠΎ ΡΠ°ΠΊ ΠΆΠ΅, ΠΊΠ°ΠΊ ΠΈ ΡΠ°Π±ΠΎΡΠ° Ρ Ρ ΡΡ-ΡΠ°Π±Π»ΠΈΡΠ°ΠΌΠΈ.
ΠΠ»Ρ ΠΏΠΎΡΡΠ΄ΠΊΠ°, Π΄Π°Π²Π°ΠΉΡΠ΅ Π·Π°Π²Π΅ΡΡΠΈΠΌ Π½Π°ΡΠΈ ΡΠΊΡΠΏΠ΅ΡΠΈΠΌΠ΅Π½ΡΡ Ρ Ρ ΡΡ-ΡΠ°Π±Π»ΠΈΡΠ΅ΠΉ. ΠΠΎΠΌΠ½ΠΈΡΠ΅, ΡΡΠΎ ΠΌΡ ΡΠΎΠ·Π΄Π°Π»ΠΈ ΡΠ°Π±Π»ΠΈΡΡ, Π² ΠΊΠΎΡΠΎΡΠΎΠΉ ΠΌΠΎΠΆΠ΅Ρ ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΡΡΡ Π΄ΠΎ ΡΠ΅ΡΡΡΠ΅Ρ ΠΊΠ»ΡΡΠ΅ΠΉ? ΠΠΎΠ±Π°Π²ΠΈΠΌ Π΅ΡΠ΅ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΠ»Π΅ΠΌΠ΅Π½ΡΠΎΠ²:
$ 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
, ΠΈ Ρ.ΠΏ.) ΠΆΠΈΡΡ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ. ΠΠ΄Π½ΠΎΠΉ ΠΈΠ· killer-ΡΠΈΡ ΠΏΡΠΎΠ΅ΠΊΡΠ° libbpf
ΡΠ²Π»ΡΠ΅ΡΡΡ BPF CO-RE (Compile Once, Run Everywhere) βΒ ΠΏΡΠΎΠ΅ΠΊΡ, ΠΊΠΎΡΠΎΡΡΠΉ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΠΏΠΈΡΠ°ΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ BPF, ΠΏΠ΅ΡΠ΅Π½ΠΎΡΠΈΠΌΡΠ΅ Ρ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΡΠ΄ΡΠ° Π½Π° Π΄ΡΡΠ³ΠΎΠ΅, Ρ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡΡ Π·Π°ΠΏΡΡΠΊΠ° Π½Π° ΡΠ°Π·Π½ΡΡ
API (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΊΠΎΠ³Π΄Π° ΡΡΡΡΠΊΡΡΡΠ° ΡΠ΄ΡΠ° ΠΌΠ΅Π½ΡΠ΅ΡΡΡ ΠΎΡ Π²Π΅ΡΡΠΈΠΈ ΠΊ Π²Π΅ΡΡΠΈΠΈ). ΠΠ»Ρ ΡΠΎΠ³ΠΎ, ΡΡΠΎΠ±Ρ ΠΈΠΌΠ΅ΡΡ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ ΡΠ°Π±ΠΎΡΠ°ΡΡ Ρ CO-RE, Π²Π°ΡΠ΅ ΡΠ΄ΡΠΎ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±ΡΡΡ ΡΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡΠΎΠ²Π°Π½ΠΎ Ρ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠΎΠΉ 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]
. ΠΠ΄Π½Π°ΠΊΠΎ Π΄Π»Ρ Π½ΡΠΆΠ΄ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ, ΠΆΠΈΠ²ΡΡΠΈΡ
Π·Π° ΠΏΡΠ΅Π΄Π΅Π»Π°ΠΌΠΈ ΡΠ΄ΡΠ°, ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅ΡΡΡ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΠΉ ΡΠ΅ΠΏΠΎΠ·ΠΈΡΠΎΡΠΈΠΉ
Π Π΄Π°Π½Π½ΠΎΠΌ ΡΠ°Π·Π΄Π΅Π»Π΅ ΠΌΡ ΠΏΠΎΡΠΌΠΎΡΡΠΈΠΌ Π½Π° ΡΠΎ, ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ ΡΠΎΠ·Π΄Π°ΡΡ ΠΏΡΠΎΠ΅ΠΊΡ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡΠΈΠΉ libbpf
, Π½Π°ΠΏΠΈΡΠ΅ΠΌ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ (Π±ΠΎΠ»Π΅Π΅-ΠΌΠ΅Π½Π΅Π΅ Π±Π΅ΡΡΠΌΡΡΠ»Π΅Π½Π½ΡΡ
) ΡΠ΅ΡΡΠΎΠ²ΡΡ
ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌ ΠΈ ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎ ΡΠ°Π·Π±Π΅ΡΠ΅ΠΌ ΠΊΠ°ΠΊ Π²ΡΠ΅ ΡΡΠΎ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ. ΠΡΠΎ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ Π½Π°ΠΌ Π² ΡΠ»Π΅Π΄ΡΡΡΠΈΡ
ΡΠ°Π·Π΄Π΅Π»Π°Ρ
ΠΏΡΠΎΡΠ΅ ΠΎΠ±ΡΡΡΠ½ΠΈΡΡ, ΠΊΠ°ΠΊ ΠΈΠΌΠ΅Π½Π½ΠΎ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ BPF Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΡΡΡ Ρ maps, kernel helpers, BTF, ΠΈ Ρ.ΠΏ.
ΠΠ±ΡΡΠ½ΠΎ ΠΏΡΠΎΠ΅ΠΊΡΡ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡΠΈΠ΅ libbpf
Π΄ΠΎΠ±Π°Π²Π»ΡΡΡ Π³ΠΈΡΡ
Π°Π±ΠΎΠ²ΡΠΊΠΈΠΉ ΡΠ΅ΠΏΠΎΠ·ΠΈΡΠΎΡΠΈΠΉ Π² ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ git submodule, ΡΠ΄Π΅Π»Π°Π΅ΠΌ ΡΡΠΎ ΠΈ ΠΌΡ:
$ 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)
. Π‘Π°ΠΌΠ° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ° BPF Π½Π° 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 (ΡΡΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ½ΠΈΠΌΠ°ΡΡ ΠΈ Π±ΡΠΊΠ²Π°Π»ΡΠ½ΠΎ, ΡΠ°ΠΊ ΠΊΠ°ΠΊ Daniel Borkman β ΠΎΠ΄ΠΈΠ½ ΠΈΠ· ΡΠΎΠ·Π΄Π°ΡΠ΅Π»Π΅ΠΉ ΠΈ ΠΌΠ°Π½ΡΠ΅ΠΉΠ½Π΅ΡΠΎΠ² BPF βΒ ΡΠ²Π΅ΠΉΡΠ°ΡΠ΅Ρ):
$ bpftool gen skeleton xdp-simple.bpf.o > xdp-simple.skel.h
Π ΡΠ°ΠΉΠ»Π΅ xdp-simple.skel.h
ΡΠΎΠ΄Π΅ΡΠΆΠΈΡΡΡ Π±ΠΈΠ½Π°ΡΠ½ΡΠΉ ΠΊΠΎΠ΄ Π½Π°ΡΠ΅ΠΉ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ ΠΈ ΡΡΠ½ΠΊΡΠΈΠΈ Π΄Π»Ρ ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ βΒ Π·Π°Π³ΡΡΠ·ΠΊΠΈ, ΠΏΡΠΈΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ, ΡΠ΄Π°Π»Π΅Π½ΠΈΡ Π½Π°ΡΠ΅Π³ΠΎ ΠΎΠ±ΡΠ΅ΠΊΡΠ°. Π Π½Π°ΡΠ΅ΠΌ ΠΏΡΠΎΡΡΠΎΠΌ ΡΠ»ΡΡΠ°Π΅ ΡΡΠΎ Π²ΡΠ³Π»ΡΠ΄ΠΈΡ ΠΊΠ°ΠΊ overkill, Π½ΠΎ ΡΡΠΎ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ ΠΈ Π² ΡΠ»ΡΡΠ°Π΅, ΠΊΠΎΠ³Π΄Π° ΠΎΠ±ΡΠ΅ΠΊΡΠ½ΡΠΉ ΡΠ°ΠΉΠ» ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ ΠΌΠ½ΠΎΠΆΠ΅ΡΡΠ²ΠΎ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌ 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 Π½Π°Ρ
ΠΎΠ΄ΡΡΡΡ ΠΈ Π΄ΡΡΠ³ΠΈΠ΅ ΡΠ΅ΠΊΡΠΈΠΈ βΒ data, readonly data, ΠΎΡΠ»Π°Π΄ΠΎΡΠ½Π°Ρ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ, Π»ΠΈΡΠ΅Π½Π·ΠΈΡ ΠΈ Ρ.ΠΏ.), Π° ΠΏΠΎΡΠΎΠΌ Π·Π°Π³ΡΡΠΆΠ°Π΅Ρ Π² ΡΠ΄ΡΠΎ ΠΏΠΎΡΡΠ΅Π΄ΡΡΠ²ΠΎΠΌ ΡΠΈΡΡΠ΅ΠΌΠ½ΠΎΠ³ΠΎ Π²ΡΠ·ΠΎΠ²Π° 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)
ΠΈ ΡΠ΄Π°ΠΌΠΏΠΈΠΌ (ΠΌΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ ΡΠΎΠΊΡΠ°ΡΠ΅Π½Π½ΡΠΉ Π²ΠΈΠ΄ ΠΊΠΎΠΌΠ°Π½Π΄Ρ 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
.
Kernel Helpers
ΠΡΠΎΠ³ΡΠ°ΠΌΠΌΡ BPF ΠΌΠΎΠ³ΡΡ Π·Π°ΠΏΡΡΠΊΠ°ΡΡ Β«Π²Π½Π΅ΡΠ½ΠΈΠ΅Β» ΡΡΠ½ΠΊΡΠΈΠΈ βΒ kernel helpers. ΠΡΠΈ ΡΡΠ½ΠΊΡΠΈΠΈ-ΠΏΠΎΠΌΠΎΡΠ½ΠΈΠΊΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ°ΠΌ BPF ΠΏΠΎΠ»ΡΡΠ°ΡΡ Π΄ΠΎΡΡΡΠΏ ΠΊ ΡΡΡΡΠΊΡΡΡΠ°ΠΌ ΡΠ΄ΡΠ°, ΡΠΏΡΠ°Π²Π»ΡΡΡ maps, Π° ΡΠ°ΠΊΠΆΠ΅ ΠΎΠ±ΡΠ°ΡΡΡΡ Ρ Β«ΡΠ΅Π°Π»ΡΠ½ΡΠΌ ΠΌΠΈΡΠΎΠΌΒ» βΒ ΡΠΎΠ·Π΄Π°Π²Π°ΡΡ perf events, ΡΠΏΡΠ°Π²Π»ΡΡΡ ΠΎΠ±ΠΎΡΡΠ΄ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΏΠ΅ΡΠ΅Π½Π°ΠΏΡΠ°Π²Π»ΡΡΡ ΠΏΠ°ΠΊΠ΅ΡΡ) ΠΈ Ρ.ΠΏ.
ΠΡΠΈΠΌΠ΅Ρ: 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
, ΠΊΠΎΡΠΎΡΠ°Ρ ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ-ΠΏΠΎΠΌΠΎΡΠ½ΠΈΠΊΠ°, ΠΏΠΎΠ½ΡΡΠ½ΠΎΠ΅ verifier:
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
, ΠΊΠΎΡΠΎΡΠ°Ρ ΠΏΠΎ ID ΡΡΠ½ΠΊΡΠΈΠΈ-ΠΏΠΎΠΌΠΎΡΠ½ΠΈΠΊΠ° ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅Ρ, ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅Ρ Π»ΠΈ 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
, ΠΊΠΎΡΠΎΡΠ°Ρ Π±ΡΠ΄Π΅Ρ Π·Π°ΠΏΡΡΠΊΠ°ΡΡΡΡ verifier ΠΊΠ°ΠΆΠ΄ΡΠΉ ΡΠ°Π·, ΠΊΠ°ΠΊ ΠΎΠ½ Π²ΡΡΡΠ΅ΡΠΈΡ Π²ΡΠ·ΠΎΠ² ΠΊΠ°ΠΊΠΎΠΉ-ΡΠΎ ΡΡΠ½ΠΊΡΠΈΠΈ Π²Π½ΡΡΡΠΈ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ 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
Π² ΡΠ΄ΡΠ΅ Π³Π΅Π½Π΅ΡΠΈΡΡΠ΅ΡΡΡ ΡΠΊΡΠΈΠΏΡΠΎΠΌ, ΠΏΠΎΡΡΠΎΠΌΡ Β«ΠΌΠ°Π³ΠΈΡΠ΅ΡΠΊΠΈΠ΅Β» ΡΠΈΡΠ»Π° βΒ ΡΡΠΎ ok). ΠΡΠ° ΡΡΠ½ΠΊΡΠΈΡ Π½Π΅ ΠΏΡΠΈΠ½ΠΈΠΌΠ°Π΅Ρ Π°ΡΠ³ΡΠΌΠ΅Π½ΡΠΎΠ² ΠΈ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΡΠΈΠΏΠ° __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-ΡΠΎΠ³Π»Π°ΡΠ΅Π½ΠΈΡ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌΠΎΠΌΡ verifier, ΡΡΠΎ ΠΈ Π΅ΡΡΡ Π²ΡΠ·ΠΎΠ² ΡΡΠ½ΠΊΡΠΈΠΈ-ΠΏΠΎΠΌΠΎΡΠ½ΠΈΠΊΠ° ΠΏΠΎΠ΄ Π½ΠΎΠΌΠ΅ΡΠΎΠΌ Π²ΠΎΡΠ΅ΠΌΡ. ΠΠΎΡΠ»Π΅ Π΅Π΅ Π·Π°ΠΏΡΡΠΊΠ° Π»ΠΎΠ³ΠΈΠΊΠ° ΠΏΡΠΎΡΡΠ°Ρ. ΠΠΎΠ·Π²ΡΠ°ΡΠ΅Π½Π½ΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΠΈΠ· ΡΠ΅Π³ΠΈΡΡΡΠ° 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
Π₯ΠΎΡΠΎΡΠΎ, verifier Π½Π°ΡΠ΅Π» ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΡΠΉ kernel-helper.
ΠΡΠΈΠΌΠ΅Ρ: ΠΏΠ΅ΡΠ΅Π΄Π°Π΅ΠΌ Π°ΡΠ³ΡΠΌΠ΅Π½ΡΡ ΠΈ, Π½Π°ΠΊΠΎΠ½Π΅Ρ, Π·Π°ΠΏΡΡΠΊΠ°Π΅ΠΌ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ!
ΠΡΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ-ΠΏΠΎΠΌΠΎΡΠ½ΠΈΠΊΠΈ Π½Π° ΡΡΠΎΠ²Π½Π΅ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΠΈΠΌΠ΅ΡΡ ΠΏΡΠΎΡΠΎΡΠΈΠΏ
u64 fn(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
ΠΠ°ΡΠ°ΠΌΠ΅ΡΡΡ ΡΡΠ½ΠΊΡΠΈΡΠΌ-ΠΏΠΎΠΌΠΎΡΠ½ΠΈΠΊΠ°ΠΌ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡΡΡ Π² ΡΠ΅Π³ΠΈΡΡΡΠ°Ρ
r1
βr5
, Π° Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΡΡΡ Π² ΡΠ΅Π³ΠΈΡΡΡΠ΅ r0
. Π€ΡΠ½ΠΊΡΠΈΠΉ, ΠΏΡΠΈΠ½ΠΈΠΌΠ°ΡΡΠΈΡ
Π±ΠΎΠ»ΡΡΠ΅ ΠΏΡΡΠΈ Π°ΡΠ³ΡΠΌΠ΅Π½ΡΠΎΠ² βΒ Π½Π΅Ρ ΠΈ Π΄ΠΎΠ±Π°Π²Π»ΡΡΡ ΠΈΡ
ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΡ Π² Π±ΡΠ΄ΡΡΠ΅ΠΌ Π½Π΅ ΠΏΡΠ΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅ΡΡΡ.
ΠΠ°Π²Π°ΠΉΡΠ΅ ΠΏΠΎΡΠΌΠΎΡΡΠΈΠΌ Π½Π° Π½ΠΎΠ²ΡΠΉ kernel helper ΠΈ ΡΠΎ ΠΊΠ°ΠΊ 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;
}
ΠΠ°ΡΠ° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ° ΠΏΠ΅ΡΠ°ΡΠ°Π΅Ρ Π½ΠΎΠΌΠ΅Ρ CPU, Π½Π° ΠΊΠΎΡΠΎΡΠΎΠΌ ΠΎΠ½Π° Π·Π°ΠΏΡΡΠ΅Π½Π°. Π‘ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡΡΠ΅ΠΌ Π΅Π΅ ΠΈ ΠΏΠΎΡΠΌΠΎΡΡΠΈΠΌ Π½Π° ΠΊΠΎΠ΄:
$ 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
(request + reply):
$ 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
Π½Π΅ Π΄Π°ΡΠΎΠΌ ΠΏΠΈΡΠ΅Ρ Π² ΠΎΡΠ»Π°Π΄ΠΎΡΠ½ΡΠΉ ΡΠ°ΠΉΠ»: ΡΡΠΎ Π½Π΅ ΡΠ°ΠΌΡΠΉ ΡΠ΄Π°ΡΠ½ΡΠΉ Ρ
Π΅Π»ΠΏΠ΅Ρ Π΄Π»Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ Π² production, Π½ΠΎ Π½Π°ΡΠ° ΡΠ΅Π»Ρ Π±ΡΠ»Π° ΠΏΠΎΠΊΠ°Π·Π°ΡΡ ΡΡΠΎ-ΡΠΎ ΠΏΡΠΎΡΡΠΎΠ΅.
ΠΠΎΡΡΡΠΏ ΠΊ maps ΠΈΠ· ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌ 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
ΠΏΠΎΠ»ΡΡΠ°Π΅ΠΌ ΡΠΊΠ°Π·Π°ΡΠ΅Π»Ρ Π½Π° ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΡΡ Π·Π°ΠΏΠΈΡΡ Π² ΠΌΠ°ΡΡΠΈΠ²Π΅, ΠΊΠΎΡΠΎΡΡΡ ΡΠ²Π΅Π»ΠΈΡΠΈΠ²Π°Π΅ΠΌ Π½Π° Π΅Π΄ΠΈΠ½ΠΈΡΡ. Π ΠΏΠ΅ΡΠ΅Π²ΠΎΠ΄Π΅ Π½Π° ΡΡΡΡΠΊΠΈΠΉ: ΠΌΡ ΠΏΠΎΠ΄ΡΡΠΈΡΡΠ²Π°Π΅ΠΌ ΡΡΠ°ΡΠΈΡΡΠΈΠΊΡ ΡΠΎΠ³ΠΎ, Π½Π° ΠΊΠ°ΠΊΠΎΠΌ CPU Π±ΡΠ»ΠΈ ΠΎΠ±ΡΠ°Π±ΠΎΡΠ°Π½Ρ Π²Ρ
ΠΎΠ΄ΡΡΠΈΠ΅ ΠΏΠ°ΠΊΠ΅ΡΡ. ΠΠΎΠΏΡΠΎΠ±ΡΠ΅ΠΌ Π·Π°ΠΏΡΡΡΠΈΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ:
$ 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
ΠΠΎ Π΅ΡΠ»ΠΈ ΠΌΡ ΠΏΠΎΡΠΌΠΎΡΡΠΈΠΌ Π½Π° ΡΠΆΠ΅ Π·Π°Π³ΡΡΠΆΠ΅Π½Π½ΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ, ΡΠΎ ΡΠ²ΠΈΠ΄ΠΈΠΌ ΡΠΊΠ°Π·Π°ΡΠ΅Π»Ρ Π½Π° ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΡΠΉ map (ΡΡΡΠΎΠΊΠ° 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
, ΠΊΠΎΡΠΎΡΠ°Ρ ΡΠΎΠ·Π΄Π°Π΅Ρ ΠΈΠ»ΠΈ ΠΎΡΠΊΡΡΠ²Π°Π΅Ρ ΡΡΡΠ΅ΡΡΠ²ΡΡΡΠΈΠ΅ 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;
(ΠΏΠΎΠ»Π½ΡΠΉ ΠΊΠΎΠ΄ ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡΠΈ
- Π²ΠΎ Π²ΡΠ΅ΠΌΡ Π·Π°Π³ΡΡΠ·ΠΊΠΈ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ verifier ΠΏΡΠΎΠ²Π΅ΡΡΠ΅Ρ ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΠΎΡΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ ΠΌΠ°ΠΏΠ° ΠΈ ΠΏΡΠΎΠΏΠΈΡΡΠ²Π°Π΅Ρ Π°Π΄ΡΠ΅Ρ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠ΅ΠΉ ΡΡΡΡΠΊΡΡΡΡ
struct bpf_map
ΠΡΠΈ Π·Π°Π³ΡΡΠ·ΠΊΠ΅ Π±ΠΈΠ½Π°ΡΠ½ΠΈΠΊΠ° ELF ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ libbpf
ΠΏΡΠΎΠΈΡΡ
ΠΎΠ΄ΠΈΡ Π΅ΡΠ΅ ΠΌΠ½ΠΎΠ³ΠΎ ΡΠΎΠ±ΡΡΠΈΠΉ, Π½ΠΎ ΠΌΡ ΠΎΠ±ΡΡΠ΄ΠΈΠΌ ΡΡΠΎ Π² ΡΠ°ΠΌΠΊΠ°Ρ
Π΄ΡΡΠ³ΠΈΡ
ΡΡΠ°ΡΠ΅ΠΉ.
ΠΠ°Π³ΡΡΠΆΠ°Π΅ΠΌ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ ΠΈ ΠΌΠ°ΠΏΡ Π±Π΅Π· libbpf
ΠΠ°ΠΊ ΠΈ ΠΎΠ±Π΅ΡΠ°Π»ΠΎΡΡ, Π²ΠΎΡ ΠΏΡΠΈΠΌΠ΅Ρ Π΄Π»Ρ ΡΠΈΡΠ°ΡΠ΅Π»Π΅ΠΉ, ΠΊΠΎΡΠΎΡΡΠ΅ Ρ
ΠΎΡΡΡ Π·Π½Π°ΡΡ, ΠΊΠ°ΠΊ ΡΠΎΠ·Π΄Π°ΡΡ ΠΈ Π·Π°Π³ΡΡΠ·ΠΈΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡΡΡ ΠΌΠ°ΠΏΡ, Π±Π΅Π· ΠΏΠΎΠΌΠΎΡΠΈ libbpf
. ΠΡΠΎ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΠΏΠΎΠ»Π΅Π·Π½ΠΎ, ΠΊΠΎΠ³Π΄Π° Π²Ρ ΡΠ°Π±ΠΎΡΠ°Π΅ΡΠ΅ Π² ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΠΈ, Π΄Π»Ρ ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ Π½Π΅ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΡΠΎΠ±ΡΠ°ΡΡ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ, ΠΈΠ»ΠΈ ΡΠΊΠΎΠ½ΠΎΠΌΠΈΡΠ΅ ΠΊΠ°ΠΆΠ΄ΡΠΉ Π±ΠΈΡ, ΠΈΠ»ΠΈ ΠΏΠΈΡΠ΅ΡΠ΅ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ ΡΠΈΠΏΠ° ply
ΠΠ»Ρ ΡΠΎΠ³ΠΎ, ΡΡΠΎΠ±Ρ Π±ΡΠ»ΠΎ ΠΏΡΠΎΡΠ΅ ΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΡ Π·Π° Π»ΠΎΠ³ΠΈΠΊΠΎΠΉ, ΠΌΡ Π΄Π»Ρ ΡΡΠΈΡ
ΡΠ΅Π»Π΅ΠΉ ΠΏΠ΅ΡΠ΅ΠΏΠΈΡΠ΅ΠΌ Π½Π°Ρ ΠΏΡΠΈΠΌΠ΅Ρ 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, Π° Π·Π½Π°ΡΠΈΡ, ΠΎΠ½ΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π»ΠΈ ΡΠ°ΠΌΡΠΉ ΠΏΡΠΈΠ²ΡΡΠ½ΡΠΉ Π΄Π»Ρ Π½ΠΈΡ
(Π½ΠΎ Π½Π΅ Π΄Π»Ρ Π½ΠΎΡΠΌΠ°Π»ΡΠ½ΡΡ
Π»ΡΠ΄Π΅ΠΉ) ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΡ Ρ ΡΠ΄ΡΠΎΠΌ: xdp_attach
β ΡΡΠΎ ΠΊΠΎΠΏΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΠΊΠΎΠ΄Π° ΠΈΠ· libbpf
, Π° ΠΈΠΌΠ΅Π½Π½ΠΎ, ΠΈΠ· ΡΠ°ΠΉΠ»Π° netlink.c
ΠΠΎΠ±ΡΠΎ ΠΏΠΎΠΆΠ°Π»ΠΎΠ²Π°ΡΡ Π² ΠΌΠΈΡ netlink ΡΠΎΠΊΠ΅ΡΠΎΠ²
ΠΡΠΊΡΡΠ²Π°Π΅ΠΌ 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
ΠΠΎΡΠ»Π΅ΠΌ ΠΏΠΈΠ½Π³ΠΈ ΠΈ ΠΏΠΎΠΌΠΎΡΡΠΈΠΌ Π½Π° map:
$ 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
Π£ΡΠ°, Π²ΡΠ΅ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ. ΠΠ°ΠΌΠ΅ΡΡΡΠ΅, ΠΊΡΡΠ°ΡΠΈ, ΡΡΠΎ Π½Π°Ρ map ΠΎΠΏΡΡΡ ΠΎΡΠΎΠ±ΡΠ°ΠΆΠ°Π΅ΡΡΡ Π² Π²ΠΈΠ΄Π΅ Π±Π°ΠΉΡΠΈΠΊΠΎΠ². ΠΡΠΎ ΠΏΡΠΎΠΈΡ
ΠΎΠ΄ΠΈΡ ΠΈΠ·-Π·Π° ΡΠΎΠ³ΠΎ, ΡΡΠΎ, Π² ΠΎΡΠ»ΠΈΡΠΈΠ΅ ΠΎΡ libbpf
ΠΌΡ Π½Π΅ Π·Π°Π³ΡΡΠΆΠ°Π»ΠΈ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ ΠΎ ΡΠΈΠΏΠ°Ρ
(BTF). ΠΠΎ ΠΏΠΎΠ΄ΡΠΎΠ±Π½Π΅Π΅ ΠΎΠ± ΡΡΠΎΠΌ ΠΌΡ ΠΏΠΎΠ³ΠΎΠ²ΠΎΡΠΈΠΌ Π² ΡΠ»Π΅Π΄ΡΡΡΠΈΠΉ ΡΠ°Π·.
Π‘ΡΠ΅Π΄ΡΡΠ²Π° ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ
Π ΡΡΠΎΠΌ ΡΠ°Π·Π΄Π΅Π»Π΅ ΠΌΡ ΠΏΠΎΡΠΌΠΎΡΡΠΈΠΌ Π½Π° ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡΠ½ΡΠΉ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠ°Π»ΡΠ½ΡΠΉ Π½Π°Π±ΠΎΡ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ° BPF.
ΠΠΎΠΎΠ±ΡΠ΅ Π³ΠΎΠ²ΠΎΡΡ, Π΄Π»Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌ BPF Π½Π΅ Π½ΡΠΆΠ½ΠΎ Π½ΠΈΡΠ΅Π³ΠΎ ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎΠ³ΠΎ βΒ BPF ΡΠ°Π±ΠΎΡΠ°Π΅Ρ Π½Π° Π»ΡΠ±ΠΎΠΌ ΠΏΡΠΈΠ»ΠΈΡΠ½ΠΎΠΌ Π΄ΠΈΡΡΡΠΈΠ±ΡΡΠΈΠ²Π½ΠΎΠΌ ΡΠ΄ΡΠ΅, Π° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ ΡΠΎΠ±ΠΈΡΠ°ΡΡΡΡ ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ clang
, ΠΊΠΎΡΠΎΡΡΠΉ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡΡΠ°Π²ΠΈΡΡ ΠΈΠ· ΠΏΠ°ΠΊΠ΅ΡΠ°. ΠΠ΄Π½Π°ΠΊΠΎ, ΠΈΠ·-Π·Π° ΡΠΎΠ³ΠΎ, ΡΡΠΎ BPF Π½Π°Ρ
ΠΎΠ΄ΠΈΡΡΡ Π² ΠΏΡΠΎΡΠ΅ΡΡΠ΅ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ, ΡΠ΄ΡΠΎ ΠΈ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΡ ΠΏΠΎΡΡΠΎΡΠ½Π½ΠΎ ΠΌΠ΅Π½ΡΡΡΡΡ, Π΅ΡΠ»ΠΈ Π²Ρ Π½Π΅ Ρ
ΠΎΡΠΈΡΠ΅ ΠΏΠΈΡΠ°ΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ BPF Π΄Π΅Π΄ΠΎΠ²ΡΠΊΠΈΠΌΠΈ ΠΌΠ΅ΡΠΎΠ΄Π°ΠΌΠΈ ΠΈΠ· 2019-Ρ
, ΡΠΎ Π²Π°ΠΌ ΠΏΡΠΈΠ΄Π΅ΡΡΡ ΡΠΎΠ±ΡΠ°ΡΡ
llvm
/clang
pahole
- ΡΠ²ΠΎΠ΅ ΡΠ΄ΡΠΎ
bpftool
(ΠΠ»Ρ ΡΠΏΡΠ°Π²ΠΊΠΈ: ΡΡΠΎΡ ΡΠ°Π·Π΄Π΅Π» ΠΈ Π²ΡΠ΅ ΠΏΡΠΈΠΌΠ΅ΡΡ Π² ΡΡΠ°ΡΡΠ΅ Π·Π°ΠΏΡΡΠΊΠ°Π»ΠΈΡΡ Π½Π° Debian 10.)
llvm/clang
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
Π²Π·ΡΡΠ° ΠΌΠ½ΠΎΠΉ ΠΈΠ·
ΠΡ Π½Π΅ Π±ΡΠ΄Π΅ΠΌ ΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°ΡΡ ΡΠΎΠ»ΡΠΊΠΎ ΡΡΠΎ ΡΠΎΠ±ΡΠ°Π½Π½ΡΠ΅ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ, Π° Π²ΠΌΠ΅ΡΡΠΎ ΡΡΠΎΠ³ΠΎ ΠΏΡΠΎΡΡΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ ΠΈΡ
Π² PATH
, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ:
export PATH="`pwd`/bin:$PATH"
(ΠΡΠΎ ΠΌΠΎΠΆΠ½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡΡ Π² .bashrc
ΠΈΠ»ΠΈ Π² ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΠΉ ΡΠ°ΠΉΠ». ΠΠΈΡΠ½ΠΎ Ρ Π΄ΠΎΠ±Π°Π²Π»ΡΡ ΡΠ°ΠΊΠΈΠ΅ Π²Π΅ΡΠΈ Π² ~/bin/activate-llvm.sh
ΠΈ ΠΊΠΎΠ³Π΄Π° Π½ΡΠΆΠ½ΠΎ Π΄Π΅Π»Π°Ρ . activate-llvm.sh
.)
Pahole ΠΈ BTF
Π£ΡΠΈΠ»ΠΈΡΠ° 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 ΠΌΡ ΠΌΠΎΠΆΠ΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΎΠ±ΡΡΠ½ΠΎΠ΅ net
net-next
bpf
bpf-next
*-next
ΡΠ΄ΡΠ° ΡΠ°ΠΌΡΠ΅ Π½Π΅ΡΡΠ°Π±ΠΈΠ»ΡΠ½ΡΠ΅ ΠΈΠ· ΠΏΠ΅ΡΠ΅ΡΠΈΡΠ»Π΅Π½Π½ΡΡ
).
Π ΡΠ°ΠΌΠΊΠΈ Π΄Π°Π½Π½ΠΎΠΉ ΡΡΠ°ΡΡΠΈ Π½Π΅ Π²Ρ
ΠΎΠ΄ΠΈΡ ΡΠ°ΡΡΠΊΠ°Π· ΠΎ ΡΠΎΠΌ, ΠΊΠ°ΠΊ ΡΠΏΡΠ°Π²Π»ΡΡΡΡΡ Ρ ΡΠ°ΠΉΠ»Π°ΠΌΠΈ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ ΡΠ΄ΡΠ° β ΠΏΡΠ΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅ΡΡΡ, ΡΡΠΎ Π²Ρ Π»ΠΈΠ±ΠΎ ΡΠΆΠ΅ ΡΠΌΠ΅Π΅ΡΠ΅ ΡΡΠΎ Π΄Π΅Π»Π°ΡΡ, Π»ΠΈΠ±ΠΎ
Π‘ΠΊΠ°ΡΠ°ΡΡ ΠΎΠ΄Π½ΠΎ ΠΈΠ· Π²ΡΡΠ΅ΡΠΏΠΎΠΌΡΠ½ΡΡΡΡ ΡΠ΄Π΅Ρ:
$ 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 β Π·Π°Π³ΡΡΠΆΠ°ΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ, ΡΠΎΠ·Π΄Π°Π²Π°ΡΡ ΠΈ ΠΈΠ·ΠΌΠ΅Π½ΡΡΡ maps, ΠΈΡΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΡ ΠΆΠΈΠ·Π½Π΅Π΄Π΅ΡΡΠ΅Π»ΡΠ½ΠΎΡΡΡ ΡΠΊΠΎΡΠΈΡΡΠ΅ΠΌΡ BPF, ΠΈ Ρ.ΠΏ. ΠΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ Π² Π²ΠΈΠ΄Π΅ ΠΈΡΡ
ΠΎΠ΄Π½ΠΈΠΊΠΎΠ² ΠΊ man pages ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡΠΈ
ΠΠ° ΠΌΠΎΠΌΠ΅Π½Ρ Π½Π°ΠΏΠΈΡΠ°Π½ΠΈΡ ΡΡΠ°ΡΡΠΈ bpftool
ΠΏΠΎΡΡΠ°Π²Π»ΡΠ΅ΡΡΡ Π² Π³ΠΎΡΠΎΠ²ΠΎΠΌ Π²ΠΈΠ΄Π΅ ΡΠΎΠ»ΡΠΊΠΎ Π΄Π»Ρ RHEL, Fedora ΠΈ Ubuntu (ΡΠΌ., Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, bpftool
Π² Debian). ΠΠΎ Π΅ΡΠ»ΠΈ Π²Ρ ΡΠΆΠ΅ ΡΠΎΠ±ΡΠ°Π»ΠΈ ΡΠ²ΠΎΠ΅ ΡΠ΄ΡΠΎ, ΡΠΎ ΡΠΎΠ±ΡΠ°ΡΡ 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, Π° Π·Π°ΡΠ΅ΠΌ β Π΄Π»Ρ ΠΏΡΠΈΠΌΠ΅ΡΠΎΠ² ΡΠ΅ΡΠ΅Π²ΡΡ ΠΈ security ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ BPF.
ΠΡΠ΅Π΄ΡΠ΄ΡΡΠΈΠ΅ ΡΡΠ°ΡΡΠΈ ΡΡΠΎΠ³ΠΎ ΡΠΈΠΊΠ»Π°
Π‘ΡΠ»ΠΊΠΈ
-
BPF and XDP Reference Guide β Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ ΠΏΠΎ BPF ΠΎΡ cilium, Π° ΡΠΎΡΠ½Π΅Π΅ ΠΎΡ Daniel Borkman, ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈΠ· ΡΠΎΠ·Π΄Π°ΡΠ΅Π»Π΅ΠΉ ΠΈ ΠΌΠ°Π½ΡΠ΅ΠΉΠ½Π΅ΡΠΎΠ² BPF. ΠΡΠΎ ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΠΏΠ΅ΡΠ²ΡΡ ΡΠ΅ΡΡΠ΅Π·Π½ΡΡ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠΉ, ΠΊΠΎΡΠΎΡΠΎΠ΅ ΠΎΡΠ»ΠΈΡΠ½ΠΎ ΠΎΡ ΠΎΡΡΠ°Π»ΡΠ½ΡΡ ΡΠ΅ΠΌ, ΡΡΠΎ Daniel ΡΠΎΡΠ½ΠΎ Π·Π½Π°Π΅Ρ ΠΎ ΡΠ΅ΠΌ ΠΏΠΈΡΠ΅Ρ ΠΈ Π»ΡΠΏΠΎΠ² ΡΠ°ΠΌ Π½Π΅ Π½Π°Π±Π»ΡΠ΄Π°Π΅ΡΡΡ. Π ΡΠ°ΡΡΠ½ΠΎΡΡΠΈ, Π² ΡΡΠΎΠΌ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ΅ ΡΠ°ΡΡΠΊΠ°Π·ΡΠ²Π°Π΅ΡΡΡ ΠΊΠ°ΠΊ ΡΠ°Π±ΠΎΡΠ°ΡΡ Ρ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ°ΠΌΠΈ BPF ΡΠΈΠΏΠΎΠ² XDP ΠΈ TC ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ ΠΈΠ·Π²Π΅ΡΡΠ½ΠΎΠΉ ΡΡΠΈΠ»ΠΈΡΡip
ΠΈΠ· ΠΏΠ°ΠΊΠ΅ΡΠ°iproute2
. -
Documentation/networking/filter.txt β ΠΎΡΠΈΠ³ΠΈΠ½Π°Π»ΡΠ½ΡΠΉ ΡΠ°ΠΉΠ» Ρ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΠ΅ΠΉ ΠΏΠΎ ΠΊΠ»Π°ΡΡΠΈΡΠ΅ΡΠΊΠΎΠΌΡ, Π° Π·Π°ΡΠ΅ΠΌ ΠΈ ΠΏΠΎ extended BPF. ΠΠΎΠ»Π΅Π·Π½ΠΎ ΡΠΈΡΠ°ΡΡ, Π΅ΡΠ»ΠΈ Π²Ρ Ρ ΠΎΡΠΈΡΠ΅ ΠΏΠΎΠΊΠΎΠΏΠ°ΡΡΡΡ Π² Π°ΡΡΠ΅ΠΌΠ±Π»Π΅ΡΠ΅ ΠΈ ΡΠ΅Ρ Π½ΠΈΡΠ΅ΡΠΊΠΈΡ Π΄Π΅ΡΠ°Π»ΡΡ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΡ. -
ΠΠ»ΠΎΠ³ ΠΏΡΠΎ BPF ΠΎΡ facebook . ΠΠ±Π½ΠΎΠ²Π»ΡΠ΅ΡΡΡ ΡΠ΅Π΄ΠΊΠΎ, Π½ΠΎ ΠΌΠ΅ΡΠΊΠΎ, ΡΠ°ΠΊ ΠΊΠ°ΠΊ ΠΏΠΈΡΡΡ ΡΡΠ΄Π° Alexei Starovoitov (Π°Π²ΡΠΎΡ eBPF) ΠΈ Andrii Nakryiko β (ΠΌΠ°Π½ΡΠ΅ΠΉΠ½Π΅Ρlibbpf
). -
Π‘Π΅ΠΊΡΠ΅ΡΡ bpftool . ΠΠ°Π½ΠΈΠΌΠ°ΡΠ΅Π»ΡΠ½ΡΠΉ twitter-ΡΡΠ΅Π΄ ΠΎΡ Quentin Monnet Ρ ΠΏΡΠΈΠΌΠ΅ΡΠ°ΠΌΠΈ ΠΈ ΡΠ΅ΠΊΡΠ΅ΡΠ°ΠΌΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ bpftool. -
Dive into BPF: a list of reading material . ΠΠΈΠ³Π°Π½ΡΡΠΊΠΈΠΉ (ΠΈ Π΄ΠΎ ΡΠΈΡ ΠΏΠΎΡ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅ΠΌΡΠΉ) ΡΠΏΠΈΡΠΎΠΊ ΡΡΡΠ»ΠΎΠΊ Π½Π° Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ ΠΏΠΎ BPF ΠΎΡ Quentin Monnet.
ΠΡΡΠΎΡΠ½ΠΈΠΊ: habr.com