naccyde / rpms / iproute

Forked from rpms/iproute 5 months ago
Clone
Blob Blame History Raw
From fe077314f11f76536a7952e8b96951be104f89d1 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Wed, 17 Feb 2016 14:03:59 +0100
Subject: [PATCH] iproute2: Ignore EADDRNOTAVAIL errors during address flush
 operation

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1291825
Upstream Status: commit e149d4e84384f

commit e149d4e84384f88965ce43a6390acf7ba356187c
Author: Neil Horman <nhorman@tuxdriver.com>
Date:   Thu Nov 5 14:54:17 2015 -0500

    iproute2: Ignore EADDRNOTAVAIL errors during address flush operation

    I found recently that, if I disabled address promotion in the kernel, that
    ip addr flush dev <dev>

    would fail with an EADDRNOTAVAIL errno (though the flush operation would in fact
    flush all addresses from an interface properly)

    Whats happening is that, if I add a primary and multiple secondary addresses to
    an interface, the flush operation first ennumerates them all with a GETADDR |
    DUMP operation, then sends a delete request for each address.  But the kernel,
    having promotion disabled, deletes all secondary addresses when the primary is
    removed.  That means, that several delete requests may still be pending in the
    netlink request for addresses that have been removed on our behalf, resulting in
    EADDRNOTAVAIL return codes.

    It seems the simplest thing to do is to understand that EADDRUNAVAIL isn't a
    fatal outcome on a flush operation, as it just indicates that an address which
    you want to remove is already removed, so it can safely be ignored.

    Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
    CC: Stephen Hemminger <stephen@networkplumber.org>
    CC: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
---
 ip/ipaddress.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 53c7001..f4537db 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -651,7 +651,17 @@ int print_linkinfo(const struct sockaddr_nl *who,
 
 static int flush_update(void)
 {
-	if (rtnl_send_check(&rth, filter.flushb, filter.flushp) < 0) {
+
+	/*
+	 * Note that the kernel may delete multiple addresses for one
+	 * delete request (e.g. if ipv4 address promotion is disabled).
+	 * Since a flush operation is really a series of delete requests
+	 * its possible that we may request an address delete that has
+	 * already been done by the kernel. Therefore, ignore EADDRNOTAVAIL
+	 * errors returned from a flush request
+	 */
+	if ((rtnl_send_check(&rth, filter.flushb, filter.flushp) < 0) &&
+	    (errno != EADDRNOTAVAIL)) {
 		perror("Failed to send flush request");
 		return -1;
 	}
-- 
1.8.3.1