Separate ARP handling DAD from inet.

This is done by signalling the intent to try tentative addresses
and then clearing the intent once the address is setup.
When the ARP handler is installed (arp_ifinit) then it adds
dad start and stop functions to the address which are used instead
of calling ARP directly.
This commit is contained in:
roy 2015-05-16 12:12:46 +00:00
parent 3333c4c041
commit f45d868787
4 changed files with 36 additions and 33 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_arp.c,v 1.164 2015/05/03 10:44:04 justin Exp $ */
/* $NetBSD: if_arp.c,v 1.165 2015/05/16 12:12:46 roy Exp $ */
/*-
* Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc.
@ -68,7 +68,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.164 2015/05/03 10:44:04 justin Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.165 2015/05/16 12:12:46 roy Exp $");
#include "opt_ddb.h"
#include "opt_inet.h"
@ -164,6 +164,8 @@ static void in_arpinput(struct mbuf *);
static void arp_drainstub(void);
static void arp_dad_timer(struct ifaddr *);
static void arp_dad_start(struct ifaddr *);
static void arp_dad_stop(struct ifaddr *);
static void arp_dad_duplicated(struct ifaddr *);
LIST_HEAD(llinfo_arpq, llinfo_arp) llinfo_arp;
@ -1417,6 +1419,13 @@ arp_ifinit(struct ifnet *ifp, struct ifaddr *ifa)
ifa->ifa_rtrequest = arp_rtrequest;
ifa->ifa_flags |= RTF_CLONING;
/* ARP will handle DAD for this address. */
if (ia->ia4_flags & IN_IFF_TRYTENTATIVE) {
ia->ia4_flags |= IN_IFF_TENTATIVE;
ia->ia_dad_start = arp_dad_start;
ia->ia_dad_stop = arp_dad_stop;
}
}
TAILQ_HEAD(dadq_head, dadq);
@ -1487,7 +1496,7 @@ arp_dad_output(struct dadq *dp, struct ifaddr *ifa)
/*
* Start Duplicate Address Detection (DAD) for specified interface address.
*/
void
static void
arp_dad_start(struct ifaddr *ifa)
{
struct in_ifaddr *ia = (struct in_ifaddr *)ifa;
@ -1559,7 +1568,7 @@ arp_dad_start(struct ifaddr *ifa)
/*
* terminate DAD unconditionally. used for address removals.
*/
void
static void
arp_dad_stop(struct ifaddr *ifa)
{
struct dadq *dp;

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_inarp.h,v 1.45 2015/05/02 14:41:32 roy Exp $ */
/* $NetBSD: if_inarp.h,v 1.46 2015/05/16 12:12:46 roy Exp $ */
/*
* Copyright (c) 1982, 1986, 1993
@ -85,9 +85,6 @@ void arp_drain(void);
int arpioctl(u_long, void *);
void arpwhohas(struct ifnet *, struct in_addr *);
void arp_dad_start(struct ifaddr *);
void arp_dad_stop(struct ifaddr *);
void revarpinput(struct mbuf *);
void in_revarpinput(struct mbuf *);
void revarprequest(struct ifnet *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: in.c,v 1.155 2015/05/05 08:52:51 roy Exp $ */
/* $NetBSD: in.c,v 1.156 2015/05/16 12:12:46 roy Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -91,7 +91,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.155 2015/05/05 08:52:51 roy Exp $");
__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.156 2015/05/16 12:12:46 roy Exp $");
#include "arp.h"
#include "opt_inet.h"
@ -664,10 +664,9 @@ in_purgeaddr(struct ifaddr *ifa)
struct ifnet *ifp = ifa->ifa_ifp;
struct in_ifaddr *ia = (void *) ifa;
#if NARP
/* stop DAD processing */
arp_dad_stop(ifa);
#endif
if (ia->ia_dad_stop != NULL)
ia->ia_dad_stop(ifa);
in_ifscrub(ifp, ia);
in_ifremlocal(ifa);
@ -905,14 +904,13 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia,
ia->ia_addr = *sin;
LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
/* Set IN_IFF flags early for arp_ifinit() */
/* Set IN_IFF flags early for if_addr_init() */
if (hostIsNew && if_do_dad(ifp) && !in_nullhost(ia->ia_addr.sin_addr)) {
if (ifp->if_link_state == LINK_STATE_DOWN)
ia->ia4_flags |= IN_IFF_DETACHED;
#if NARP
else
ia->ia4_flags |= IN_IFF_TENTATIVE;
#endif
/* State the intent to try DAD if possible */
ia->ia4_flags |= IN_IFF_TRYTENTATIVE;
}
/*
@ -922,7 +920,10 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia,
*/
if ((error = if_addr_init(ifp, &ia->ia_ifa, true)) != 0)
goto bad;
/* Now clear the try tentative flag, it's job is done. */
ia->ia4_flags &= ~IN_IFF_TRYTENTATIVE;
splx(s);
if (scrub) {
ia->ia_ifa.ifa_addr = sintosa(&oldaddr);
in_ifscrub(ifp, ia);
@ -984,12 +985,10 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia,
ia->ia_allhosts = in_addmulti(&addr, ifp);
}
#if NARP
if (hostIsNew && if_do_dad(ifp) &&
!in_nullhost(ia->ia_addr.sin_addr) &&
ia->ia4_flags & IN_IFF_TENTATIVE)
arp_dad_start((struct ifaddr *)ia);
#endif
ia->ia_dad_start((struct ifaddr *)ia);
return (error);
bad:
@ -1179,22 +1178,17 @@ in_if_link_up(struct ifnet *ifp)
/* If detached then mark as tentative */
if (ia->ia4_flags & IN_IFF_DETACHED) {
ia->ia4_flags &= ~IN_IFF_DETACHED;
#if NARP
if (if_do_dad(ifp))
if (if_do_dad(ifp) && ia->ia_dad_start != NULL)
ia->ia4_flags |= IN_IFF_TENTATIVE;
else
#endif
if ((ia->ia4_flags & IN_IFF_TENTATIVE) == 0)
else if ((ia->ia4_flags & IN_IFF_TENTATIVE) == 0)
rt_newaddrmsg(RTM_NEWADDR, ifa, 0, NULL);
}
#if NARP
if (ia->ia4_flags & IN_IFF_TENTATIVE) {
/* Clear the duplicated flag as we're starting DAD. */
ia->ia4_flags &= ~IN_IFF_DUPLICATED;
arp_dad_start(ifa);
ia->ia_dad_start(ifa);
}
#endif
}
}
@ -1220,10 +1214,9 @@ in_if_link_down(struct ifnet *ifp)
continue;
ia = (struct in_ifaddr *)ifa;
#if NARP
/* Stop DAD processing */
arp_dad_stop(ifa);
#endif
if (ia->ia_dad_stop != NULL)
ia->ia_dad_stop(ifa);
/*
* Mark the address as detached.

View File

@ -1,4 +1,4 @@
/* $NetBSD: in_var.h,v 1.71 2015/05/02 14:41:32 roy Exp $ */
/* $NetBSD: in_var.h,v 1.72 2015/05/16 12:12:46 roy Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -69,9 +69,11 @@
#define IN_IFF_TENTATIVE 0x01 /* tentative address */
#define IN_IFF_DUPLICATED 0x02 /* DAD detected duplicate */
#define IN_IFF_DETACHED 0x04 /* may be detached from the link */
#define IN_IFF_TRYTENTATIVE 0x08 /* intent to try DAD */
/* do not input/output */
#define IN_IFF_NOTREADY (IN_IFF_TENTATIVE | IN_IFF_DUPLICATED)
#define IN_IFF_NOTREADY \
(IN_IFF_TRYTENTATIVE | IN_IFF_TENTATIVE | IN_IFF_DUPLICATED)
/*
* Interface address, Internet version. One of these structures
@ -100,6 +102,8 @@ struct in_ifaddr {
the allhosts multicast group */
uint16_t ia_idsalt; /* ip_id salt for this ia */
int ia4_flags; /* address flags */
void (*ia_dad_start) (struct ifaddr *); /* DAD start function */
void (*ia_dad_stop) (struct ifaddr *); /* DAD stop function */
};
struct in_aliasreq {