Forum Linux.noyau comment investiguer des "packet receive errors" en UDP ?

Posté par .
Tags : aucun
1
26
mai
2009
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 (page perso) . Évalué à 3.

    Je serai d'avis de dire que si les paquets sont marqués en erreur dans la sortie de netstat, c'est qu'ils ne sont jamais remontés à ton appli pour diverses raisons liées au protocole UDP en lui même.

    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 . Évalué à 2.

      Merci!
      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 (page perso) . Évalué à 1.

        Je pense plutot qu'il s'agit du système qui, débordé par les interruptions (carte réseau & disque) en laisse passer quelques unes.
  • # pistes

    Posté par . É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 . Évalué à 1.

      Merci de tes pistes. J'ai un peu plus d'info, voir mon post précedent.
      • [^] # Re: pistes

        Posté par . Évalué à 4.

        Le problème ce n'est pas ton application qui ne reçoit pas les paquets lorsqu'elle écrit sur le disque : le problème c'est que lorsque tu écris, tu traites les données moins vite, le buffer de ton socket en réception se remplit, et lorsqu'il est plein, les nouveaux paquets reçus sont droppés (en quel langage est implémentée ton appli, tu as des mécanismes de synchronisation?).
        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 . Évalué à 1.

          Depuis plusieurs jours on explore plusieurs pistes. J'ai maintenant la certitude que la perte de paquet est liée a l'application. En effet, si je commente l'écriture sur disque (fonction write()) dans le thread dédié a cela, je ne pert plus aucun paquet.

          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 . Évalué à 3.

            mais il semble perdre certains paquets probablement au moment de l'écriture sur le disque (voir plus haut).
            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 . Évalué à 1.

              J'ai regardé, et les synchro sont bonnes. Il y a un mutex, mais il sert juste a changer le pointeur sur le buffer de reception (il y a un double buffer pour pouvoir recevoir pendant qu'on écrit le buffer sur le disque). La librairie de thread est bien la libpthread. Et on reçoit bien des paquets pendant que le write s'execute.

              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 . Évalué à 1.

            Il faudrait plus d'infos pour t'aider :
            /sbin/ifconfig et cat /proc/net/snmp, pour avoir une idée de la cause des pertes de paquets.
            • [^] # Re: pistes

              Posté par . Évalué à 1.

              Aussi cat /proc/interrupts.

              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 à ceux qui les ont postés. Nous n'en sommes pas responsables.