]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
ARP: Don't send an initial ARP announcement for newly added addresses
authorRoy Marples <roy@marples.name>
Tue, 8 Oct 2019 12:35:50 +0000 (13:35 +0100)
committerRoy Marples <roy@marples.name>
Tue, 8 Oct 2019 12:35:50 +0000 (13:35 +0100)
The kernel will do this for us.

src/arp.c
src/ipv4.c
src/ipv4.h

index 337252117ab5d85ef8d5aa8f703f22017287d7af..55b6203bb99285a5732bf4cd3f5f630dcdc30b1f 100644 (file)
--- a/src/arp.c
+++ b/src/arp.c
@@ -425,6 +425,7 @@ arp_announce1(void *arg)
 {
        struct arp_state *astate = arg;
        struct interface *ifp = astate->iface;
+       struct ipv4_addr *ia;
 
        if (++astate->claims < ANNOUNCE_NUM)
                logdebugx("%s: ARP announcing %s (%d of %d), "
@@ -435,24 +436,26 @@ arp_announce1(void *arg)
                logdebugx("%s: ARP announcing %s (%d of %d)",
                    ifp->name, inet_ntoa(astate->addr),
                    astate->claims, ANNOUNCE_NUM);
+
+       /* The kernel will send a Gratuitous ARP for newly added addresses.
+        * So we can avoid sending the same. */
+       ia = ipv4_iffindaddr(ifp, &astate->addr, NULL);
+       if (astate->claims == 1 && ia != NULL && ia->flags & IPV4_AF_NEW)
+               goto skip_request;
+
        if (arp_request(ifp, &astate->addr, &astate->addr) == -1)
                logerr(__func__);
+
+skip_request:
+       /* No longer a new address. */
+       if (ia != NULL)
+               ia->flags |= ~IPV4_AF_NEW;
+
        eloop_timeout_add_sec(ifp->ctx->eloop, ANNOUNCE_WAIT,
            astate->claims < ANNOUNCE_NUM ? arp_announce1 : arp_announced,
            astate);
 }
 
-/*
- * XXX FIXME
- * Kernels supporting RFC5227 will announce the address when it's
- * added.
- * dhcpcd should not announce when this happens, nor need to open
- * a BPF socket for it.
- * Also, an address might be added to a non preferred inteface when
- * the same address exists on a preferred one so we need to instruct
- * the kernel not to announce the address somehow.
- */
-
 void
 arp_announce(struct arp_state *astate)
 {
@@ -498,6 +501,9 @@ arp_ifannounceaddr(struct interface *ifp, const struct in_addr *ia)
 {
        struct arp_state *astate;
 
+       if (ifp->flags & IFF_NOARP)
+               return;
+
        astate = arp_find(ifp, ia);
        if (astate == NULL) {
                astate = arp_new(ifp, ia);
index 8c89dc73ef73a65abcc256016b09c0478a9cfe5f..c55a7da6cb1d61c766c765596a3b1143f5e5fae5 100644 (file)
@@ -622,7 +622,6 @@ ipv4_addaddr(struct interface *ifp, const struct in_addr *addr,
 {
        struct ipv4_state *state;
        struct ipv4_addr *ia;
-       bool is_new = false;
 #ifdef ALIAS_ADDR
        int replaced, blank;
        struct ipv4_addr *replaced_ia;
@@ -653,8 +652,9 @@ ipv4_addaddr(struct interface *ifp, const struct in_addr *addr,
 #ifdef IN_IFF_TENTATIVE
                ia->addr_flags = IN_IFF_TENTATIVE;
 #endif
-               is_new = true;
-       }
+               ia->flags = IPV4_AF_NEW;
+       } else
+               ia->flags |= ~IPV4_AF_NEW;
 
        ia->mask = *mask;
        ia->brd = *bcast;
@@ -698,7 +698,7 @@ ipv4_addaddr(struct interface *ifp, const struct in_addr *addr,
        }
 #endif
 
-       if (is_new)
+       if (ia->flags & IPV4_AF_NEW)
                TAILQ_INSERT_TAIL(&state->addrs, ia, next);
        return ia;
 }
@@ -743,8 +743,7 @@ ipv4_applyaddr(void *arg)
 #ifdef ARP
                                /* Announce the preferred address to
                                 * kick ARP caches. */
-                               if (!(ifp->flags & IFF_NOARP))
-                                       arp_announceaddr(ifp->ctx,&lease->addr);
+                               arp_announceaddr(ifp->ctx,&lease->addr);
 #endif
                        }
                        script_runreason(ifp, state->reason);
@@ -806,8 +805,7 @@ ipv4_applyaddr(void *arg)
        rt_build(ifp->ctx, AF_INET);
 
 #ifdef ARP
-       if (!(ifp->flags & IFF_NOARP))
-               arp_announceaddr(ifp->ctx, &state->addr->addr);
+       arp_announceaddr(ifp->ctx, &state->addr->addr);
 #endif
 
        if (state->state == DHS_BOUND) {
index eaa0dcce9ab9fbfcf1bd845dcef017bf697ed15b..59b48a53b04d5fed71d1621aac390a09aefe5d8f 100644 (file)
@@ -100,6 +100,7 @@ struct ipv4_addr {
 TAILQ_HEAD(ipv4_addrhead, ipv4_addr);
 
 #define        IPV4_AF_STALE           (1U << 0)
+#define        IPV4_AF_NEW             (1U << 1)
 
 #define        IPV4_ADDR_EQ(a1, a2)    ((a1) && (a1)->addr.s_addr == (a2)->addr.s_addr)
 #define        IPV4_MASK1_EQ(a1, a2)   ((a1) && (a1)->mask.s_addr == (a2)->mask.s_addr)