Table des matières de l'article :
La mise en réseau TCP / IP est un sujet complexe et cela devient vraiment compliqué lorsque vous essayez de définir des problèmes de performances ou de résoudre un problème. Il est utile d'avoir des outils qui peuvent sonder votre système et confirmer vos soupçons ou, mieux encore, qu'il n'y a pas de problèmes.
Un de ces outils est open source hyperf3. Voici sa description de GitHub :
iperf est un outil de mesure active de la bande passante maximale joignable sur les réseaux IP. Il prend en charge l'optimisation de divers paramètres liés aux temps, aux protocoles et aux tampons. Chaque test rapporte le débit/débit binaire mesuré, la perte et d'autres paramètres.
Cet article vous montre comment:
- Enquêter sur les problèmes de bande passante entre deux terminaux avec iperf 3
- Tester la connectivité multidiffusion UDP (User Datagram Protocol) (utilisée par Precision Time Protocol et d'autres protocoles pour la synchronisation de l'heure)
- Découvrez les erreurs de contrôle de redondance cyclique (CRC) sur une interface réseau
- Utilisez ethtool et tcpdump pour confirmer qu'une interface réseau ou un câble défectueux interrompt le trafic
- Écrire des scripts plus complexes à l'aide de Python 3
J'expliquerai également brièvement l'affinité CPU et pourquoi cela pourrait être important pour iperf3.
Commencer avec iperf3
Pour suivre ce tutoriel, vous aurez besoin de :
- Une distribution Linux (j'ai exécuté mes exemples sur un serveur Fedora)
- La possibilité d'exécuter des commandes en tant que root (en utilisant sudo , par exemple)
- Une compréhension de base des principes de réseau
Exécutez la commande pour installer iperf3. À propos de Fedora :
$ sudo dnf install -y iperf3
Iperf3 fonctionne en exécutant un client et un serveur qui se parlent. Voici quelques termes à connaître avant de commencer à l'utiliser :
- Le débit mesure combien de colis arrivent à destination avec succès.
- La bande passante Le réseau est la capacité maximale de transfert de données d'un réseau.
- La gigue est le délai entre le moment où un signal est émis et celui où il est reçu. Les bonnes connexions ont un temps de réponse constant.
- TCP va Transmission Control Protocol . Il s'agit d'un protocole fiable qui garantit que les paquets arrivent dans le même ordre qu'ils ont été envoyés via un tenir incontrôlable.
- UDP il n'a pas de protocole de prise de contact comme TCP. Il est plus rapide que TCP, mais si un paquet est perdu, il ne sera pas renvoyé et il n'y a aucune garantie que les paquets arriveront dans l'ordre envoyé.
Dans la démonstration de cet article :
- Le client et le serveur se connectent à l'interface Ethernet filaire. (Je n'utiliserai pas d'interfaces sans fil car elles sont plus sujettes à la gigue du bruit extérieur.)
- Mon test utilise les paramètres par défaut (port, connexion TCP à moins qu'ils ne soient remplacés par le drapeau
--udp
sur le client).
La preuve confirme si :
- Le switch entre les deux machines supporte des connexions à 1.000 Mbit/sec et les interfaces ont été configurées à cette capacité.
- Le mode full-duplex est activé pour envoyer et recevoir des données sur la carte en même temps. Vous le confirmerez plus tard dans l'article avec un autre outil appelé ethtool.
Sans plus tarder, je vais commencer.
Mesurer la bande passante et la gigue
Voici les commandes initiales sur le serveur :
[server ~]$ sudo ethtool eth0|rg -e 'Speed|Duplex'
Speed: 1000Mb/s
Duplex: Full
[server ~]$ ip --oneline address|rg 192
2: eth0 inet 192.168.1.11/24 brd 192.168.1.255 scope global dynamic eth0\ valid_lft 2090sec preferred_lft 2090sec
[server ~]$ iperf3 --server --bind 192.168.1.11 -affinity 1
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
Et maintenant le client :
[client ~]$ sudo ethtool eno1|rg -e 'Speed|Duplex'
Speed: 1000Mb/s
Duplex: Full
[client ~]$ iperf3 --client raspberrypi --bind 192.168.1.28 --affinity 1
Connecting to host raspberrypi, port 5201
[ 5] local 192.168.1.28 port 47609 connected to 192.168.1.11 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 111 MBytes 932 Mbits/sec 0 2.79 MBytes
[ 5] 1.00-2.00 sec 110 MBytes 923 Mbits/sec 0 2.98 MBytes
...
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 1021 MBytes 857 Mbits/sec 0 sender
[ 5] 0.00-9.95 sec 1020 MBytes 860 Mbits/sec receiver
iperf Done.
J'analyse les résultats :
- Zéro tentative (colonne Retr). C'est bien et attendu.
- Le débit est d'environ 860 Mbit/sec. La vitesse de liaison est proche de la bande passante théorique. Les commutateurs ont une limite sur la quantité de trafic que le fond de panier peut gérer.
- TCP garantit les pertes de transmission de paquets, donc la gigue n'est pas signalée ici.
Si vous inversez le
Tester la bande passante UDP
Pour tester UDP, procédez comme suit sur le client uniquement :
[client ~]$ iperf3 --client raspberrypi --bind 192.168.1.28 --udp --affinity 1
Connecting to host raspberrypi, port 5201
[ 5] local 192.168.1.28 port 47985 connected to 192.168.1.11 port 5201
[ ID] Interval Transfer Bitrate Total Datagrams
[ 5] 0.00-1.00 sec 129 KBytes 1.05 Mbits/sec 91
[ 5] 1.00-2.00 sec 127 KBytes 1.04 Mbits/sec 90
[ 5] 2.00-3.00 sec 129 KBytes 1.05 Mbits/sec 91
...
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Jitter Lost/Total Datagrams
[ 5] 0.00-10.00 sec 1.25 MBytes 1.05 Mbits/sec 0.000 ms 0/906 (0%) sender
[ 5] 0.00-9.99 sec 1.25 MBytes 1.05 Mbits/sec 0.028 ms 0/906 (0%) receiver
Voici les résultats:
- Le débit est beaucoup plus proche de la bande passante théorique. De plus, il n'y a pas de perte de paquets, ce qui est génial.
- UDP ne garantit pas la perte de paquets, donc les datagrammes perdus et la gigue sont signalés (et ont de bonnes valeurs).
Vous vous demandez peut-être ce que c'est --affinity
drapeau. Il n'est pas vraiment nécessaire ici de tester la bande passante sur cet exemple simple, mais cela me donne une excuse pour parler d'affinité.
Déviation rapide : affinité CPU, NUMA, isolcpus
Si vous étiez curieux et que vous avez consulté la documentation et les exemples d'iperf, vous avez probablement vu des références à l'affinité du CPU ou du processeur .
Alors c'est quoi? De Wikipédia :
L'affinité du processeur, ou le verrouillage du processeur ou "l'affinité du cache", permet à un processus ou à un thread d'être associé et dissocié d'une unité centrale de traitement (CPU) ou d'une gamme de processeurs, de sorte que le processus ou le thread ne s'exécute que sur le processeur ou le processeur désigné à la place de n'importe quel processeur.
Pourquoi voudriez-vous ajouter un processus à un groupe CPU spécifique ?
Aucune instance verrouillée par CPU ne peut utiliser les CPU d'une autre instance gelée, ce qui évite les conflits de ressources entre les instances. L'accès à la mémoire non uniforme (NUMA) permet à plusieurs processeurs de partager les caches L1, L2 et L3 et la mémoire principale.
Vous pouvez utiliser le matériel NUMA pour vous assurer de toujours utiliser la mémoire la plus proche du processeur.
À quoi ressemble un serveur avec plusieurs nœuds NUMA ? Vous pouvez le découvrir avec lscpu| rg NUMA
:
[client ~]$ lscpu|rg NUMA
NUMA node(s): 2
NUMA node0 CPU(s): 0-7
NUMA node1 CPU(s): 8-15
Il s'agit d'un serveur 16 CPU avec deux nœuds NUMA (il s'agit d'un exemple simplifié, une machine avec HyperThreading activé semble différente. Selon l'application, vous pouvez décider de le désactiver.
N'oubliez pas que vous pouvez utiliser l'affinité CPU non seulement pour augmenter les performances du réseau mais aussi les performances du disque.
Pour en revenir à iperf3, vous pouvez l'ajouter à un processeur spécifique en utilisant -A
o --affinity
. Par exemple, le CPU 3 (numéroté de 0 à n-1) ressemble à ceci :
# Equivalent of running iperf3 with numactl: /bin/numactl --physcpubind=2 iperf3 -c remotehost
iperf3 --affinity 2 --client remotehost
N'oubliez pas que vous devrez peut-être également dire au système d'exploitation d'éviter d'exécuter des processus hôtes sur ces processeurs, donc si vous utilisez Grubby, vous pouvez le faire avec isolcpus :
# Find the default kernel
$ sudo grubby --default-kernel
# Use that information and add isolcpus parameter, then reboot
$ sudo grubby --update-kernel=/boot/vmlinuz-5.14.18-100.fc33.x86_64 --args="isolcpus=2"
sudo shutdown -r now 'Updated kernel isolcpus, need to reboot'
Encore une fois, cela n'est pas nécessaire pour résoudre un problème de réseau, mais cela peut s'avérer utile si vous souhaitez que iperf3 se comporte comme l'une de vos applications optimisées.
L'optimisation est une sujet complexe, puis prenez une tasse de café (ou deux) et préparez-vous à commencer à lire.
Utilisez iperf3 pour détecter les paquets perdus et les erreurs CRC
Un Erreur CRC elle est causée par un périphérique physique défectueux (carte réseau, port de commutateur, câble) ou par une inadéquation des configurations full et half duplex entre deux périphériques. Celles-ci sont parfois difficiles à suivre sur les commutateurs en mode direct, où le commutateur transmet les erreurs reçues à tous les ports.
Il s'agit d'un scénario simplifié pour s'assurer qu'une nouvelle connexion NIC fonctionne sans erreurs CRC ou reçues/transmises (Rx/Tx) (ce qui signifie que la carte de commutation, le câble et le port sont OK).
Dans cet esprit, vous pouvez effectuer un test simple pour vous assurer que l'état du lien est bon :
- Capturez l'état CRC et les erreurs de perte de paquets sur la carte réseau testée.
- Exécutez iperf3 en mode TCP plus longtemps que d'habitude.
- Récupère les statistiques CRC de la carte réseau.
Si la différence est supérieure à zéro, alors :
- Vérifiez le mode duplex intégral sur la carte et le port du commutateur (ethtool).
- Remplacez le câble.
- Réinstallez ou remplacez la carte réseau.
- Changez le port sur le commutateur.
Obtenez l'image ; iperf3 aidera à "brûler" le lien et à déclencher tout comportement indésirable avant d'utiliser cette interface en production.
Voici le processus en action. Supposons que nous prenions le premier instantané sur le serveur iperf3 :
[server ~]$ sudo ethtool --statistics eth0| rg -i -e 'dropped|error'
rx_errors: 0
tx_errors: 0
rx_dropped: 0
tx_dropped: 0
rxq0_errors: 0
rxq0_dropped: 0
rxq1_errors: 0
rxq1_dropped: 0
rxq2_errors: 0
rxq2_dropped: 0
rxq3_errors: 0
rxq3_dropped: 0
rxq16_errors: 0
rxq16_dropped: 0
Alors le client :
[client ~]$ sudo ethtool --statistics eno1| rg -i -e 'dropped|errors'
tx_errors: 0
rx_errors: 0
align_errors: 0
Exécutez le iperf3
serveur:
[server ~]$ iperf3 --server --bind 192.168.1.11
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
Cours iperf3
sur le client pendant 120 secondes :
[client ~]$ iperf3 --client raspberrypi --bind 192.168.1.28 --time 120
Connecting to host raspberrypi, port 5201
[ 5] local 192.168.1.28 port 41337 connected to 192.168.1.11 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 111 MBytes 934 Mbits/sec 0 2.94 MBytes
[ 5] 1.00-2.00 sec 111 MBytes 933 Mbits/sec 0 2.95 MBytes
[ 5] 2.00-3.00 sec 111 MBytes 933 Mbits/sec 0 2.95 MBytes
...
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-120.00 sec 11.0 GBytes 787 Mbits/sec 0 sender
[ 5] 0.00-119.70 sec 11.0 GBytes 789 Mbits/sec receiver
# Measure again ...
[client ~]$ sudo ethtool --statistics eno1| rg -i -e 'dropped|errors'
tx_errors: 0
rx_errors: 0
align_errors: 0
Je vais maintenant parler d'un autre outil utile pour obtenir des statistiques d'interface réseau, ethtool.
Qu'est-ce qu'ethtool ?
Comment expliquez-vous Wikipédia :
ethtool est le principal moyen des systèmes d'exploitation basés sur le noyau Linux (principalement Linux et Android) pour afficher et modifier les paramètres des contrôleurs d'interface réseau (NIC) et du logiciel de pilote de périphérique associé à partir des programmes d'application dans
en cours d'exécution dans l'espace utilisateur.
Voici quelques questions pour vous après avoir vérifié la page homme par ethtool :
- Que fait le
sudo ethtool -g eno1
commande? - Et ça?
sudo ethtool -s eno1 speed 1000 duplex full autoneg on
L'utilitaire ethtool est un autre outil que vous devriez avoir dans votre boîte à outils.
Automatiser iperf3 avec Python 3
Vous remarquerez peut-être qu'iperf3 possède une bibliothèque qui vous permet d'intégrer l'outil à d'autres langages, dont Python :
[client ~]$ rpm -qil iperf3|rg libiperf
/usr/lib64/libiperf.so.0
/usr/lib64/libiperf.so.0.0.0
/usr/share/man/man3/libiperf.3.gz
Il existe plusieurs raccourcis pour Python :
- hyperf3-python a une API pour intégrer iperf3 à Python, en utilisant ces liaisons.
- Il Module Python ethtool il est disponible mais marqué obsolète, mais je l'utiliserai pour les besoins de cette démonstration.
Je ne couvrirai pas l'API ici, mais vous dirigerai plutôt vers le code source d'un script Python qui utilise iperf3 et ethtool pour détecter les erreurs de réseau (comme je l'ai fait manuellement ci-dessus). Vous pouvez le voir fonctionner ci-dessous. Vérifier la dépôt et exécutez le script. Vous serez étonné de voir à quel point il est facile d'automatiser certaines tâches avec Python.
Que pouvez-vous faire ensuite ?
L'apprentissage ne s'arrête jamais, alors voici quelques conseils et observations pour vous aider à continuer :
- Données plus rapides a plusieurs exemples d'utilisation d'iperf avec différents paramètres.
- Veuillez noter qu'isolcpus est considéré comme obsolète et processeur conseillé. Référez-vous à ceci discussion sur le débordement de la pile pour voir comment jouer avec cpuset.
- Vous savez maintenant comment écrire vos propres scripts de dépannage avec l'API Python iperf3. Vous devriez probablement écrire un serveur iperf3 qui peut afficher les résultats à l'aide d'un navigateur Web (peut-être le combiner avec API rapide ?).