ΠšΡ€Π°Ρ‚ΠΊΠΎΠ΅ Π²Π²Π΅Π΄Π΅Π½ΠΈΠ΅ Π² BPF ΠΈ eBPF

ΠŸΡ€ΠΈΠ²Π΅Ρ‚, Π₯Π°Π±Ρ€! Π‘ΠΎΠΎΠ±Ρ‰Π°Π΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ нас готовится ΠΊ Π²Ρ‹Ρ…ΠΎΠ΄Ρƒ ΠΊΠ½ΠΈΠ³Π° "Linux Observability with BPF".

ΠšΡ€Π°Ρ‚ΠΊΠΎΠ΅ Π²Π²Π΅Π΄Π΅Π½ΠΈΠ΅ Π² BPF ΠΈ eBPF
ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Π°Ρ машина BPF ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ°Π΅Ρ‚ ΡΠ²ΠΎΠ»ΡŽΡ†ΠΈΠΎΠ½ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈ Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎ примСняСтся Π½Π° ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ΅, ΠΌΡ‹ ΠΏΠ΅Ρ€Π΅Π²Π΅Π»ΠΈ для вас ΡΡ‚Π°Ρ‚ΡŒΡŽ, ΠΎΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‰ΡƒΡŽ Π΅Π΅ основныС возмоТности ΠΈ состояниС Π½Π° настоящСС врСмя.

Π’ послСдниС Π³ΠΎΠ΄Ρ‹ стали Π½Π°Π±ΠΈΡ€Π°Ρ‚ΡŒ ΠΏΠΎΠΏΡƒΠ»ΡΡ€Π½ΠΎΡΡ‚ΡŒ инструмСнтарии для программирования ΠΈ ΠΏΡ€ΠΈΠ΅ΠΌΡ‹, ΠΏΡ€ΠΈΠ·Π²Π°Π½Π½Ρ‹Π΅ ΠΊΠΎΠΌΠΏΠ΅Π½ΡΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ограничСния ядра Linux Π² случаях, ΠΊΠΎΠ³Π΄Π° трСбуСтся Π²Ρ‹ΡΠΎΠΊΠΎΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½Π°Ρ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ². Один ΠΈΠ· Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ популярных ΠΏΡ€ΠΈΠ΅ΠΌΠΎΠ² Ρ‚Π°ΠΊΠΎΠ³ΠΎ Ρ€ΠΎΠ΄Π° называСтся ΠΎΠ±Ρ…ΠΎΠ΄ ядра (kernel bypass) ΠΈ позволяСт, пропуская сСтСвой ΡƒΡ€ΠΎΠ²Π΅Π½ΡŒ ядра, Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ всю ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² ΠΈΠ· ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ пространства. ΠžΠ±Ρ…ΠΎΠ΄ ядра Ρ‚Π°ΠΊΠΆΠ΅ ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅Ρ‚ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ сСтСвой ΠΊΠ°Ρ€Ρ‚ΠΎΠΉ ΠΈΠ· ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ пространства. Π˜Π½Ρ‹ΠΌΠΈ словами, ΠΏΡ€ΠΈ Ρ€Π°Π±ΠΎΡ‚Π΅ с сСтСвой ΠΊΠ°Ρ€Ρ‚ΠΎΠΉ ΠΌΡ‹ полагаСмся Π½Π° Π΄Ρ€Π°ΠΉΠ²Π΅Ρ€ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ пространства.

ΠŸΠ΅Ρ€Π΅Π΄Π°Π²Π°Ρ ΠΏΠΎΠ»Π½Ρ‹ΠΉ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΡŒ Π½Π°Π΄ сСтСвой ΠΊΠ°Ρ€Ρ‚ΠΎΠΉ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅ ΠΈΠ· ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ пространства, ΠΌΡ‹ сокращаСм ΠΈΠ·Π΄Π΅Ρ€ΠΆΠΊΠΈ, обусловлСнныС Ρ€Π°Π±ΠΎΡ‚ΠΎΠΉ ядра (ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ контСкста, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° сСтСвого уровня, прСрывания, Ρ‚.Π΄.), Ρ‡Ρ‚ΠΎ достаточно Π²Π°ΠΆΠ½ΠΎ ΠΏΡ€ΠΈ Ρ€Π°Π±ΠΎΡ‚Π΅ Π½Π° скоростях 10Π“Π±/с ΠΈΠ»ΠΈ Π²Ρ‹ΡˆΠ΅. ΠžΠ±Ρ…ΠΎΠ΄ ядра плюс комбинация Π΄Ρ€ΡƒΠ³ΠΈΡ… возмоТностСй (пакСтная ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ°) ΠΈ аккуратная настройка ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ (ΡƒΡ‡Π΅Ρ‚ NUMA, изоляция CPU, Ρ‚.Π΄.) ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‚ основам Π²Ρ‹ΡΠΎΠΊΠΎΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΉ сСтСвой ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π² ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠΌ пространствС. Π’ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, ΠΎΠ±Ρ€Π°Π·Ρ†ΠΎΠ²Ρ‹ΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Ρ‚Π°ΠΊΠΎΠ³ΠΎ Π½ΠΎΠ²ΠΎΠ³ΠΎ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π° ΠΊ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² – это DPDK ΠΎΡ‚ Intel (Data Plane Development Kit), хотя, ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‚ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΡˆΠΈΡ€ΠΎΠΊΠΎ извСстныС инструмСнтарии ΠΈ ΠΏΡ€ΠΈΠ΅ΠΌΡ‹, срСди ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… VPP ΠΎΡ‚ Cisco (Vector Packet Processing), Netmap ΠΈ, ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎ ΠΆΠ΅, Snabb.

