2017-01-10 2 views
1

매우 이상한 상황을 만났습니다.sendto() 반환 오류 코드 ENETDOWN

내 프로그램에서 sendto() 함수는 네트워크가 작동 중이고 trying이 성공하더라도 오류 코드 ENETDOWN(Network is down)을 반환합니다.

스트림이 UDP 스트림이 여러 게이트웨이를 통해 다른 네트워크에 연결될 때만 발생합니다. 가끔은 항상 그런 것은 아닙니다. 동일한 서브 네트워크에서 동일한 코드를 실행하면 ENETDOWN과 같은 오류가 없습니다.

그래서 sendto()커널 영역으로 추적됩니다. 의 함수는 ip_finish_output2()iop_output.c이고 hh->hh_output()을 호출하고 ENETDOWN 오류 코드를 반환합니다.

정상적으로 작동하면 hh->hh_output() 기능이 에 할당되고 패킷이 네트워크로 전송됩니다.

문제가 발생하면 의 neigh_blackhole() 기능에 할당 된 것으로 보입니다. neighbour.c입니다. neigh_blackhole()-ENETDOWN 코드를 반환합니다.

그러나 언제 neigh_destroy()이 호출되는지, 왜 그 기능이 호출되는지는 알 수 없습니다.

저는 몇 주 동안이 문제로 고심하고 있습니다.

답변

0

호스트가 계층 3 주소를 유지하면서 계층 2 주소를 변경했거나 더 이상 도달 할 수없는 경우를 포함하여 다양한 이유로 인해 이웃 노드가 삭제 될 것이라고 주장됩니다. this을 참조하십시오. 또한 이웃을위한 게이트웨이가 ICMP 리다이렉트를 보내고 리다이렉션 처리가 커널에서 활성화되면 삭제 될 수 있습니다.

이웃 노드가 삭제되는 과정에있는 경우, 그 패킷은 neigh_blackhole에 전달되어 무조건 -ENETDOWN을 반환합니다. 코드 here을 참조하십시오.

설명서 페이지가 sendto() 인 경우 이러한 상황에서 -ENETDOWN을 얻지 않아야한다고 생각할 수 있습니다.하지만 이는 잘못된 것 같습니다.

이 경우 네트워크 캡처를 시도하고 대상이 도달 할 수 없거나 대상 (또는 가능하면 중복 된 IP 주소)의 MAC 주소가 ARP 패킷 또는 MAC 주소를 통해 변경되었음을 나타내는 ICMP 메시지를 찾으려고합니다. 대상에서 도착 패킷에 대한 MAC 주소

+0

내 프로그램이 실행되는 컴퓨터가 ICMP 리디렉션 메시지를받는 경우 인접 프로그램을 제거 할 수 있습니까? – shin2011

+1

"호스트로 리디렉션"코드와 새 게이트웨이 주소가있는 ICMP 리디렉션 메시지를 볼 수 있습니다. – shin2011

+0

ICMP 리다이렉트가 원인인지 알기 위해 커널 코드를 보지 않았지만 확실히 가능합니다. -ENETDOWN 오류를 일시적인 것으로 처리하고 다시 시도하는 것을 권장합니다. 아마도 지연과 어쩌면 백 오프로 처리 할 수도 있습니다. –

1

내 시험기는 아래 설명과 같이 배치됩니다. 시험 기계 --- 게이트웨이 (1.1.1.1) --- 방화벽 (1.1.1.2) --- 네트워크 ---- 목적지.

처음으로 내 테스트 컴퓨터와 내 테스트 컴퓨터의 대상 및 게이트웨이 주소 간의 UDP 연결 설정은 1.1.1.1입니다. 테스트 대상 컴퓨터 사이에는 트래픽에 문제가 없습니다. 잠시 후 또는 갑자기 "네트워크가 다운 됨"오류 (오류 번호 100, ENETDOWN)로 트래픽 전송이 실패합니다. 현재 테스트 머신에서 목적지로 ping을 시도하면 응답이 ping됩니다. 테스트 머신의 패킷 앞부분을 캡처 할 때 ICMP 리디렉션 메시지는 게이트웨이 (1.1.1.1)에서 나옵니다. 정보는 "호스트로 방향 재 지정"이고 새 게이트 주소는 "1.1.1.2"입니다. 테스트 머신의 OS (Linux 3.0.35)가 ICMP 리다이렉트 메시지를 받으면, hh-> hh_output()의 가상 함수 포인터를 ev_queue_xmit()에서 neigh_blackhole()으로 바꾼다. 결국 neighb_blackhole()은 -ENETDOWN 코드를 반환합니다.

그래서 내 테스트 컴퓨터의 게이트 주소를 1.1.1.2로 변경하십시오. 그 후에, "Network is down"오류가 다시 발생하지 않습니다.

이상한 조작이라고 생각합니다. sendto() 함수는 맨 페이지로 ENETDOWN 코드를 반환하지 않습니다. 하지만 ENETDOWN 코드가 반환됩니다. 네트워크 인터페이스가 업데이트 되더라도 sendto() 함수가 -ENETDOWN을 반환하면이 오류를 어떻게 극복 할 수 있습니까? UDP 스트림을 다시 연결합니까?

이 문제는 Linux 커널 3.0.35의 버그입니다.

내가이 문제에 대해 알고 있거나 발견하면 여기에서 업데이트 할 것입니다. 나와 비슷한 문제가있는 경우 사례를 참조하십시오.

관련 문제