Bonjour a tous,
Je suis en train de tester une appli qui enregistre des paquets UPD arrivant sur une interface réseau. Je post-traite ensuite les fichiers enregistrés. Et je trouve que certains paquets manquent. Par exemple, j'envoie 1 million de paquet, et j'en reçois 1 million moins 48.
Or si je fais un "netstat -su" avant et après, je peux voir que le champ "packet receive errors" a augmenté de 48. Ces paquets UDP ont donc bien atteints la machine cible, par contre je ne sais pas ce qui leurs est arrivé. Et je ne sais pas trop investiguer ça, c'est un domaine que je ne connais pas.
Je ne sais pas si c'est mon appli qui ne fait son travail (récupérer les paquets UDP) ou si mon appli ne les voit même pas (paquets bloqués quelque part ?). Il doit probablement y avoir des fichier de log que le noyau linux créé quelque part, mais je ne sais pas ou regarder.
Quelques pistes pour m'orienter ?
Merci
# Mon avis
Posté par LaBienPensanceMaTuer . Évalué à 3.
En effet, le User_Datagram_Protocol c'est un peu le protocole réseau du on fait au mieux, dixit la définition wikipedia:
Contrairement au protocole TCP, il travaille en mode non-connecté : il n'y a pas de moyen de vérifier si tous les paquets envoyés sont bien arrivés à destination et ni dans quel ordre (le séquencement peut cependant être assuré par un protocole réseau de couche inférieure). Il n'est prévu aucun contrôle de flux ni contrôle de congestion. C'est pour cela qu'il est souvent décrit comme étant un protocole non-fiable. En revanche, pour un paquet UDP donné, l'exactitude du contenu des données est assurée grâce à une somme de contrôle (checksum).
Vu tes symptomes, je serai d'avis de dire que c'est 48 paquets sont mauvais et on été rejetés par la pile réseau (mauvaise transmission et checksum mauvais, ou encore buffer de ta carte réseau trop rempli, ...).
[^] # Re: Mon avis
Posté par fabricius . Évalué à 2.
J'ai fait un test et j'ai désactivé l'écriture sur disque, et la plus de problème, je reçoit bien mon million de paquet.
Je soupçonne donc mon application (avec des threads) de ne plus écouter lors de l'écriture sur disque. Pourtant c'est censé etre fait: il y a 2 threads. Un qui reçoit et un qui écrit sur disque (pour simplifier).
[^] # Re: Mon avis
Posté par LaBienPensanceMaTuer . Évalué à 1.
# pistes
Posté par neologix . Évalué à 2.
/sbin/ifconfig
cat /proc/net/snmp
Causes possibles, :
- buffer du socket plein (plus probable, modifiable avec sysctl)
- rx_ring de la carte pleine
[^] # Re: pistes
Posté par fabricius . Évalué à 1.
[^] # Re: pistes
Posté par neologix . Évalué à 4.
Tu peux vérifier en faisant un netstat pendant que tu reçois des paquets, tu dois voir la recv-q de ton socket augmenter.
Tu peux essayer d'augmenter la taille maximum du buffer en faisant :
sysctl -w net.core.rmem_max=8388608
par exemple.[^] # Re: pistes
Posté par fabricius . Évalué à 1.
L'appli est écrite en C++, et il a un mécanisme de synchro des threads. Pendant l'écriture sur disque, le thread "receveur" continue son travail (recevoir des paquets UDP) mais il semble perdre certains paquets probablement au moment de l'écriture sur le disque (voir plus haut).
Le débit n'est même pas énorme: j'ai des pertes pour 20 Mb/s ! Pas beaucoup, mais c'est quand meme génant (de 50 a 2000 paquets sur 1 million). Du coup, la recv-q augmente tres peu, ce débit est assez faible. Ce sont des tout petit paquets qui partent (de 300 a 500 octets).
Quant à la variable net.core.rmem_max, impossible de la setter: "Operation not permitted". Je vais demander a mon admin.
Que vaut-il mieux employer comme fonction pour recevoir les paquets ?
recfromv() ou read() ? Avec les deux j'ai des pertes.
Merci pour ton aide.
[^] # Re: pistes
Posté par briaeros007 . Évalué à 3.
Un appel système bloque le thread qui l'apelle (le thread est dans le noyau). Tu utilise bien libpthread normal et pas une librairie de thread utilisateur pour ton programme ?
La synchro s'effectue comment ? Style pas un mutex avant de rentrer dans le write, et qui le libère à la sortie, qui bloquerais le thread receveur pendant ce temps ?
Pour read/redcvfrom , pour moi c'est bonnet blanc et blanc bonnet, mais je peux me tromper
[^] # Re: pistes
Posté par fabricius . Évalué à 1.
Ce qui est étrange, c'est que si on augmente la taille des paquets envoyés (de 300 octets a 1490 octets), alors on n'en perd plus.
Pour l'instant, j'essaie de setter la variable SO_RCVLOWAT pour la mettre a une valeur plus grande que 1 (valeur par defaut) pour que la socket UDP ne me dérange pas à chaque fois qu'il y a au moins un bit à lire (je pourrais lire un certain nombre de paquets plutot que lire x fois des petits paquets. Ca changerait peut etre quelque chose.
[^] # Re: pistes
Posté par fabricius . Évalué à 1.
http://fixunix.com/unix/552109-select-least-n-bytes-readable(...)
il est inutile de setter la variable SO_RCVLOWAT en UDP. La socket se reveillera de toute façon quand on aura une trame UDP complete. Mauvaise piste!
[^] # Re: pistes
Posté par neologix . Évalué à 1.
/sbin/ifconfig et cat /proc/net/snmp, pour avoir une idée de la cause des pertes de paquets.
[^] # Re: pistes
Posté par neologix . Évalué à 1.
Sinon, est-ce que tu écris les paquets sur le disque dès qu'il arrivent ? Essaie de grouper les écritures en utilisant un buffer ou en procédant de façon périodique ou mieux, utilise fwrite au lieu de write.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.