Π£ ΠΎΡ€Π³Π°Π½ΠΈΠ·Π°Ρ†ΠΈΠΈ сСтСвых взаимодСйствий Π² ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠΌ пространствС Π΅ΡΡ‚ΡŒ ряд нСдостатков:

  • Π―Π΄Ρ€ΠΎ ОБ – это ΡƒΡ€ΠΎΠ²Π΅Π½ΡŒ абстрагирования для Π°ΠΏΠΏΠ°Ρ€Π°Ρ‚Π½Ρ‹Ρ… рСсурсов. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°ΠΌ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ пространства приходится ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ своими рСсурсами Π½Π°ΠΏΡ€ΡΠΌΡƒΡŽ, ΠΈΠΌ Ρ‚Π°ΠΊΠΆΠ΅ приходится ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ ΠΈ собствСнным Π°ΠΏΠΏΠ°Ρ€Π°Ρ‚Π½Ρ‹ΠΌ обСспСчСниСм. Π—Π°Ρ‡Π°ΡΡ‚ΡƒΡŽ это ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΡΡ‚ΡŒ программирования собствСнных Π΄Ρ€Π°ΠΉΠ²Π΅Ρ€ΠΎΠ².
  • ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΌΡ‹ ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ отказываСмся ΠΎΡ‚ пространства ядра, ΠΌΡ‹ Ρ‚Π°ΠΊΠΆΠ΅ отказываСмся ΠΈ ΠΎΡ‚ всСго сСтСвого Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»Π°, прСдоставляСмого ядром. ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°ΠΌ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ пространства приходится Π·Π°Π½ΠΎΠ²ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, ΡƒΠΆΠ΅ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‚ΡΡ ядром ΠΈΠ»ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΎΠ½Π½ΠΎΠΉ систСмой.
  • ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ пСсочницы, Ρ‡Ρ‚ΠΎ ΡΠ΅Ρ€ΡŒΠ΅Π·Π½ΠΎ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡ΠΈΠ²Π°Π΅Ρ‚ возмоТности ΠΈΡ… взаимодСйствия ΠΈ ΠΌΠ΅ΡˆΠ°Π΅Ρ‚ ΠΈΠΌ ΠΈΠ½Ρ‚Π΅Π³Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒΡΡ с Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ частями ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΎΠ½Π½ΠΎΠΉ систСмы.

Π’ сущности, ΠΏΡ€ΠΈ ΠΎΡ€Π³Π°Π½ΠΈΠ·Π°Ρ†ΠΈΠΈ сСтСвых взаимодСйствий Π² ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠΌ пространствС ΠΏΠΎΠ²Ρ‹ΡˆΠ΅Π½ΠΈΠ΅ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ достигаСтся ΠΏΡƒΡ‚Π΅ΠΌ пСрСноса ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² ΠΈΠ· ядра Π² ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠ΅ пространство. XDP Π΄Π΅Π»Π°Π΅Ρ‚ Ρ€ΠΎΠ²Π½ΠΎ Π½Π°ΠΎΠ±ΠΎΡ€ΠΎΡ‚: ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π°Π΅Ρ‚ сСтСвыС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΈΠ· ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ пространства (Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹, ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ, ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·Π°Ρ†ΠΈΡ, Ρ‚.Π΄.) Π² ΠΎΠ±Π»Π°ΡΡ‚ΡŒ ядра. XDP позволяСт Π½Π°ΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΡΠ΅Ρ‚Π΅Π²ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, ΠΊΠ°ΠΊ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚ ΠΏΠΎΠΏΠ°Π΄Π°Π΅Ρ‚ Π½Π° сСтСвой интСрфСйс ΠΈ Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΎΠ½ Π½Π°Ρ‡ΠΈΠ½Π°Π΅Ρ‚ Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅ Π²Π²Π΅Ρ€Ρ… Π² ΡΠ΅Ρ‚Π΅Π²ΡƒΡŽ подсистСму ядра. Π’ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ ΡΠΊΠΎΡ€ΠΎΡΡ‚ΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² сущСствСнно увСличиваСтся. Однако, ΠΊΠ°ΠΊ ядро позволяСт ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŽ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ свои ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ Π² пространствС ядра? ΠŸΡ€Π΅ΠΆΠ΄Π΅ Ρ‡Π΅ΠΌ ΠΎΡ‚Π²Π΅Ρ‚ΠΈΡ‚ΡŒ Π½Π° этот вопрос, Π΄Π°Π²Π°ΠΉΡ‚Π΅ рассмотрим, Ρ‡Ρ‚ΠΎ Ρ‚Π°ΠΊΠΎΠ΅ BPF.

BPF ΠΈ eBPF

