2017-01-10 1 views
1

J'ai rencontré une situation très étrange.sendto() renvoie le code d'erreur ENETDOWN

Dans mon programme, la fonction sendto() renvoie le code d'erreur ENETDOWN(Network is down) même si le réseau est en cours et que ping tryout a abouti.

Il s'est produit uniquement lorsque le flux UDP se connecte à un autre réseau via plusieurs passerelles. Ce n'est pas toujours et arrive parfois. Si je cours le même code sous le même sous-réseau, il n'y a pas d'erreur comme ENETDOWN. Donc, je trace sendto() fonction à Zone du noyau. La fonction neigh_hh_output() dans ip_finish_output2() de iop_output.c appelle hh->hh_output() et il renvoie le code d'erreur ENETDOWN.

En fonctionnement normal, la fonction hh->hh_output() est affectée à dev_queue_xmit() de dev.c et les paquets sont envoyés au réseau.

Lorsqu'un problème est survenu, il semble affecté à la fonction neigh_blackhole() dans neigh_destroy() de neighbour.c. Le neigh_blackhole() renvoie le code -ENETDOWN. Mais, je ne sais pas quand le neigh_destroy() est appelé et pourquoi cette fonction est appelée.

Je suis aux prises avec ce problème depuis plusieurs semaines.

Répondre

0

Il est revendiqué qu'un voisin sera supprimé pour une variété de raisons, y compris l'hôte a changé son adresse de couche 2 tout en conservant son adresse de couche 3 ou n'est plus accessible. Voir this. Il peut également être supprimé si la passerelle pour le voisin envoie une redirection ICMP et que le traitement des redirections est activé dans le noyau.

Si le voisin est en cours de suppression, le paquet est envoyé à neigh_blackhole qui renvoie inconditionnellement -ENETDOWN. Voir le code here.

La page de manuel pour sendto() vous amènerait à croire que vous ne devriez pas obtenir -ENETDOWN dans de telles circonstances, mais cela semble être incorrect. Je voudrais essayer d'obtenir une capture réseau lorsque cela se produit et rechercher des messages ICMP indiquant que votre destination n'est pas accessible ou pour un changement de l'adresse MAC de la destination (ou éventuellement une adresse IP dupliquée) via des paquets ARP ou le Adresses MAC sur les paquets arrivant de la destination.

+0

Si la machine sur laquelle mon programme s'exécute reçoit un message de redirection ICMP, est-ce que le voisin peut supprimer? – shin2011

+1

Je peux voir le message de redirection ICMP qui a le code "rediriger pour l'hôte" et la nouvelle adresse de passerelle. – shin2011

+0

Je n'ai pas regardé le code du noyau pour voir si une redirection ICMP causerait cela, mais c'est certainement possible. Je conseillerais de traiter l'erreur -ENETDOWN comme quelque chose de transitoire et de réessayer, peut-être avec un retard et peut-être aussi avec un backoff. –

1

Ma machine d'essai est placée comme ci-dessous la description. Machine d'essai --- passerelle (1.1.1.1) --- pare-feu (1.1.1.2) --- réseau ---- Destination.

Première connexion UDP établie entre ma machine de test et la destination et l'adresse de passerelle de ma machine de test est 1.1.1.1. Le trafic n'a aucun problème entre la destination de la machine de test. Après un certain temps ou juste après, soudainement, le trafic de transmission échoue avec l'erreur "Network is Down" (numéro d'erreur 100, ENETDOWN). À ce moment, si j'essaie d'envoyer une requête ping à la destination sur mon ordinateur de test, lancez une réponse ping OK. Lorsque je capture le paquet devant ma machine de test, le message de redirection ICMP provient de la passerelle (1.1.1.1). Son information est "Rediriger pour l'hôte" et l'adresse de la nouvelle porte est "1.1.1.2". Lorsque le système d'exploitation de ma machine de test (Linux 3.0.35) a reçu le message de redirection ICMP, il change le pointeur de fonction virtuelle de hh-> hh_output() de ev_queue_xmit() en neigh_blackhole(). Finalement, neigh_blackhole() retourne le code -ENETDOWN. Donc, changez l'adresse de porte de ma machine de test en 1.1.1.2. Après cela, "Network is down" erreur n'est pas encore arrivé. Je pense que c'est une opération étrange. La fonction sendto() ne renvoie pas le code ENETDOWN en tant que page de manuel. Mais, c'est le retour du code ENETDOWN. Quoi qu'il en soit, si la fonction sendto() renvoie -ENETDOWN même si l'interface réseau est mise à jour, comment résoudre cette erreur? Est-ce que je reconnecte le flux UDP?

Je me demande ce problème est le bogue de Linux kernel 3.0.35.

Si je vais savoir ou trouver quelque chose à propos de ce problème, je vais mettre à jour ici. S'il vous plaît référence mon cas si quelqu'un a un problème similaire avec moi.