Introduction au BPF

Les initiales BPF désignaient historiquement un composant obscur de Linux appelé le Berkeley Packet Filter, qui permet d’optimiser la performance des outils de capture de paquets réseau comme tcpdump en éliminant les paquets réseau non désirés directement au niveau du noyau, sans devoir les transmettre à l’application de capture de paquets.

Les programmes BPF subissent des vérifications qui visent à assurer qu’ils ne peuvent pas causer trop de dommages à leur “hôte”. En particulier, ils ne peuvent pas crasher, ni entrer dans une boucle infinie, ni modifier des structures de données ou du code qui ne leur appartiennent pas.

Depuis le début des années 2010, les capacités de cet outil ont été énormément étendues, jusqu’à en faire un outil générique pour injecter du code dans un programme (noyau Linux, applications…). En plus des paquets réseau, il est aujourd’hui possible d’attacher un programme BPF à toutes les sources d’événements abordées dans ce TP (PMCs, tracepoints, kprobes, uprobes et USDT), pour effectuer toutes sortes d’actions en réponse à l’événement.

Les possibilités des programmes BPF ont aussi été étendues, ainsi ils peuvent désormais manipuler des tables de hachage, les partager avec des applications utilisateur, mesurer des piles d’appel, et appeler un petit nombre de fonctions du noyau Linux.

Au niveau des limitations, le nombre d’APIs noyau accessibles est très réduit, les ressources utilisables sont limitées (tant en mémoire qu’en temps CPU), et on ne peut pas faire de boucle dont le compilateur ne peut pas prouver qu’elle est bornée. De plus, en raison d’un grand nombre de failles de sécurité découvertes dernièrement dans l’infrastructure sous-jacente, la plupart des distributions Linux restreignent l’utilisation de BPF à l’administrateur. C’est pour cette dernière raison que je ne peux pas vous en faire manipuler facilement en TP.

En termes d’utilisations concrètes…

  • Au niveau de perf, on peut injecter des programmes BPF au niveau d’un événement, dont la fonction est de filtrer les événements enregistrés par perf au niveau noyau, et d’y ajouter éventuellement des données supplémentaires (ce qui est par exemple très utile quand on veut extraires des informations textuelles dans une kprobe/uprobe).
  • En-dehors du monde perf, il est possible de calculer certains types de profils en histogramme directement dans le noyau, sans passer par le processus de copie des données en userspace de perf et donc d’extraire des informations de façon systématique (à chaque occurence d’un événement) avec un coût plus faible que ce qui est possible avec perf.

Ces possibilités sont explorées en détail dans le livre de Brendan Gregg BPF Performance Tools.