НСсмотря Π½Π° Π½Π΅ Π²ΠΏΠΎΠ»Π½Π΅ понятноС Π½Π°Π·Π²Π°Π½ΠΈΠ΅ BPF (Π€ΠΈΠ»ΡŒΡ‚Ρ€Π°Ρ†ΠΈΡ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ², Π‘Π΅Ρ€ΠΊΠ»ΠΈ) – это, фактичСски, модСль Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½ΠΎΠΉ ΠΌΠ°ΡˆΠΈΠ½Ρ‹. Данная Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Π°Ρ машина исходно ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π»Π°ΡΡŒ для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°Ρ†ΠΈΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ², ΠΎΡ‚ΡΡŽΠ΄Π° ΠΈ Π½Π°Π·Π²Π°Π½ΠΈΠ΅.

Одним ΠΈΠ· Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ извСстных инструмСнтов, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰ΠΈΡ… BPF, являСтся tcpdump. ΠŸΡ€ΠΈ Π·Π°Ρ…Π²Π°Ρ‚Π΅ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ tcpdump ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ ΠΌΠΎΠΆΠ΅Ρ‚ Π·Π°Π΄Π°Ρ‚ΡŒ Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ для Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°Ρ†ΠΈΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ². Π—Π°Ρ…Π²Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒΡΡ Π±ΡƒΠ΄ΡƒΡ‚ лишь ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹, ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ этому Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΡŽ. НапримСр, Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ β€œtcp dst port 80” касаСтся всСх TCP-ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ², ΠΏΠΎΡΡ‚ΡƒΠΏΠ°ΡŽΡ‰ΠΈΡ… Π½Π° ΠΏΠΎΡ€Ρ‚ 80. ΠšΠΎΠΌΠΏΠΈΠ»ΡΡ‚ΠΎΡ€ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΠΎΠΊΡ€Π°Ρ‚ΠΈΡ‚ΡŒ это Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅, ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π² Π΅Π³ΠΎ Π² Π±Π°ΠΉΡ‚-ΠΊΠΎΠ΄ BPF.

$ sudo tcpdump -d "tcp dst port 80"
(000) ldh [12] (001) jeq #0x86dd jt 2 jf 6
(002) ldb [20] (003) jeq #0x6 jt 4 jf 15
(004) ldh [56] (005) jeq #0x50 jt 14 jf 15
(006) jeq #0x800 jt 7 jf 15
(007) ldb [23] (008) jeq #0x6 jt 9 jf 15
(009) ldh [20] (010) jset #0x1fff jt 15 jf 11
(011) ldxb 4*([14]&0xf)
(012) ldh [x + 16] (013) jeq #0x50 jt 14 jf 15
(014) ret #262144
(015) ret #0

Π’ΠΎΡ‚ Ρ‡Ρ‚ΠΎ, Π² ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠ΅, Π΄Π΅Π»Π°Π΅Ρ‚ Π²Ρ‹ΡˆΠ΅ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½Π°Ρ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°:

  • Π˜Π½ΡΡ‚Ρ€ΡƒΠΊΡ†ΠΈΡ (000): Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ ΠΏΠ°ΠΊΠ΅Ρ‚ со смСщСниСм 12, Π² Π²ΠΈΠ΄Π΅ 16-разрядного слова Π² аккумулятор. Π‘ΠΌΠ΅Ρ‰Π΅Π½ΠΈΠ΅ 12 соотвСтствуСт ethertype ΠΏΠ°ΠΊΠ΅Ρ‚Π°.
  • Π˜Π½ΡΡ‚Ρ€ΡƒΠΊΡ†ΠΈΡ (001): сравниваСт Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π² аккумуляторС с 0x86dd, Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ, с ethertype-Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ для IPv6. Если Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ€Π°Π²Π΅Π½ true, Ρ‚ΠΎ счСтчик ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΡ‚ ΠΊ инструкции (002), Π° Ссли Π½Π΅Ρ‚ – Ρ‚ΠΎ ΠΊ (006).
  • Π˜Π½ΡΡ‚Ρ€ΡƒΠΊΡ†ΠΈΡ (006): сравниваСт Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ с 0x800 (ethertype-Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ для IPv4). Если ΠΎΡ‚Π²Π΅Ρ‚ true, Ρ‚ΠΎ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΡ‚ ΠΊ (007), Ссли Π½Π΅Ρ‚ – Ρ‚ΠΎ ΠΊ (015).

И Ρ‚Π°ΠΊ Π΄Π°Π»Π΅Π΅, ΠΏΠΎΠΊΠ° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°Ρ†ΠΈΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² Π½Π΅ Π²Π΅Ρ€Π½Π΅Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚. ΠžΠ±Ρ‹Ρ‡Π½ΠΎ это Π±ΡƒΠ»Π΅Π°Π½. Π’ΠΎΠ·Π²Ρ€Π°Ρ‚ Π½Π΅Π½ΡƒΠ»Π΅Π²ΠΎΠ³ΠΎ значСния (инструкция (014)) ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚ подошСл, Π° Π²ΠΎΠ·Π²Ρ€Π°Ρ‚ Π½ΡƒΠ»Π΅Π²ΠΎΠ³ΠΎ (инструкция (015)) ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚ Π½Π΅ подошСл.

