diff options
Diffstat (limited to 'shared/n-acd')
| -rw-r--r-- | shared/n-acd/src/n-acd.c | 41 | ||||
| -rw-r--r-- | shared/n-acd/src/n-acd.h | 2 |
2 files changed, 31 insertions, 12 deletions
diff --git a/shared/n-acd/src/n-acd.c b/shared/n-acd/src/n-acd.c index ae149abb..9164f958 100644 --- a/shared/n-acd/src/n-acd.c +++ b/shared/n-acd/src/n-acd.c @@ -534,7 +534,11 @@ static int n_acd_handle_timeout(NAcd *acd) { */ r = n_acd_send(acd, NULL); - if (r < 0) + /* + * During probe we must respect the total timeout and so + * we ignore errors caused by a down interface. + */ + if (r < 0 && r != -N_ACD_E_DOWN) return r; if (++acd->n_iteration >= N_ACD_RFC_PROBE_NUM) @@ -559,11 +563,26 @@ static int n_acd_handle_timeout(NAcd *acd) { */ r = n_acd_send(acd, &acd->config.ip); - if (r < 0) - return r; + if (r < 0) { + if (r != -N_ACD_E_DOWN) + return r; + /* + * We want to send all the 3 announcements even if the + * interface goes temporarily down. Therefore, if send() + * fails, don't increment the iteration and try again. + */ + } else + acd->n_iteration++; - if (++acd->n_iteration < N_ACD_RFC_ANNOUNCE_NUM) { - r = n_acd_schedule(acd, acd->timeout_multiplier * N_ACD_RFC_ANNOUNCE_INTERVAL_USEC, 0); + if (acd->n_iteration < N_ACD_RFC_ANNOUNCE_NUM) { + /* + * Announcements are always scheduled according to the + * time-intervals specified in the spec. We always use + * the RFC5227-mandated multiplier. + * If you reconsider this, note that timeout_multiplier + * might be 0 here. + */ + r = n_acd_schedule(acd, N_ACD_TIMEOUT_RFC5227 * N_ACD_RFC_ANNOUNCE_INTERVAL_USEC, 0); if (r < 0) return r; } @@ -803,14 +822,12 @@ static int n_acd_dispatch_socket(NAcd *acd, struct epoll_event *event) { return -EIO; } else if (errno == ENETDOWN || errno == ENXIO) { /* - * We get ENETDOWN if the network-device goes down or is - * removed. ENXIO might happen on async send-operations if the - * network-device was unplugged and thus the kernel is no - * longer aware of it. - * In any case, we do not allow proceeding with this socket. We - * stop the engine and notify the user gracefully. + * The network device went down or was removed. Ignore + * such errors and let the pending probe time out. + * Subsequent reads will simply return EAGAIN until the + * device is up again and has data queued. */ - return -N_ACD_E_DOWN; + return 0; } else if (errno == EAGAIN) { /* * We cannot read data from the socket (we got EAGAIN). As a safety net diff --git a/shared/n-acd/src/n-acd.h b/shared/n-acd/src/n-acd.h index 46394dca..75646243 100644 --- a/shared/n-acd/src/n-acd.h +++ b/shared/n-acd/src/n-acd.h @@ -15,6 +15,8 @@ extern "C" { #include <netinet/in.h> #include <stdbool.h> +#define N_ACD_TIMEOUT_RFC5227 (UINT64_C(9000)) + enum { _N_ACD_E_SUCCESS, |