|
Description
|
An IPMP test suite failure revealed an IPv6 DAD bug in Nevada.
Specifically, ipif_up() and ip_rput_dlpi_writer() both have
a similar sequence of:
if (isv6) {
(1) -> err = ipif_ndp_up(ipif);
if (err != 0) {
if (err != EINPROGRESS)
mp = ipsq_pending_mp_get(ipsq, &connp);
return (err);
}
}
/* Now, ARP */
(2) -> err = ipif_resolver_up(ipif, Res_act_initial);
if (err == EINPROGRESS) {
/* We will complete it in ip_arp_done */
return (err);
}
However, there are several cases at (1) where ipif_ndp_up() can set
ipif->ipif_addr_ready (e.g., if the ipif is marked IPIF_NOLOCAL) --
but the call to ipif_resolver_up() ends up clearing ipif_addr_ready
again, rendering the set in ipif_ndp_up() meaningless:
if (res_act == Res_act_initial) {
--> ipif->ipif_addr_ready = 0;
/*
* We're bringing an interface up here. There's no way that we
* should need to shut down ARP now.
*/
mutex_enter(&ill->ill_lock);
if (ipif->ipif_flags & IPIF_DUPLICATE) {
ipif->ipif_flags &= ~IPIF_DUPLICATE;
ill->ill_ipif_dup_count--;
was_dup = B_TRUE;
}
mutex_exit(&ill->ill_lock);
}
From the code, it seems clear that the intent was to have ipif_resolver_up()
initialize the DAD state. As such, it needs to be called prior to calling
ipif_ndp_up(), not afterwards.
|