Π’ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Π°Ρ машина BPF ΠΈ Π΅Π΅ Π±Π°ΠΉΡ‚-ΠΊΠΎΠ΄ Π±Ρ‹Π»ΠΈ ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½Ρ‹ Π‘Ρ‚ΠΈΠ²ΠΎΠΌ Мак-Канном ΠΈ Π’Π°Π½ΠΎΠΌ ДТСйкобсоном Π² ΠΊΠΎΠ½Ρ†Π΅ 1992, ΠΊΠΎΠ³Π΄Π° Π²Ρ‹ΡˆΠ»Π° ΠΈΡ… ΡΡ‚Π°Ρ‚ΡŒΡ Π€ΠΈΠ»ΡŒΡ‚Ρ€ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² BSD: Новая Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π° для Π·Π°Ρ…Π²Π°Ρ‚Π° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² Π½Π° ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠΌ ΡƒΡ€ΠΎΠ²Π½Π΅, Π²ΠΏΠ΅Ρ€Π²Ρ‹Π΅ данная тСхнология Π±Ρ‹Π»Π° прСдставлСна Π½Π° ΠΊΠΎΠ½Ρ„Π΅Ρ€Π΅Π½Ρ†ΠΈΠΈ Usenix Π·ΠΈΠΌΠΎΠΉ 1993 Π³ΠΎΠ΄Π°.

ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ BPF – это Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Π°Ρ машина, ΠΎΠ½Π° опрСдСляСт срСду, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ΡΡ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹. ΠšΡ€ΠΎΠΌΠ΅ Π±Π°ΠΉΡ‚-ΠΊΠΎΠ΄Π° ΠΎΠ½Π° Ρ‚Π°ΠΊΠΆΠ΅ опрСдСляСт ΠΏΠ°ΠΊΠ΅Ρ‚Π½ΡƒΡŽ модСль памяти (инструкции Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ нСявно ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡŽΡ‚ΡΡ ΠΊ ΠΏΠ°ΠΊΠ΅Ρ‚Ρƒ), рСгистры (A ΠΈ X; рСгистры аккумулятора ΠΈ индСкса), Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ скрСтч-памяти ΠΈ нСявный счСтчик ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌ. Π˜Π½Ρ‚Π΅Ρ€Π΅ΡΠ½ΠΎ, Ρ‡Ρ‚ΠΎ Π±Π°ΠΉΡ‚-ΠΊΠΎΠ΄ BPF Π±Ρ‹Π» смодСлирован ΠΏΠΎ ΠΎΠ±Ρ€Π°Π·Ρ†Ρƒ Motorola 6502 ISA. Как вспоминал Π‘Ρ‚ΠΈΠ² Мак-Канн Π² своСм ΠΏΠ»Π΅Π½Π°Ρ€Π½ΠΎΠΌ Π΄ΠΎΠΊΠ»Π°Π΄Π΅ Π½Π° Sharkfest β€˜11, ΠΎΠ½ Π±Ρ‹Π» Π·Π½Π°ΠΊΠΎΠΌ со сборкой 6502 Π΅Ρ‰Π΅ со ΡΡ‚Π°Ρ€ΡˆΠΈΡ… классов, ΠΊΠΎΠ³Π΄Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π» Π½Π° Apple II, ΠΈ эти знания повлияли Π½Π° Π΅Π³ΠΎ Ρ€Π°Π±ΠΎΡ‚Ρƒ ΠΏΠΎ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡŽ Π±Π°ΠΉΡ‚-ΠΊΠΎΠ΄Π° BPF.

ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° BPF Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π° Π² ядрС Linux Π² вСрсии v2.5 ΠΈ Π²Ρ‹ΡˆΠ΅, Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Π° Π² основном усилиями ДТСя Шуллиста. Код BPF оставался Π±Π΅Π· ΡΠ΅Ρ€ΡŒΠ΅Π·Π½Ρ‹Ρ… ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ Π²ΠΏΠ»ΠΎΡ‚ΡŒ Π΄ΠΎ 2011 Π³ΠΎΠ΄Π°, ΠΊΠΎΠ³Π΄Π° Π­Ρ€ΠΈΠΊ Π”ΡƒΠΌΠ°Π·Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π΅Π»Π°Π» ΠΈΠ½Ρ‚Π΅Ρ€ΠΏΡ€Π΅Ρ‚Π°Ρ‚ΠΎΡ€ BPF для Ρ€Π°Π±ΠΎΡ‚Ρ‹ Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ JIT (Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: JIT для ΠΏΠ°ΠΊΠ΅Ρ‚Π½Ρ‹Ρ… Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ²). ПослС этого ядро вмСсто ΠΈΠ½Ρ‚Π΅Ρ€ΠΏΡ€Π΅Ρ‚Π°Ρ†ΠΈΠΈ Π±Π°ΠΉΡ‚-ΠΊΠΎΠ΄Π° BPF ΠΌΠΎΠ³Π»ΠΎ Π½Π°ΠΏΡ€ΡΠΌΡƒΡŽ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ BPF ΠΏΠΎΠ΄ Ρ†Π΅Π»Π΅Π²ΡƒΡŽ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρƒ: x86, ARM, MIPS, Ρ‚.Π΄.

