Page MenuHomeFreeBSD

D54749.diff
No OneTemporary

D54749.diff

diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h
--- a/sys/netinet6/in6_var.h
+++ b/sys/netinet6/in6_var.h
@@ -134,6 +134,8 @@
* currently used for temporary addresses only.
*/
time_t ia6_updatetime;
+ time_t ia6_dad_lastattempt; /* Last DAD attempt */
+ uint32_t ia6_dad_restarts; /* Number of restarts */
/* back pointer to the ND prefix (for autoconfigured addresses only) */
struct nd_prefix *ia6_ndpr;
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -392,6 +392,7 @@
caddr_t nd6_ifptomac(struct ifnet *);
void nd6_dad_init(void);
void nd6_dad_start(struct ifaddr *, int);
+void nd6_dad_restart(struct in6_ifaddr *);
void nd6_dad_stop(struct ifaddr *);
/* nd6_rtr.c */
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -1030,9 +1030,17 @@
((ifp->if_flags & IFF_UP) == 0 ||
(ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
(ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) != 0)){
+ nd6_dad_stop(&ia6->ia_ifa);
ia6->ia6_flags &= ~IN6_IFF_DUPLICATED;
ia6->ia6_flags |= IN6_IFF_TENTATIVE;
}
+ if ((ia6->ia6_flags & IN6_IFF_DUPLICATED) != 0) {
+ /*
+ * Retry DAD to recover in the case the other
+ * client is no longer using this address
+ */
+ nd6_dad_restart(ia6);
+ }
/*
* A new RA might have made a deprecated address
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -113,6 +113,15 @@
transmit DAD packet */
#define V_dad_maxtry VNET(dad_maxtry)
+#define MAX_DAD_RESTARTS 10 /* Maximum restarts */
+#define DAD_RESTART_INTERVAL 30 /* In seconds */
+
+VNET_DEFINE_STATIC(int, max_dad_restarts) = MAX_DAD_RESTARTS;
+#define V_max_dad_restarts VNET(max_dad_restarts)
+
+SYSCTL_INT(_net_inet6_ip6, OID_AUTO, dad_restart, CTLFLAG_VNET | CTLFLAG_RW,
+ &VNET_NAME(max_dad_restarts), 0, "Maximum DAD restart attempts per address");
+
VNET_DEFINE_STATIC(int, nd6_onlink_ns_rfc4861) = 0;
#define V_nd6_onlink_ns_rfc4861 VNET(nd6_onlink_ns_rfc4861)
SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_ONLINKNSRFC4861,
@@ -1337,6 +1346,33 @@
DADQ_WUNLOCK();
}
+/*
+ * Restarts the Duplicate Address Detection (DAD) process for an IPv6 interface address.
+ *
+ * This function reinitializes the DAD process for the specified IPv6 interface
+ * address (`ia6`). It is typically invoked when a DAD failure occurs or when
+ * the DAD process needs to be retried due to changes in the network state or
+ * configuration.
+ */
+void
+nd6_dad_restart(struct in6_ifaddr *ia6)
+{
+ if (((ia6->ia6_flags & IN6_IFF_DUPLICATED) == 0) ||
+ (ia6->ia6_dad_lastattempt == 0) ||
+ (ia6->ia6_dad_restarts >= V_max_dad_restarts)) {
+ return;
+ }
+
+ if (((time_uptime - ia6->ia6_dad_lastattempt) >= DAD_RESTART_INTERVAL) &&
+ ((ia6->ia6_flags & IN6_IFF_DETACHED) == 0)) {
+ ia6->ia6_dad_lastattempt = 0;
+ ia6->ia6_dad_restarts++;
+ ia6->ia6_flags &= ~IN6_IFF_DUPLICATED;
+ ia6->ia6_flags |= IN6_IFF_TENTATIVE;
+ nd6_dad_start(&ia6->ia_ifa, arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz));
+ }
+}
+
/*
* terminate DAD unconditionally. used for address removals.
*/

File Metadata

Mime Type
text/plain
Expires
Wed, Feb 4, 10:58 PM (11 h, 45 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28438267
Default Alt Text
D54749.diff (3 KB)

Event Timeline