about summary refs log tree commit diff
path: root/shared/n-acd
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2018-06-04 00:08:31 +0200
committerMichael Biebl <biebl@debian.org>2018-06-04 00:08:31 +0200
commit0dd9df69fdbd475c48a0c8d5b0a1882550fe7321 (patch)
tree249cf25643b1fe408e10679bb61613bc6540e894 /shared/n-acd
parent2e94a3b93171ab3fb95bf689aab1664d23988809 (diff)
parent04bc9e1cd3544445d883ad29ea108c1645c8e7b7 (diff)
Update upstream source from tag 'upstream/1.11.4'
Update to upstream version '1.11.4'
with Debian dir d0638aa2e32d5bae4e8daa021b9a66b7c4d6647e
Diffstat (limited to 'shared/n-acd')
-rw-r--r--shared/n-acd/src/n-acd.c41
-rw-r--r--shared/n-acd/src/n-acd.h2
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,