ПозТС, Π² 2014 Π³ΠΎΠ΄Ρƒ, АлСксСй Π‘Ρ‚Π°Ρ€ΠΎΠ²ΠΎΠΉΡ‚ΠΎΠ² ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠΈΠ» Π½ΠΎΠ²Ρ‹ΠΉ JIT-ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ для BPF. ЀактичСски этот Π½ΠΎΠ²Ρ‹ΠΉ JIT стал Π½ΠΎΠ²ΠΎΠΉ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€ΠΎΠΉ Π½Π° основС BPF ΠΈ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ» Π½Π°Π·Π²Π°Π½ΠΈΠ΅ eBPF. Π”ΡƒΠΌΠ°ΡŽ, Π² Ρ‚Π΅Ρ‡Π΅Π½ΠΈΠ΅ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ ΠΎΠ±Π΅ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹Π΅ ΠΌΠ°ΡˆΠΈΠ½Ρ‹ сосущСствовали, Π½ΠΎ Π² настоящСС врСмя Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°Ρ†ΠΈΡ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² рСализуСтся Π½Π° основС eBPF. ЀактичСски, Π²ΠΎ ΠΌΠ½ΠΎΠ³ΠΈΡ… ΠΎΠ±Ρ€Π°Π·Ρ†Π°Ρ… соврСмСнной Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ ΠΏΠΎΠ΄ BPF понимаСтся eBPF, Π° классичСская BPF сСгодня извСстна ΠΊΠ°ΠΊ cBPF.

eBPF Π² Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΡΡ… Ρ€Π°ΡΡˆΠΈΡ€ΡΠ΅Ρ‚ ΠΊΠ»Π°ΡΡΠΈΡ‡Π΅ΡΠΊΡƒΡŽ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½ΡƒΡŽ ΠΌΠ°ΡˆΠΈΠ½Ρƒ BPF:

  • ΠžΠΏΠΈΡ€Π°Π΅Ρ‚ΡΡ Π½Π° соврСмСнныС 64-разрядныС Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρ‹. eBPF ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ 64-разрядныС рСгистры ΠΈ ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π΅Ρ‚ количСство доступных рСгистров с 2 (аккумулятор ΠΈ X) Π΄ΠΎ 10. Π’ eBPF Ρ‚Π°ΠΊΠΆΠ΅ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‚ΡΡ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΊΠΎΠ΄Ρ‹ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ (BPF_MOV, BPF_JNE, BPF_CALL…).
  • ΠžΡ‚ΠΊΡ€Π΅ΠΏΠ»Π΅Π½Π° ΠΎΡ‚ подсистСмы сСтСвого уровня. BPF Π±Ρ‹Π»Π° завязана Π½Π° ΠΏΠ°ΠΊΠ΅Ρ‚Π½ΡƒΡŽ модСль Π΄Π°Π½Π½Ρ‹Ρ…. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ½Π° использовалась для Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°Ρ†ΠΈΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ², ΠΊΠΎΠ΄ Π΅Π΅ находился Π² подсистСмС, ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΠ²Π°ΡŽΡ‰Π΅ΠΉ сСтСвыС взаимодСйствия. Однако, Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Π°Ρ машина eBPF большС Π½Π΅ привязана ΠΊ ΠΌΠΎΠ΄Π΅Π»ΠΈ Π΄Π°Π½Π½Ρ‹Ρ… ΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π² Π»ΡŽΠ±Ρ‹Ρ… цСлях. Π’Π°ΠΊ, Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ eBPF ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ ΠΊ tracepoint ΠΈΠ»ΠΈ ΠΊ kprobe. Π­Ρ‚ΠΎ ΠΎΡ‚ΠΊΡ€Ρ‹Π²Π°Π΅Ρ‚ ΠΏΡƒΡ‚ΡŒ ΠΊ ΠΈΠ½ΡΡ‚Ρ€ΡƒΠΌΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡŽ eBPF, Π°Π½Π°Π»ΠΈΠ·Ρƒ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ ΠΈ ΠΌΠ½ΠΎΠ³ΠΈΠΌ Π΄Ρ€ΡƒΠ³ΠΈΠΌ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π°ΠΌ использования Π² контСкстС Π΄Ρ€ΡƒΠ³ΠΈΡ… подсистСм ядра. Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΊΠΎΠ΄ eBPF располагаСтся ΠΏΠΎ собствСнному ΠΏΡƒΡ‚ΠΈ: kernel/bpf.
  • Π“Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹Π΅ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π° Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎΠ΄ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ΠΌ ΠšΠ°Ρ€Ρ‚Ρ‹. ΠšΠ°Ρ€Ρ‚Ρ‹ – это Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π° Ρ‚ΠΈΠΏΠ° Β«ΠΊΠ»ΡŽΡ‡-Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅Β», ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΠ²Π°ΡŽΡ‰ΠΈΠ΅ ΠΎΠ±ΠΌΠ΅Π½ Π΄Π°Π½Π½Ρ‹ΠΌΠΈ ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΠΌ пространством ΠΈ пространством ядра. Π’ eBPF ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‚ΡΡ ΠΊΠ°Ρ€Ρ‚Ρ‹ Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… Ρ‚ΠΈΠΏΠΎΠ².
  • Π’ΡΠΏΠΎΠΌΠΎΠ³Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. Π’ частности, для пСрСзаписи ΠΏΠ°ΠΊΠ΅Ρ‚Π°, вычислСния ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΡŒΠ½ΠΎΠΉ суммы ΠΈΠ»ΠΈ клонирования ΠΏΠ°ΠΊΠ΅Ρ‚Π°. Π­Ρ‚ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ΡΡ Π²Π½ΡƒΡ‚Ρ€ΠΈ ядра ΠΈ Π½Π΅ относятся ΠΊ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°ΠΌ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ пространства. ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, ΠΈΠ· ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌ eBPF ΠΌΠΎΠΆΠ½ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ систСмныС Π²Ρ‹Π·ΠΎΠ²Ρ‹.
  • ΠšΠΎΠ½Ρ†Π΅Π²Ρ‹Π΅ Π²Ρ‹Π·ΠΎΠ²Ρ‹. Π Π°Π·ΠΌΠ΅Ρ€ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ Π² eBPF ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ 4096 Π±Π°ΠΉΡ‚. Π’ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΊΠΎΠ½Ρ†Π΅Π²ΠΎΠ³ΠΎ Π²Ρ‹Π·ΠΎΠ²Π° позволяСт ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅ eBPF ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½ΠΎΠ²ΠΎΠΉ eBPF-ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅ ΠΈ Ρ‚Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ ΠΎΠ±ΠΎΠΉΡ‚ΠΈ Π΄Π°Π½Π½ΠΎΠ΅ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ (Ρ‚Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ ΠΌΠΎΠΆΠ½ΠΎ ΡΠ²ΡΠ·Π°Ρ‚ΡŒ Π΄ΠΎ 32 ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌ).

eBPF: ΠΏΡ€ΠΈΠΌΠ΅Ρ€

Π’ исходниках ядра Linux Π΅ΡΡ‚ΡŒ нСсколько ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠ² для eBPF. Они доступны ΠΏΠΎ адрСсу samples/bpf/. Π§Ρ‚ΠΎΠ±Ρ‹ ΡΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ эти ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹, просто Π²Π²Π΅Π΄ΠΈΡ‚Π΅:

$ sudo make samples/bpf/

Π― Π½Π΅ Π±ΡƒΠ΄Ρƒ сам ΠΏΠΈΡΠ°Ρ‚ΡŒ Π½ΠΎΠ²Ρ‹ΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ для eBPF, Π° Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡΡŒ ΠΎΠ΄Π½ΠΈΠΌ ΠΈΠ· ΠΎΠ±Ρ€Π°Π·Ρ†ΠΎΠ², доступных Π² samples/bpf/. Π Π°ΡΡΠΌΠΎΡ‚Ρ€ΡŽ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ участки ΠΊΠΎΠ΄Π° ΠΈ объясню, ΠΊΠ°ΠΊ ΠΎΠ½ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚. Π’ качСствС ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° я Π²Ρ‹Π±Ρ€Π°Π» ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ tracex4.

Π’ΠΎΠΎΠ±Ρ‰Π΅, ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΈΠ· ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠ² Π² samples/bpf/ состоит ΠΈΠ· Π΄Π²ΡƒΡ… Ρ„Π°ΠΉΠ»ΠΎΠ². Π’ Π΄Π°Π½Π½ΠΎΠΌ случаС:

  • tracex4_kern.c, содСрТит исходный ΠΊΠΎΠ΄, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ Π² ядрС ΠΊΠ°ΠΊ Π±Π°ΠΉΡ‚-ΠΊΠΎΠ΄ eBPF.
  • tracex4_user.c, содСрТит ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ ΠΈΠ· ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ пространства.

Π’ Ρ‚Π°ΠΊΠΎΠΌ случаС, Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΡΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ tracex4_kern.c Π² Π±Π°ΠΉΡ‚-ΠΊΠΎΠ΄ eBPF. Π’ настоящий ΠΌΠΎΠΌΠ΅Π½Ρ‚ Π² gcc отсутствуСт сСрвСрная Ρ‡Π°ΡΡ‚ΡŒ для eBPF. К ΡΡ‡Π°ΡΡ‚ΡŒΡŽ, clang ΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹Π΄Π°Π²Π°Ρ‚ΡŒ Π±Π°ΠΉΡ‚-ΠΊΠΎΠ΄ eBPF. Makefile ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ clang для компиляции tracex4_kern.c Π² Ρ„Π°ΠΉΠ» ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°.

Π’Ρ‹ΡˆΠ΅ я ΡƒΠΏΠΎΠΌΠΈΠ½Π°Π», Ρ‡Ρ‚ΠΎ ΠΎΠ΄Π½ΠΎΠΉ ΠΈΠ· Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ интСрСсных Ρ„ΠΈΡ‡ eBPF ΡΠ²Π»ΡΡŽΡ‚ΡΡ ΠΊΠ°Ρ€Ρ‚Ρ‹. tracex4_kern опрСдСляСт ΠΎΠ΄Π½Ρƒ ΠΊΠ°Ρ€Ρ‚Ρƒ:

struct pair {
    u64 val;
    u64 ip;
};  

struct bpf_map_def SEC("maps") my_map = {
    .type = BPF_MAP_TYPE_HASH,
    .key_size = sizeof(long),
    .value_size = sizeof(struct pair),
    .max_entries = 1000000,
};

BPF_MAP_TYPE_HASH – ΠΎΠ΄ΠΈΠ½ ΠΈΠ· ΠΌΠ½ΠΎΠ³ΠΈΡ… Ρ‚ΠΈΠΏΠΎΠ² ΠΊΠ°Ρ€Ρ‚, ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π΅ΠΌΡ‹Ρ… eBPF. Π’ Π΄Π°Π½Π½ΠΎΠΌ случаС, это просто Ρ…Π΅Ρˆ. Π’Π°ΠΊΠΆΠ΅ Π²Ρ‹ ΠΌΠΎΠ³Π»ΠΈ Π·Π°ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ объявлСниС SEC("maps"). SEC – это макрос, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹ΠΉ для создания Π½ΠΎΠ²ΠΎΠΉ сСкции Π΄Π²ΠΎΠΈΡ‡Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π°. БобствСнно, Π² ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ tracex4_kern опрСдСляСтся Π΅Ρ‰Π΅ Π΄Π²Π΅ сСкции:

SEC("kprobe/kmem_cache_free")
int bpf_prog1(struct pt_regs *ctx)
{   
    long ptr = PT_REGS_PARM2(ctx);

    bpf_map_delete_elem(&my_map, &ptr); 
    return 0;
}
    
SEC("kretprobe/kmem_cache_alloc_node") 
int bpf_prog2(struct pt_regs *ctx)
{
    long ptr = PT_REGS_RC(ctx);
    long ip = 0;

    // ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ ip-адрСс Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΉ стороны kmem_cache_alloc_node() 
    BPF_KRETPROBE_READ_RET_IP(ip, ctx);

    struct pair v = {
        .val = bpf_ktime_get_ns(),
        .ip = ip,
    };
    
    bpf_map_update_elem(&my_map, &ptr, &v, BPF_ANY);
    return 0;
}   

Π”Π²Π΅ эти Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‚ ΡƒΠ΄Π°Π»ΠΈΡ‚ΡŒ запись ΠΈΠ· ΠΊΠ°Ρ€Ρ‚Ρ‹ (kprobe/kmem_cache_free) ΠΈ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Π½Π° ΠΊΠ°Ρ€Ρ‚Ρƒ Π½ΠΎΠ²ΡƒΡŽ запись (kretprobe/kmem_cache_alloc_node). ВсС ΠΈΠΌΠ΅Π½Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ, записанныС Π·Π°Π³Π»Π°Π²Π½Ρ‹ΠΌΠΈ Π±ΡƒΠΊΠ²Π°ΠΌΠΈ, ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‚ макросам, ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΌ Π² bpf_helpers.h.

Если я Π²Ρ‹Π²Π΅Π΄Ρƒ Π΄Π°ΠΌΠΏ сСкций ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π°, Ρ‚ΠΎ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ эти Π½ΠΎΠ²Ρ‹Π΅ сСкции ΡƒΠΆΠ΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Ρ‹:

$ objdump -h tracex4_kern.o

tracex4_kern.o: file format elf64-little

Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000000 0000000000000000 0000000000000000 00000040 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 kprobe/kmem_cache_free 00000048 0000000000000000 0000000000000000 00000040 2**3
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
2 kretprobe/kmem_cache_alloc_node 000000c0 0000000000000000 0000000000000000 00000088 2**3
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
3 maps 0000001c 0000000000000000 0000000000000000 00000148 2**2
CONTENTS, ALLOC, LOAD, DATA
4 license 00000004 0000000000000000 0000000000000000 00000164 2**0
CONTENTS, ALLOC, LOAD, DATA
5 version 00000004 0000000000000000 0000000000000000 00000168 2**2
CONTENTS, ALLOC, LOAD, DATA
6 .eh_frame 00000050 0000000000000000 0000000000000000 00000170 2**3
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

Π•Ρ‰Π΅ Π΅ΡΡ‚ΡŒ tracex4_user.c, основная ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°. Π’ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠ΅, эта ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° ΡΠ»ΡƒΡˆΠ°Π΅Ρ‚ события kmem_cache_alloc_node. Когда происходит Ρ‚Π°ΠΊΠΎΠ΅ событиС, выполняСтся ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ ΠΊΠΎΠ΄ eBPF. Код сохраняСт IP-Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° Π² ΠΊΠ°Ρ€Ρ‚Ρƒ, ΠΈ Π·Π°Ρ‚Π΅ΠΌ этот ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ цикличСски выводится Π² основной ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅. ΠŸΡ€ΠΈΠΌΠ΅Ρ€:

$ sudo ./tracex4
obj 0xffff8d6430f60a00 is 2sec old was allocated at ip ffffffff9891ad90
obj 0xffff8d6062ca5e00 is 23sec old was allocated at ip ffffffff98090e8f
obj 0xffff8d5f80161780 is 6sec old was allocated at ip ffffffff98090e8f

Как связаны ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ пространства ΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° eBPF? ΠŸΡ€ΠΈ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ tracex4_user.c Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ Ρ„Π°ΠΉΠ» ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° tracex4_kern.o ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ load_bpf_file.

int main(int ac, char **argv)
{
    struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
    char filename[256];
    int i;

    snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);

    if (setrlimit(RLIMIT_MEMLOCK, &r)) {
        perror("setrlimit(RLIMIT_MEMLOCK, RLIM_INFINITY)");
        return 1;
    }

    if (load_bpf_file(filename)) {
        printf("%s", bpf_log_buf);
        return 1;
    }

    for (i = 0; ; i++) {
        print_old_objects(map_fd[1]);
        sleep(1);
    }

    return 0;
}

ΠŸΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ load_bpf_file Π·ΠΎΠ½Π΄Ρ‹, ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹Π΅ Π² Ρ„Π°ΠΉΠ»Π΅ eBPF, Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ΡΡ Π² /sys/kernel/debug/tracing/kprobe_events. Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΌΡ‹ ΡΠ»ΡƒΡˆΠ°Π΅ΠΌ эти события, ΠΈ наша ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° ΠΌΠΎΠΆΠ΅Ρ‚ Ρ‡Ρ‚ΠΎ-Π»ΠΈΠ±ΠΎ Π΄Π΅Π»Π°Ρ‚ΡŒ, ΠΊΠΎΠ³Π΄Π° ΠΎΠ½ΠΈ происходят.

$ sudo cat /sys/kernel/debug/tracing/kprobe_events
p:kprobes/kmem_cache_free kmem_cache_free
r:kprobes/kmem_cache_alloc_node kmem_cache_alloc_node

ВсС ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ Π² sample/bpf/ структурированы сходим ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ. Π’ Π½ΠΈΡ… всСгда ΠΏΠΎ Π΄Π²Π° Ρ„Π°ΠΉΠ»Π°:

  • XXX_kern.c: ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° eBPF.
  • XXX_user.c: основная ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°.

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° eBPF опрСдСляСт ΠΊΠ°Ρ€Ρ‚Ρ‹ ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, привязанныС ΠΊ сСкции. Когда ядро Π²Ρ‹Π΄Π°Π΅Ρ‚ событиС ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ° (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, tracepoint), привязанныС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ΡΡ. ΠšΠ°Ρ€Ρ‚Ρ‹ ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΠ²Π°ΡŽΡ‚ ΠΎΠ±ΠΌΠ΅Π½ Π΄Π°Π½Π½Ρ‹ΠΌΠΈ ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΎΠΉ ядра ΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΎΠΉ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ пространства.

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

Π’ этой ΡΡ‚Π°Ρ‚ΡŒΠ΅ Π² ΠΎΠ±Ρ‰ΠΈΡ… Ρ‡Π΅Ρ€Ρ‚Π°Ρ… Π±Ρ‹Π»ΠΈ рассмотрСны BPF ΠΈ eBPF. Π― знаю, Ρ‡Ρ‚ΠΎ сСгодня ΠΎΡ‡Π΅Π½ΡŒ ΠΌΠ½ΠΎΠ³ΠΎ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΈ рСсурсов ΠΎΠ± eBPF, поэтому ΠΏΠΎΡ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡƒΡŽ Π΅Ρ‰Π΅ нСсколько ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠ² для дальнСйшСго изучСния

Π Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡƒΡŽ ΠΏΠΎΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ:

  • BPF: the universal in-kernel virtual machine Π”ΠΆΠΎΠ½Π°Ρ‚Π°Π½Π° ΠšΠΎΡ€Π±Π΅Ρ‚Ρ‚Π°. Π’Π²Π΅Π΄Π΅Π½ΠΈΠ΅ Π² BPF ΠΈ рассказ ΠΎ Ρ‚ΠΎΠΌ, ΠΊΠ°ΠΊ ΠΎΠ½Π° ΡΠ²ΠΎΠ»ΡŽΡ†ΠΈΠΎΠ½ΠΈΡ€ΠΎΠ²Π°Π»Π° Π² eBPF.
  • A thorough introduction to eBPF Π‘Ρ€Π΅Π½Π΄Π°Π½Π° Π“Ρ€Π΅Π³Π³Π°. Π‘Ρ‚Π°Ρ‚ΡŒΡ с сайта LWN.net. Π‘Ρ€Π΅Π½Π΄Π°Π½ часто ΠΏΠΈΡˆΠ΅Ρ‚ Ρ‚Π²ΠΈΡ‚Ρ‹ ΠΎΠ± eBPF ΠΈ Π²Π΅Π΄Π΅Ρ‚ список рСсурсов Π½Π° эту Ρ‚Π΅ΠΌΡƒ Ρƒ сСбя Π² Π±Π»ΠΎΠ³Π΅.
  • Notes on BPF & eBPF Π”ΠΆΡƒΠ»ΠΈΠΈ Эванс. ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ ΠΊ ΠΏΡ€Π΅Π·Π΅Π½Ρ‚Π°Ρ†ΠΈΠΈ Π‘ΡƒΡ‡Π°ΠΊΡ€Ρ‹ Π¨Π°Ρ€ΠΌΡ‹ β€œThe BSD Packet Filter: A New Architecture for User-level Packet Capture”. ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ Ρ…ΠΎΡ€ΠΎΡˆΠΈΠ΅ ΠΈ Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΏΠΎΠΌΠΎΠ³Π°ΡŽΡ‚ Ρ€Π°Π·ΠΎΠ±Ρ€Π°Ρ‚ΡŒΡΡ Π² слайдах.
  • eBPF, part1: Past, Present and Future ЀСрриса Эллиса. Π›ΠΎΠ½Π³Ρ€ΠΈΠ΄ с ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ΅Π½ΠΈΠ΅ΠΌ, Π½ΠΎ Ρ‡ΠΈΡ‚Π°Ρ‚ΡŒ стоит. Одна ΠΈΠ· Π»ΡƒΡ‡ΡˆΠΈΡ… статСй ΠΎΠ± eBPF, ΠΊΠ°ΠΊΠΈΠ΅ ΠΌΠ½Π΅ попадались.

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