summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/uts/common/inet/ip.h44
-rw-r--r--usr/src/uts/common/inet/ip/ip.c506
-rw-r--r--usr/src/uts/common/inet/ip/ip6_if.c18
-rw-r--r--usr/src/uts/common/inet/ip/ip_if.c386
-rw-r--r--usr/src/uts/common/inet/ip/ip_ndp.c4
-rw-r--r--usr/src/uts/common/inet/ip_if.h8
-rw-r--r--usr/src/uts/common/sys/stream.h3
-rw-r--r--usr/src/uts/common/sys/strsun.h3
8 files changed, 481 insertions, 491 deletions
diff --git a/usr/src/uts/common/inet/ip.h b/usr/src/uts/common/inet/ip.h
index e7036a106e..909a1a71a2 100644
--- a/usr/src/uts/common/inet/ip.h
+++ b/usr/src/uts/common/inet/ip.h
@@ -1326,13 +1326,13 @@ typedef struct ipif_s {
* Table of ipif_t members and their protection
*
* ipif_next ill_g_lock ill_g_lock
- * ipif_ill ipsq + down ipif write once
- * ipif_id ipsq + down ipif write once
+ * ipif_ill ipsq + down ipif write once
+ * ipif_id ipsq + down ipif write once
* ipif_mtu ipsq
- * ipif_v6lcl_addr ipsq + down ipif up ipif
- * ipif_v6src_addr ipsq + down ipif up ipif
- * ipif_v6subnet ipsq + down ipif up ipif
- * ipif_v6net_mask ipsq + down ipif up ipif
+ * ipif_v6lcl_addr ipsq + down ipif up ipif
+ * ipif_v6src_addr ipsq + down ipif up ipif
+ * ipif_v6subnet ipsq + down ipif up ipif
+ * ipif_v6net_mask ipsq + down ipif up ipif
*
* ipif_v6brd_addr
* ipif_v6pp_dst_addr
@@ -1404,6 +1404,7 @@ typedef struct ipif_s {
#define CONN_CLOSE 1 /* No mi_copy */
#define COPYOUT 2 /* do an mi_copyout if needed */
#define NO_COPYOUT 3 /* do an mi_copy_done */
+#define IPI2MODE(ipi) ((ipi)->ipi_flags & IPI_GET_CMD ? COPYOUT : NO_COPYOUT)
/*
* The IP-MT design revolves around the serialization object ipsq_t.
@@ -1428,14 +1429,15 @@ typedef struct ipif_s {
typedef struct ipsq_s {
kmutex_t ipsq_lock;
int ipsq_reentry_cnt;
- kthread_t *ipsq_writer; /* current owner (thread id) */
+ kthread_t *ipsq_writer; /* current owner (thread id) */
int ipsq_flags;
mblk_t *ipsq_xopq_mphead; /* list of excl ops mostly ioctls */
mblk_t *ipsq_xopq_mptail;
mblk_t *ipsq_mphead; /* msgs on ipsq linked thru b_next */
mblk_t *ipsq_mptail; /* msgs on ipsq linked thru b_next */
+ int ipsq_current_ioctl; /* current ioctl, or 0 if no ioctl */
+ ipif_t *ipsq_current_ipif; /* ipif associated with current op */
ipif_t *ipsq_pending_ipif; /* ipif associated w. ipsq_pending_mp */
- ipif_t *ipsq_current_ipif; /* ipif associated with current ioctl */
mblk_t *ipsq_pending_mp; /* current ioctl mp while waiting for */
/* response from another module */
struct ipsq_s *ipsq_next; /* list of all syncq's (ipsq_g_list) */
@@ -1444,7 +1446,7 @@ typedef struct ipsq_s {
boolean_t ipsq_split; /* ipsq may need to be split */
int ipsq_waitfor; /* Values encoded below */
char ipsq_name[LIFNAMSIZ+1]; /* same as phyint_groupname */
- int ipsq_last_cmd; /* debugging aid */
+
#ifdef ILL_DEBUG
int ipsq_depth; /* debugging aid */
pc_t ipsq_stack[IP_STACK_DEPTH]; /* debugging aid */
@@ -1990,11 +1992,11 @@ extern void ill_delete_glist(ill_t *);
* ill_ipif_up_count ill_lock + ipsq ill_lock
* ill_max_frag ipsq Write once
*
- * ill_name ill_g_lock + ipsq Write once
- * ill_name_length ill_g_lock + ipsq Write once
+ * ill_name ill_g_lock + ipsq Write once
+ * ill_name_length ill_g_lock + ipsq Write once
* ill_ndd_name ipsq Write once
* ill_net_type ipsq Write once
- * ill_ppa ill_g_lock + ipsq Write once
+ * ill_ppa ill_g_lock + ipsq Write once
* ill_sap ipsq + down ill Write once
* ill_sap_length ipsq + down ill Write once
* ill_phys_addr_length ipsq + down ill Write once
@@ -2020,9 +2022,8 @@ extern void ill_delete_glist(ill_t *);
* ill_down_mp ipsq ipsq
* ill_dlpi_deferred ipsq ipsq
* ill_dlpi_pending ipsq and ill_lock ipsq or ill_lock
- * ill_phys_addr_mp ipsq ipsq
- * ill_phys_addr ipsq up ill
- * ill_ick ipsq + down ill only when ill is up
+ * ill_phys_addr_mp ipsq + down ill only when ill is up
+ * ill_phys_addr ipsq + down ill only when ill is up
*
* ill_state_flags ill_lock ill_lock
* exclusive bit flags ipsq_t ipsq_t
@@ -2041,7 +2042,7 @@ extern void ill_delete_glist(ill_t *);
* ill_max_mtu
*
* ill_reachable_time ipsq + ill_lock ill_lock
- * ill_reachable_retrans_time ipsq + ill_lock ill_lock
+ * ill_reachable_retrans_time ipsq + ill_lock ill_lock
* ill_max_buf ipsq + ill_lock ill_lock
*
* Next 2 fields need ill_lock because of the get ioctls. They should not
@@ -2063,12 +2064,12 @@ extern void ill_delete_glist(ill_t *);
* ill_mrtun_refcnt ill_lock ill_lock
* ill_srcif_refcnt ill_lock ill_lock
* ill_srcif_table ill_lock ill_lock
- * ill_nd_lla_mp ill_lock ill_lock
- * ill_nd_lla ill_lock ill_lock
- * ill_nd_lla_len ill_lock ill_lock
+ * ill_nd_lla_mp ipsq + down ill only when ill is up
+ * ill_nd_lla ipsq + down ill only when ill is up
+ * ill_nd_lla_len ipsq + down ill only when ill is up
* ill_phys_addr_pend ipsq + down ill only when ill is up
* ill_ifname_pending_err ipsq ipsq
- * ill_avl_byppa ipsq, ill_g_lock Write once
+ * ill_avl_byppa ipsq, ill_g_lock write once
*
* ill_fastpath_list ill_lock ill_lock
* ill_refcnt ill_lock ill_lock
@@ -3289,8 +3290,7 @@ extern void ip_process_ioctl(ipsq_t *, queue_t *, mblk_t *, void *);
extern void ip_quiesce_conn(conn_t *);
extern void ip_reprocess_ioctl(ipsq_t *, queue_t *, mblk_t *, void *);
extern void ip_restart_optmgmt(ipsq_t *, queue_t *, mblk_t *, void *);
-extern void ip_ioctl_finish(queue_t *, mblk_t *, int, int, ipif_t *,
- ipsq_t *);
+extern void ip_ioctl_finish(queue_t *, mblk_t *, int, int, ipsq_t *);
extern boolean_t ip_cmpbuf(const void *, uint_t, boolean_t, const void *,
uint_t);
diff --git a/usr/src/uts/common/inet/ip/ip.c b/usr/src/uts/common/inet/ip/ip.c
index 5e09b7b743..328026159d 100644
--- a/usr/src/uts/common/inet/ip/ip.c
+++ b/usr/src/uts/common/inet/ip/ip.c
@@ -15436,9 +15436,8 @@ ip_rput_dlpi_writer(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
ipif_t *ipif = NULL;
mblk_t *mp1 = NULL;
conn_t *connp = NULL;
- t_uscalar_t physaddr_req;
+ t_uscalar_t paddrreq;
mblk_t *mp_hw;
- union DL_primitives *dlp;
boolean_t success;
boolean_t ioctl_aborted = B_FALSE;
boolean_t log = B_TRUE;
@@ -15492,13 +15491,13 @@ ip_rput_dlpi_writer(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
* We don't complete the IOCTL until all three DL_PARs
* have been attempted, so set *_len to 0 and break.
*/
- physaddr_req = ill->ill_phys_addr_pend;
+ paddrreq = ill->ill_phys_addr_pend;
ill_dlpi_done(ill, DL_PHYS_ADDR_REQ);
- if (physaddr_req == DL_IPV6_TOKEN) {
+ if (paddrreq == DL_IPV6_TOKEN) {
ill->ill_token_length = 0;
log = B_FALSE;
break;
- } else if (physaddr_req == DL_IPV6_LINK_LAYER_ADDR) {
+ } else if (paddrreq == DL_IPV6_LINK_LAYER_ADDR) {
ill->ill_nd_lla_len = 0;
log = B_FALSE;
break;
@@ -15672,6 +15671,10 @@ ip_rput_dlpi_writer(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
mp1 = ipsq_pending_mp_get(ipsq, &connp);
if (mp1 == NULL)
break;
+ /*
+ * Because mp1 was added by ill_dl_up(), and it always
+ * passes a valid connp, connp must be valid here.
+ */
ASSERT(connp != NULL);
q = CONNP_TO_WQ(connp);
@@ -15730,8 +15733,7 @@ ip_rput_dlpi_writer(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
* in ip_rput(). If there's an error, we
* complete it here.
*/
- err = ipif_ndp_up(ipif, &ipif->ipif_v6lcl_addr,
- B_FALSE);
+ err = ipif_ndp_up(ipif, &ipif->ipif_v6lcl_addr);
if (err == 0) {
if (ill->ill_flags & ILLF_XRESOLV) {
mutex_enter(&connp->conn_lock);
@@ -15811,148 +15813,15 @@ ip_rput_dlpi_writer(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
boolean_t need_ire_walk_v4 = B_FALSE;
boolean_t need_ire_walk_v6 = B_FALSE;
- /*
- * Change the address everywhere we need to.
- * What we're getting here is a link-level addr or phys addr.
- * The new addr is at notify + notify->dl_addr_offset
- * The address length is notify->dl_addr_length;
- */
switch (notify->dl_notification) {
case DL_NOTE_PHYS_ADDR:
- mp_hw = copyb(mp);
- if (mp_hw == NULL) {
- err = ENOMEM;
- break;
- }
- dlp = (union DL_primitives *)mp_hw->b_rptr;
- /*
- * We currently don't support changing
- * the token via DL_NOTIFY_IND.
- * When we do support it, we have to consider
- * what the implications are with respect to
- * the token and the link local address.
- */
- mutex_enter(&ill->ill_lock);
- if (dlp->notify_ind.dl_data ==
- DL_IPV6_LINK_LAYER_ADDR) {
- if (ill->ill_nd_lla_mp != NULL)
- freemsg(ill->ill_nd_lla_mp);
- ill->ill_nd_lla_mp = mp_hw;
- ill->ill_nd_lla = (uchar_t *)mp_hw->b_rptr +
- dlp->notify_ind.dl_addr_offset;
- ill->ill_nd_lla_len =
- dlp->notify_ind.dl_addr_length -
- ABS(ill->ill_sap_length);
- mutex_exit(&ill->ill_lock);
- break;
- } else if (dlp->notify_ind.dl_data ==
- DL_CURR_PHYS_ADDR) {
- if (ill->ill_phys_addr_mp != NULL)
- freemsg(ill->ill_phys_addr_mp);
- ill->ill_phys_addr_mp = mp_hw;
- ill->ill_phys_addr = (uchar_t *)mp_hw->b_rptr +
- dlp->notify_ind.dl_addr_offset;
- ill->ill_phys_addr_length =
- dlp->notify_ind.dl_addr_length -
- ABS(ill->ill_sap_length);
- if (ill->ill_isv6 &&
- !(ill->ill_flags & ILLF_XRESOLV)) {
- if (ill->ill_nd_lla_mp != NULL)
- freemsg(ill->ill_nd_lla_mp);
- ill->ill_nd_lla_mp = copyb(mp_hw);
- ill->ill_nd_lla = (uchar_t *)
- ill->ill_nd_lla_mp->b_rptr +
- dlp->notify_ind.dl_addr_offset;
- ill->ill_nd_lla_len =
- ill->ill_phys_addr_length;
- }
- }
- mutex_exit(&ill->ill_lock);
- /*
- * Send out gratuitous arp request for our new
- * hardware address.
- */
- for (ipif = ill->ill_ipif; ipif != NULL;
- ipif = ipif->ipif_next) {
- if (!(ipif->ipif_flags & IPIF_UP))
- continue;
- if (ill->ill_isv6) {
- ipif_ndp_down(ipif);
- /*
- * Set B_TRUE to enable
- * ipif_ndp_up() to send out
- * unsolicited advertisements.
- */
- err = ipif_ndp_up(ipif,
- &ipif->ipif_v6lcl_addr,
- B_TRUE);
- if (err) {
- ip1dbg((
- "ip_rput_dlpi_writer: "
- "Failed to update ndp "
- "err %d\n", err));
- }
- } else {
- /*
- * IPv4 ARP case
- *
- * Set Res_act_move, as we only want
- * ipif_resolver_up to send an
- * AR_ENTRY_ADD request up to
- * ARP.
- */
- err = ipif_resolver_up(ipif,
- Res_act_move);
- if (err) {
- ip1dbg((
- "ip_rput_dlpi_writer: "
- "Failed to update arp "
- "err %d\n", err));
- }
- }
- }
- /*
- * Allow "fall through" to the DL_NOTE_FASTPATH_FLUSH
- * case so that all old fastpath information can be
- * purged from IRE caches.
- */
- /* FALLTHRU */
+ err = ill_set_phys_addr(ill, mp);
+ break;
+
case DL_NOTE_FASTPATH_FLUSH:
- /*
- * Any fastpath probe sent henceforth will get the
- * new fp mp. So we first delete any ires that are
- * waiting for the fastpath. Then walk all ires and
- * delete the ire or delete the fp mp. In the case of
- * IRE_MIPRTUN and IRE_BROADCAST it is difficult to
- * recreate the ire's without going through a complex
- * ipif up/down dance. So we don't delete the ire
- * itself, but just the nce_fp_mp for these 2 ire's
- * In the case of the other ire's we delete the ire's
- * themselves. Access to nce_fp_mp is completely
- * protected by ire_lock for IRE_MIPRTUN and
- * IRE_BROADCAST. Deleting the ire is preferable in the
- * other cases for performance.
- */
- if (ill->ill_isv6) {
- nce_fastpath_list_dispatch(ill, NULL, NULL);
- ndp_walk(ill, (pfi_t)ndp_fastpath_flush,
- NULL);
- } else {
- ire_fastpath_list_dispatch(ill, NULL, NULL);
- ire_walk_ill_v4(MATCH_IRE_WQ | MATCH_IRE_TYPE,
- IRE_CACHE | IRE_BROADCAST,
- ire_fastpath_flush, NULL, ill);
- mutex_enter(&ire_mrtun_lock);
- if (ire_mrtun_count != 0) {
- mutex_exit(&ire_mrtun_lock);
- ire_walk_ill_mrtun(MATCH_IRE_WQ,
- IRE_MIPRTUN, ire_fastpath_flush,
- NULL, ill);
- } else {
- mutex_exit(&ire_mrtun_lock);
- }
- }
+ ill_fastpath_flush(ill);
break;
+
case DL_NOTE_SDU_SIZE:
/*
* Change the MTU size of the interface, of all
@@ -16114,64 +15983,42 @@ ip_rput_dlpi_writer(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
}
case DL_PHYS_ADDR_ACK: {
/*
- * We should have an IOCTL waiting on this when request
- * sent by ill_dl_phys.
- * However, ill_dl_phys was called on an ill queue (from
- * SIOCSLIFNAME), thus conn_pending_ill is not set. But the
- * ioctl is known to be pending on ill_wq.
- * There are two additional phys_addr_req's sent to the
- * driver to get the token and lla. ill_phys_addr_pend
- * keeps track of the last one sent so we know which
- * response we are dealing with. ill_dlpi_done will
- * update ill_phys_addr_pend when it sends the next req.
- * We don't complete the IOCTL until all three DL_PARs
- * have been attempted.
- *
- * We don't need any lock to update ill_nd_lla* fields,
- * since the ill is not yet up, We grab the lock just
- * for uniformity with other code that accesses ill_nd_lla.
+ * As part of plumbing the interface via SIOCSLIFNAME,
+ * ill_dl_phys() will queue a series of DL_PHYS_ADDR_REQs,
+ * whose answers we receive here. As each answer is received,
+ * we call ill_dlpi_done() to dispatch the next request as
+ * we're processing the current one. Once all answers have
+ * been received, we use ipsq_pending_mp_get() to dequeue the
+ * outstanding IOCTL and reply to it. (Because ill_dl_phys()
+ * is invoked from an ill queue, conn_oper_pending_ill is not
+ * available, but we know the ioctl is pending on ill_wq.)
*/
- physaddr_req = ill->ill_phys_addr_pend;
+ uint_t paddrlen, paddroff;
+
+ paddrreq = ill->ill_phys_addr_pend;
+ paddrlen = ((dl_phys_addr_ack_t *)mp->b_rptr)->dl_addr_length;
+ paddroff = ((dl_phys_addr_ack_t *)mp->b_rptr)->dl_addr_offset;
+
ill_dlpi_done(ill, DL_PHYS_ADDR_REQ);
- if (physaddr_req == DL_IPV6_TOKEN ||
- physaddr_req == DL_IPV6_LINK_LAYER_ADDR) {
- if (physaddr_req == DL_IPV6_TOKEN) {
- /*
- * bcopy to low-order bits of ill_token
- *
- * XXX Temporary hack - currently,
- * all known tokens are 64 bits,
- * so I'll cheat for the moment.
- */
- dlp = (union DL_primitives *)mp->b_rptr;
-
- mutex_enter(&ill->ill_lock);
- bcopy((uchar_t *)(mp->b_rptr +
- dlp->physaddr_ack.dl_addr_offset),
- (void *)&ill->ill_token.s6_addr32[2],
- dlp->physaddr_ack.dl_addr_length);
- ill->ill_token_length =
- dlp->physaddr_ack.dl_addr_length;
- mutex_exit(&ill->ill_lock);
- } else {
- ASSERT(ill->ill_nd_lla_mp == NULL);
- mp_hw = copyb(mp);
- if (mp_hw == NULL) {
- err = ENOMEM;
- break;
- }
- dlp = (union DL_primitives *)mp_hw->b_rptr;
- mutex_enter(&ill->ill_lock);
- ill->ill_nd_lla_mp = mp_hw;
- ill->ill_nd_lla = (uchar_t *)mp_hw->b_rptr +
- dlp->physaddr_ack.dl_addr_offset;
- ill->ill_nd_lla_len =
- dlp->physaddr_ack.dl_addr_length;
- mutex_exit(&ill->ill_lock);
- }
+ if (paddrreq == DL_IPV6_TOKEN) {
+ /*
+ * bcopy to low-order bits of ill_token
+ *
+ * XXX Temporary hack - currently, all known tokens
+ * are 64 bits, so I'll cheat for the moment.
+ */
+ bcopy(mp->b_rptr + paddroff,
+ &ill->ill_token.s6_addr32[2], paddrlen);
+ ill->ill_token_length = paddrlen;
+ break;
+ } else if (paddrreq == DL_IPV6_LINK_LAYER_ADDR) {
+ ASSERT(ill->ill_nd_lla_mp == NULL);
+ ill_set_ndmp(ill, mp, paddroff, paddrlen);
+ mp = NULL;
break;
}
- ASSERT(physaddr_req == DL_CURR_PHYS_ADDR);
+
+ ASSERT(paddrreq == DL_CURR_PHYS_ADDR);
ASSERT(ill->ill_phys_addr_mp == NULL);
if (!ill->ill_ifname_pending)
break;
@@ -16192,61 +16039,47 @@ ip_rput_dlpi_writer(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
ill->ill_ifname_pending_err = 0;
break;
}
+
+ ill->ill_phys_addr_mp = mp;
+ ill->ill_phys_addr = mp->b_rptr + paddroff;
+ mp = NULL;
+
/*
- * Get the interface token. If the zeroth interface
- * address is zero then set the address to the link local
- * address
+ * If paddrlen is zero, the DLPI provider doesn't support
+ * physical addresses. The other two tests were historical
+ * workarounds for bugs in our former PPP implementation, but
+ * now other things have grown dependencies on them -- e.g.,
+ * the tun module specifies a dl_addr_length of zero in its
+ * DL_BIND_ACK, but then specifies an incorrect value in its
+ * DL_PHYS_ADDR_ACK. These bogus checks need to be removed,
+ * but only after careful testing ensures that all dependent
+ * broken DLPI providers have been fixed.
*/
- mp_hw = copyb(mp);
- if (mp_hw == NULL) {
- err = ENOMEM;
- break;
- }
- dlp = (union DL_primitives *)mp_hw->b_rptr;
- ill->ill_phys_addr_mp = mp_hw;
- ill->ill_phys_addr = (uchar_t *)mp_hw->b_rptr +
- dlp->physaddr_ack.dl_addr_offset;
- if (dlp->physaddr_ack.dl_addr_length == 0 ||
- ill->ill_phys_addr_length == 0 ||
+ if (paddrlen == 0 || ill->ill_phys_addr_length == 0 ||
ill->ill_phys_addr_length == IP_ADDR_LEN) {
- /*
- * Compatibility: atun driver returns a length of 0.
- * ipdptp has an ill_phys_addr_length of zero(from
- * DL_BIND_ACK) but a non-zero length here.
- * ipd has an ill_phys_addr_length of 4(from
- * DL_BIND_ACK) but a non-zero length here.
- */
ill->ill_phys_addr = NULL;
- } else if (dlp->physaddr_ack.dl_addr_length !=
- ill->ill_phys_addr_length) {
- ip0dbg(("DL_PHYS_ADDR_ACK: "
- "Address length mismatch %d %d\n",
- dlp->physaddr_ack.dl_addr_length,
- ill->ill_phys_addr_length));
+ } else if (paddrlen != ill->ill_phys_addr_length) {
+ ip0dbg(("DL_PHYS_ADDR_ACK: got addrlen %d, expected %d",
+ paddrlen, ill->ill_phys_addr_length));
err = EINVAL;
break;
}
- mutex_enter(&ill->ill_lock);
+
if (ill->ill_nd_lla_mp == NULL) {
- ill->ill_nd_lla_mp = copyb(mp_hw);
- if (ill->ill_nd_lla_mp == NULL) {
+ if ((mp_hw = copyb(ill->ill_phys_addr_mp)) == NULL) {
err = ENOMEM;
- mutex_exit(&ill->ill_lock);
break;
}
- ill->ill_nd_lla =
- (uchar_t *)ill->ill_nd_lla_mp->b_rptr +
- dlp->physaddr_ack.dl_addr_offset;
- ill->ill_nd_lla_len = ill->ill_phys_addr_length;
+ ill_set_ndmp(ill, mp_hw, paddroff, paddrlen);
}
- mutex_exit(&ill->ill_lock);
- if (IN6_IS_ADDR_UNSPECIFIED(&ill->ill_token))
- (void) ill_setdefaulttoken(ill);
/*
- * If the ill zero interface has a zero address assign
- * it the proper link local address.
+ * Set the interface token. If the zeroth interface address
+ * is unspecified, then set it to the link local address.
*/
+ if (IN6_IS_ADDR_UNSPECIFIED(&ill->ill_token))
+ (void) ill_setdefaulttoken(ill);
+
ASSERT(ill->ill_ipif->ipif_id == 0);
if (ipif != NULL &&
IN6_IS_ADDR_UNSPECIFIED(&ipif->ipif_v6lcl_addr))
@@ -16270,30 +16103,29 @@ ip_rput_dlpi_writer(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
}
freemsg(mp);
- if (mp1) {
- struct iocblk *iocp;
- int mode;
-
- /*
- * Complete the waiting IOCTL. For SIOCLIFADDIF or
- * SIOCSLIFNAME do a copyout.
- */
- iocp = (struct iocblk *)mp1->b_rptr;
-
- if (iocp->ioc_cmd == SIOCLIFADDIF ||
- iocp->ioc_cmd == SIOCSLIFNAME)
- mode = COPYOUT;
- else
- mode = NO_COPYOUT;
+ if (mp1 != NULL) {
/*
- * The ioctl must complete now without EINPROGRESS
- * since ipsq_pending_mp_get has removed the ioctl mblk
- * from ipsq_pending_mp. Otherwise the ioctl will be
- * stuck for ever in the ipsq.
+ * The operation must complete without EINPROGRESS
+ * since ipsq_pending_mp_get() has removed the mblk
+ * from ipsq_pending_mp. Otherwise, the operation
+ * will be stuck forever in the ipsq.
*/
ASSERT(err != EINPROGRESS);
- ip_ioctl_finish(q, mp1, err, mode, ipif, ipsq);
+ switch (ipsq->ipsq_current_ioctl) {
+ case 0:
+ ipsq_current_finish(ipsq);
+ break;
+
+ case SIOCLIFADDIF:
+ case SIOCSLIFNAME:
+ ip_ioctl_finish(q, mp1, err, COPYOUT, ipsq);
+ break;
+
+ default:
+ ip_ioctl_finish(q, mp1, err, NO_COPYOUT, ipsq);
+ break;
+ }
}
}
@@ -16363,7 +16195,6 @@ ip_rput_other(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
if (ta->ifta_flags & (IFTUN_SRC | IFTUN_DST)) {
ipif_set_tun_llink(ill, ta);
}
-
}
if (mp1 != NULL) {
/*
@@ -16379,11 +16210,9 @@ ip_rput_other(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
mp1->b_cont->b_prev;
}
inet_freemsg(mp1);
- ASSERT(ipsq->ipsq_current_ipif != NULL);
ASSERT(connp != NULL);
ip_ioctl_finish(CONNP_TO_WQ(connp), mp,
- iocp->ioc_error, NO_COPYOUT,
- ipsq->ipsq_current_ipif, ipsq);
+ iocp->ioc_error, NO_COPYOUT, ipsq);
} else {
ASSERT(connp == NULL);
putnext(q, mp);
@@ -16415,7 +16244,7 @@ ip_rput_other(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
mp->b_datap->db_type = M_IOCDATA;
ASSERT(connp != NULL);
ip_ioctl_finish(CONNP_TO_WQ(connp), mp,
- iocp->ioc_error, COPYOUT, NULL, NULL);
+ iocp->ioc_error, COPYOUT, NULL);
} else {
ASSERT(connp == NULL);
putnext(q, mp);
@@ -16430,7 +16259,6 @@ ip_rput_other(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
switch (iocp->ioc_cmd) {
int mode;
- ipif_t *ipif;
case DL_IOC_HDR_INFO:
/*
@@ -16471,12 +16299,9 @@ ip_rput_other(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
iocp->ioc_id);
mode = COPYOUT;
ipsq = NULL;
- ipif = NULL;
} else {
mp1 = ipsq_pending_mp_get(ipsq, &connp);
mode = NO_COPYOUT;
- ASSERT(ipsq->ipsq_current_ipif != NULL);
- ipif = ipsq->ipsq_current_ipif;
}
if (mp1 != NULL) {
/*
@@ -16496,7 +16321,7 @@ ip_rput_other(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
iocp->ioc_error = EINVAL;
ASSERT(connp != NULL);
ip_ioctl_finish(CONNP_TO_WQ(connp), mp,
- iocp->ioc_error, mode, ipif, ipsq);
+ iocp->ioc_error, mode, ipsq);
} else {
ASSERT(connp == NULL);
putnext(q, mp);
@@ -26829,7 +26654,6 @@ ip_reprocess_ioctl(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
{
struct iocblk *iocp;
mblk_t *mp1;
- ipif_t *ipif;
ip_ioctl_cmd_t *ipip;
int err;
sin_t *sin;
@@ -26842,9 +26666,8 @@ ip_reprocess_ioctl(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
mp1 = mp->b_cont->b_cont;
ipip = ip_sioctl_lookup(iocp->ioc_cmd);
if (ipip->ipi_cmd == SIOCSLIFNAME || ipip->ipi_cmd == IF_UNITSEL) {
- ill_t *ill;
/*
- * Special case where ipsq_current_ipif may not be set.
+ * Special case where ipsq_current_ipif is not set:
* ill_phyint_reinit merged the v4 and v6 into a single ipsq.
* ill could also have become part of a ipmp group in the
* process, we are here as were not able to complete the
@@ -26852,13 +26675,11 @@ ip_reprocess_ioctl(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
* exclusive on the new ipsq, In such a case ipsq_current_ipif
* will not be set so we need to set it.
*/
- ill = (ill_t *)q->q_ptr;
- ipsq->ipsq_current_ipif = ill->ill_ipif;
- ipsq->ipsq_last_cmd = ipip->ipi_cmd;
+ ill_t *ill = q->q_ptr;
+ ipsq_current_start(ipsq, ill->ill_ipif, ipip->ipi_cmd);
}
+ ASSERT(ipsq->ipsq_current_ipif != NULL);
- ipif = ipsq->ipsq_current_ipif;
- ASSERT(ipif != NULL);
if (ipip->ipi_cmd_type == IF_CMD) {
/* This a old style SIOC[GS]IF* command */
ifr = (struct ifreq *)mp1->b_rptr;
@@ -26871,13 +26692,10 @@ ip_reprocess_ioctl(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
sin = NULL;
}
- err = (*ipip->ipi_func_restart)(ipif, sin, q, mp, ipip,
- (void *)mp1->b_rptr);
+ err = (*ipip->ipi_func_restart)(ipsq->ipsq_current_ipif, sin, q, mp,
+ ipip, mp1->b_rptr);
- /* SIOCLIFREMOVEIF could have removed the ipif */
- ip_ioctl_finish(q, mp, err,
- ipip->ipi_flags & IPI_GET_CMD ? COPYOUT : NO_COPYOUT,
- ipip->ipi_cmd == SIOCLIFREMOVEIF ? NULL : ipif, ipsq);
+ ip_ioctl_finish(q, mp, err, IPI2MODE(ipip), ipsq);
}
/*
@@ -26928,9 +26746,7 @@ ip_process_ioctl(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *arg)
*/
if (ipip->ipi_cmd == SIOCLIFADDIF) {
err = ip_sioctl_addif(NULL, NULL, q, mp, NULL, NULL);
- ip_ioctl_finish(q, mp, err,
- ipip->ipi_flags & IPI_GET_CMD ? COPYOUT : NO_COPYOUT,
- NULL, NULL);
+ ip_ioctl_finish(q, mp, err, IPI2MODE(ipip), NULL);
return;
}
@@ -26946,9 +26762,7 @@ ip_process_ioctl(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *arg)
err = ip_extract_lifreq_cmn(q, mp, ipip->ipi_cmd_type,
ipip->ipi_flags, &ci, ip_process_ioctl);
if (err != 0) {
- ip_ioctl_finish(q, mp, err,
- ipip->ipi_flags & IPI_GET_CMD ?
- COPYOUT : NO_COPYOUT, NULL, NULL);
+ ip_ioctl_finish(q, mp, err, IPI2MODE(ipip), NULL);
return;
}
ASSERT(ci.ci_ipif != NULL);
@@ -26961,9 +26775,7 @@ ip_process_ioctl(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *arg)
*/
err = ip_extract_tunreq(q, mp, &ci.ci_ipif, ip_process_ioctl);
if (err != 0) {
- ip_ioctl_finish(q, mp, err,
- ipip->ipi_flags & IPI_GET_CMD ?
- COPYOUT : NO_COPYOUT, NULL, NULL);
+ ip_ioctl_finish(q, mp, err, IPI2MODE(ipip), NULL);
return;
}
ASSERT(ci.ci_ipif != NULL);
@@ -26987,10 +26799,8 @@ ip_process_ioctl(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *arg)
err = ip_extract_msfilter(q, mp, &ci.ci_ipif,
ip_process_ioctl);
if (err != 0) {
- ip_ioctl_finish(q, mp, err,
- ipip->ipi_flags & IPI_GET_CMD ?
- COPYOUT : NO_COPYOUT, NULL, NULL);
- return;
+ ip_ioctl_finish(q, mp, err, IPI2MODE(ipip),
+ NULL);
}
break;
}
@@ -27015,9 +26825,7 @@ ip_process_ioctl(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *arg)
ci.ci_lifr);
if (ci.ci_ipif != NULL)
ipif_refrele(ci.ci_ipif);
- ip_ioctl_finish(q, mp, err,
- ipip->ipi_flags & IPI_GET_CMD ? COPYOUT : NO_COPYOUT,
- NULL, NULL);
+ ip_ioctl_finish(q, mp, err, IPI2MODE(ipip), NULL);
return;
}
@@ -27038,12 +26846,8 @@ ip_process_ioctl(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *arg)
if (ipsq == NULL)
return;
- mutex_enter(&ipsq->ipsq_lock);
- ASSERT(ipsq->ipsq_current_ipif == NULL);
- ipsq->ipsq_current_ipif = ci.ci_ipif;
- ipsq->ipsq_last_cmd = ipip->ipi_cmd;
- mutex_exit(&ipsq->ipsq_lock);
- mutex_enter(&(ci.ci_ipif)->ipif_ill->ill_lock);
+ ipsq_current_start(ipsq, ci.ci_ipif, ipip->ipi_cmd);
+
/*
* For most set ioctls that come here, this serves as a single point
* where we set the IPIF_CHANGING flag. This ensures that there won't
@@ -27057,6 +26861,7 @@ ip_process_ioctl(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *arg)
* sets the IPIF_CONDEMNED flag internally after identifying the right
* ipif to operate on.
*/
+ mutex_enter(&(ci.ci_ipif)->ipif_ill->ill_lock);
if (ipip->ipi_cmd != SIOCLIFREMOVEIF &&
ipip->ipi_cmd != SIOCLIFFAILOVER &&
ipip->ipi_cmd != SIOCLIFFAILBACK &&
@@ -27069,13 +26874,9 @@ ip_process_ioctl(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *arg)
* either queued and waiting for some reason or has
* already completed.
*/
- err = (*ipip->ipi_func)(ci.ci_ipif, ci.ci_sin, q, mp, ipip,
- ci.ci_lifr);
+ err = (*ipip->ipi_func)(ci.ci_ipif, ci.ci_sin, q, mp, ipip, ci.ci_lifr);
- /* SIOCLIFREMOVEIF could have removed the ipif */
- ip_ioctl_finish(q, mp, err,
- ipip->ipi_flags & IPI_GET_CMD ? COPYOUT : NO_COPYOUT,
- ipip->ipi_cmd == SIOCLIFREMOVEIF ? NULL : ci.ci_ipif, ipsq);
+ ip_ioctl_finish(q, mp, err, IPI2MODE(ipip), ipsq);
if (entered_ipsq)
ipsq_exit(ipsq, B_TRUE, B_TRUE);
@@ -27086,11 +26887,9 @@ ip_process_ioctl(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *arg)
* do mi_copyout/mi_copy_done.
*/
void
-ip_ioctl_finish(queue_t *q, mblk_t *mp, int err, int mode,
- ipif_t *ipif, ipsq_t *ipsq)
+ip_ioctl_finish(queue_t *q, mblk_t *mp, int err, int mode, ipsq_t *ipsq)
{
conn_t *connp = NULL;
- hook_nic_event_t *info;
if (err == EINPROGRESS)
return;
@@ -27113,7 +26912,7 @@ ip_ioctl_finish(queue_t *q, mblk_t *mp, int err, int mode,
break;
default:
- /* An ioctl aborted through a conn close would take this path */
+ ASSERT(mode == CONN_CLOSE); /* aborted through CONN_CLOSE */
break;
}
@@ -27123,46 +26922,8 @@ ip_ioctl_finish(queue_t *q, mblk_t *mp, int err, int mode,
if (connp != NULL)
CONN_OPER_PENDING_DONE(connp);
- /*
- * If the ioctl were an exclusive ioctl it would have set
- * IPIF_CHANGING at the start of the ioctl which is undone here.
- */
- if (ipif != NULL) {
- mutex_enter(&(ipif)->ipif_ill->ill_lock);
- ipif->ipif_state_flags &= ~IPIF_CHANGING;
-
- /*
- * Unhook the nic event message from the ill and enqueue it into
- * the nic event taskq.
- */
- if ((info = ipif->ipif_ill->ill_nic_event_info) != NULL) {
- if (ddi_taskq_dispatch(eventq_queue_nic,
- ip_ne_queue_func, (void *)info, DDI_SLEEP)
- == DDI_FAILURE) {
- ip2dbg(("ip_ioctl_finish: ddi_taskq_dispatch"
- "failed\n"));
- if (info->hne_data != NULL)
- kmem_free(info->hne_data,
- info->hne_datalen);
- kmem_free(info, sizeof (hook_nic_event_t));
- }
-
- ipif->ipif_ill->ill_nic_event_info = NULL;
- }
-
- mutex_exit(&(ipif)->ipif_ill->ill_lock);
- }
-
- /*
- * Clear the current ipif in the ipsq at the completion of the ioctl.
- * Note that a non-null ipsq_current_ipif prevents new ioctls from
- * entering the ipsq
- */
- if (ipsq != NULL) {
- mutex_enter(&ipsq->ipsq_lock);
- ipsq->ipsq_current_ipif = NULL;
- mutex_exit(&ipsq->ipsq_lock);
- }
+ if (ipsq != NULL)
+ ipsq_current_finish(ipsq);
}
/*
@@ -28715,18 +28476,30 @@ ip_arp_done(ipsq_t *dummy_sq, queue_t *q, mblk_t *mp, void *dummy_arg)
freeb(mp);
}
- /* We should have an IOCTL waiting on this. */
ipsq = ill->ill_phyint->phyint_ipsq;
ipif = ipsq->ipsq_pending_ipif;
mp1 = ipsq_pending_mp_get(ipsq, &connp);
- ASSERT(!((mp1 != NULL) ^ (ipif != NULL)));
+ ASSERT(!((mp1 != NULL) ^ (ipif != NULL)));
if (mp1 == NULL) {
/* bringup was aborted by the user */
freemsg(mp2);
return;
}
- ASSERT(connp != NULL);
- q = CONNP_TO_WQ(connp);
+
+ /*
+ * If an IOCTL is waiting on this (ipsq_current_ioctl != 0), then we
+ * must have an associated conn_t. Otherwise, we're bringing this
+ * interface back up as part of handling an asynchronous event (e.g.,
+ * physical address change).
+ */
+ if (ipsq->ipsq_current_ioctl != 0) {
+ ASSERT(connp != NULL);
+ q = CONNP_TO_WQ(connp);
+ } else {
+ ASSERT(connp == NULL);
+ q = ill->ill_rq;
+ }
+
/*
* If the DL_BIND_REQ fails, it is noted
* in arc_name_offset.
@@ -28752,18 +28525,19 @@ ip_arp_done(ipsq_t *dummy_sq, queue_t *q, mblk_t *mp, void *dummy_arg)
return;
}
- if (ill->ill_up_ipifs) {
+ if (ill->ill_up_ipifs)
ill_group_cleanup(ill);
- }
/*
- * The ioctl must complete now without EINPROGRESS
- * since ipsq_pending_mp_get has removed the ioctl mblk
- * from ipsq_pending_mp. Otherwise the ioctl will be
- * stuck for ever in the ipsq.
+ * The operation must complete without EINPROGRESS since
+ * ipsq_pending_mp_get() has removed the mblk from ipsq_pending_mp.
+ * Otherwise, the operation will be stuck forever in the ipsq.
*/
ASSERT(err != EINPROGRESS);
- ip_ioctl_finish(q, mp1, err, NO_COPYOUT, ipif, ipsq);
+ if (ipsq->ipsq_current_ioctl != 0)
+ ip_ioctl_finish(q, mp1, err, NO_COPYOUT, ipsq);
+ else
+ ipsq_current_finish(ipsq);
}
/* Allocate the private structure */
diff --git a/usr/src/uts/common/inet/ip/ip6_if.c b/usr/src/uts/common/inet/ip/ip6_if.c
index 246d1df11e..3283176ad8 100644
--- a/usr/src/uts/common/inet/ip/ip6_if.c
+++ b/usr/src/uts/common/inet/ip/ip6_if.c
@@ -1055,17 +1055,9 @@ ill_setdefaulttoken(ill_t *ill)
int i;
in6_addr_t v6addr, v6mask;
- /*
- * Though we execute on the ipsq, we need to hold the ill_lock
- * to prevent readers from seeing partially updated values
- * while we do the update.
- */
- mutex_enter(&ill->ill_lock);
if (!MEDIA_V6INTFID(ill->ill_media, ill->ill_phys_addr_length,
- ill->ill_phys_addr, &v6addr)) {
- mutex_exit(&ill->ill_lock);
+ ill->ill_phys_addr, &v6addr))
return (B_FALSE);
- }
(void) ip_plen_to_mask_v6(IPV6_TOKEN_LEN, &v6mask);
@@ -1075,7 +1067,6 @@ ill_setdefaulttoken(ill_t *ill)
V6_MASK_COPY(v6addr, v6mask, ill->ill_token);
ill->ill_token_length = IPV6_TOKEN_LEN;
- mutex_exit(&ill->ill_lock);
return (B_TRUE);
}
@@ -1364,7 +1355,7 @@ ipif_ndp_setup_multicast(ipif_t *ipif, nce_t **ret_nce)
* as writer.)
*/
int
-ipif_ndp_up(ipif_t *ipif, const in6_addr_t *addr, boolean_t macaddr_change)
+ipif_ndp_up(ipif_t *ipif, const in6_addr_t *addr)
{
ill_t *ill = ipif->ipif_ill;
int err = 0;
@@ -1408,8 +1399,7 @@ ipif_ndp_up(ipif_t *ipif, const in6_addr_t *addr, boolean_t macaddr_change)
uchar_t *hw_addr = NULL;
/* Permanent entries don't need NUD */
- flags = NCE_F_PERMANENT;
- flags |= NCE_F_NONUD;
+ flags = NCE_F_PERMANENT | NCE_F_NONUD;
if (ill->ill_flags & ILLF_ROUTER)
flags |= NCE_F_ISROUTER;
@@ -1419,7 +1409,7 @@ ipif_ndp_up(ipif_t *ipif, const in6_addr_t *addr, boolean_t macaddr_change)
if (ill->ill_net_type == IRE_IF_RESOLVER) {
hw_addr = ill->ill_nd_lla;
- if (ill->ill_move_in_progress || macaddr_change) {
+ if (ill->ill_move_in_progress) {
/*
* Addresses are failing over to this ill.
* Don't wait for NUD to see this change.
diff --git a/usr/src/uts/common/inet/ip/ip_if.c b/usr/src/uts/common/inet/ip/ip_if.c
index 09ed4c8421..32367adb79 100644
--- a/usr/src/uts/common/inet/ip/ip_if.c
+++ b/usr/src/uts/common/inet/ip/ip_if.c
@@ -193,6 +193,7 @@ static void ill_nominate_bcast_rcv(ill_group_t *illgrp);
static void ill_phyint_free(ill_t *ill);
static void ill_phyint_reinit(ill_t *ill);
static void ill_set_nce_router_flags(ill_t *, boolean_t);
+static void ill_set_phys_addr_tail(ipsq_t *, queue_t *, mblk_t *, void *);
static void ill_signal_ipsq_ills(ipsq_t *, boolean_t);
static boolean_t ill_split_ipsq(ipsq_t *cur_sq);
static void ill_stq_cache_delete(ire_t *, char *);
@@ -991,8 +992,8 @@ ill_delete_tail(ill_t *ill)
ill->ill_frag_ptr = NULL;
ill->ill_frag_hash_tbl = NULL;
}
- if (ill->ill_nd_lla_mp != NULL)
- freemsg(ill->ill_nd_lla_mp);
+
+ freemsg(ill->ill_nd_lla_mp);
/* Free all retained control messages. */
mpp = &ill->ill_first_mp_to_free;
do {
@@ -1213,19 +1214,28 @@ boolean_t
ipsq_pending_mp_add(conn_t *connp, ipif_t *ipif, queue_t *q, mblk_t *add_mp,
int waitfor)
{
- ipsq_t *ipsq;
+ ipsq_t *ipsq = ipif->ipif_ill->ill_phyint->phyint_ipsq;
ASSERT(IAM_WRITER_IPIF(ipif));
ASSERT(MUTEX_HELD(&ipif->ipif_ill->ill_lock));
ASSERT((add_mp->b_next == NULL) && (add_mp->b_prev == NULL));
+ ASSERT(ipsq->ipsq_pending_mp == NULL);
+ /*
+ * The caller may be using a different ipif than the one passed into
+ * ipsq_current_start() (e.g., suppose an ioctl that came in on the V4
+ * ill needs to wait for the V6 ill to quiesce). So we can't ASSERT
+ * that `ipsq_current_ipif == ipif'.
+ */
+ ASSERT(ipsq->ipsq_current_ipif != NULL);
+
/*
* M_IOCDATA from ioctls, M_IOCTL from tunnel ioctls,
- * M_ERROR/M_HANGUP from driver
+ * M_ERROR/M_HANGUP/M_PROTO/M_PCPROTO from the driver.
*/
ASSERT((DB_TYPE(add_mp) == M_IOCDATA) || (DB_TYPE(add_mp) == M_IOCTL) ||
- (DB_TYPE(add_mp) == M_ERROR) || (DB_TYPE(add_mp) == M_HANGUP));
+ (DB_TYPE(add_mp) == M_ERROR) || (DB_TYPE(add_mp) == M_HANGUP) ||
+ (DB_TYPE(add_mp) == M_PROTO) || (DB_TYPE(add_mp) == M_PCPROTO));
- ipsq = ipif->ipif_ill->ill_phyint->phyint_ipsq;
if (connp != NULL) {
ASSERT(MUTEX_HELD(&connp->conn_lock));
/*
@@ -1248,17 +1258,7 @@ ipsq_pending_mp_add(conn_t *connp, ipif_t *ipif, queue_t *q, mblk_t *add_mp,
add_mp->b_queue = q;
ipsq->ipsq_pending_mp = add_mp;
ipsq->ipsq_waitfor = waitfor;
- /*
- * ipsq_current_ipif is needed to restart the operation from
- * ipif_ill_refrele_tail when the last reference to the ipi/ill
- * is gone. Since this is not an ioctl ipsq_current_ipif has not
- * been set until now.
- */
- if (DB_TYPE(add_mp) == M_ERROR || DB_TYPE(add_mp) == M_HANGUP) {
- ASSERT(ipsq->ipsq_current_ipif == NULL);
- ipsq->ipsq_current_ipif = ipif;
- ipsq->ipsq_last_cmd = DB_TYPE(add_mp);
- }
+
if (connp != NULL)
connp->conn_oper_pending_ill = ipif->ipif_ill;
mutex_exit(&ipsq->ipsq_lock);
@@ -1352,11 +1352,18 @@ ipsq_pending_mp_cleanup(ill_t *ill, conn_t *connp)
ipsq->ipsq_pending_ipif = NULL;
ipsq->ipsq_waitfor = 0;
ipsq->ipsq_current_ipif = NULL;
+ ipsq->ipsq_current_ioctl = 0;
mutex_exit(&ipsq->ipsq_lock);
if (DB_TYPE(mp) == M_IOCTL || DB_TYPE(mp) == M_IOCDATA) {
- ip_ioctl_finish(q, mp, ENXIO, connp != NULL ? CONN_CLOSE :
- NO_COPYOUT, connp != NULL ? ipif : NULL, NULL);
+ if (connp == NULL) {
+ ip_ioctl_finish(q, mp, ENXIO, NO_COPYOUT, NULL);
+ } else {
+ ip_ioctl_finish(q, mp, ENXIO, CONN_CLOSE, NULL);
+ mutex_enter(&ipif->ipif_ill->ill_lock);
+ ipif->ipif_state_flags &= ~IPIF_CHANGING;
+ mutex_exit(&ipif->ipif_ill->ill_lock);
+ }
} else {
/*
* IP-MT XXX In the case of TLI/XTI bind / optmgmt this can't
@@ -1397,7 +1404,7 @@ ill_pending_mp_cleanup(ill_t *ill)
mp->b_next = NULL;
mp->b_prev = NULL;
mp->b_queue = NULL;
- ip_ioctl_finish(q, mp, ENXIO, NO_COPYOUT, NULL, NULL);
+ ip_ioctl_finish(q, mp, ENXIO, NO_COPYOUT, NULL);
mutex_enter(&ill->ill_lock);
}
ill->ill_pending_ipif = NULL;
@@ -1468,7 +1475,7 @@ ipsq_xopq_mp_cleanup(ill_t *ill, conn_t *connp)
curr->b_queue = NULL;
if (DB_TYPE(curr) == M_IOCTL || DB_TYPE(curr) == M_IOCDATA) {
ip_ioctl_finish(q, curr, ENXIO, connp != NULL ?
- CONN_CLOSE : NO_COPYOUT, NULL, NULL);
+ CONN_CLOSE : NO_COPYOUT, NULL);
} else {
/*
* IP-MT XXX In the case of TLI/XTI bind / optmgmt
@@ -1613,7 +1620,7 @@ ipif_all_down_tail(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
}
ill_down_tail(ill);
freemsg(mp);
- ipsq->ipsq_current_ipif = NULL;
+ ipsq_current_finish(ipsq);
}
/*
@@ -1624,11 +1631,9 @@ ipif_all_down_tail(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *dummy_arg)
boolean_t
ill_down_start(queue_t *q, mblk_t *mp)
{
- ill_t *ill;
+ ill_t *ill = q->q_ptr;
ipif_t *ipif;
- ill = q->q_ptr;
-
ASSERT(IAM_WRITER_ILL(ill));
for (ipif = ill->ill_ipif; ipif != NULL; ipif = ipif->ipif_next)
@@ -1637,16 +1642,15 @@ ill_down_start(queue_t *q, mblk_t *mp)
ill_down(ill);
(void) ipsq_pending_mp_cleanup(ill, NULL);
- mutex_enter(&ill->ill_lock);
+
+ ipsq_current_start(ill->ill_phyint->phyint_ipsq, ill->ill_ipif, 0);
+
/*
- * Atomically test and add the pending mp if references are
- * still active.
+ * Atomically test and add the pending mp if references are active.
*/
+ mutex_enter(&ill->ill_lock);
if (!ill_is_quiescent(ill)) {
- /*
- * Get rid of any pending mps and cleanup. Call will
- * not fail since we are passing a null connp.
- */
+ /* call cannot fail since `conn_t *' argument is NULL */
(void) ipsq_pending_mp_add(NULL, ill->ill_ipif, ill->ill_rq,
mp, ILL_DOWN);
mutex_exit(&ill->ill_lock);
@@ -4936,24 +4940,21 @@ ill_init(queue_t *q, ill_t *ill)
int
ill_dls_info(struct sockaddr_dl *sdl, const ipif_t *ipif)
{
- size_t length;
+ size_t len;
ill_t *ill = ipif->ipif_ill;
sdl->sdl_family = AF_LINK;
sdl->sdl_index = ill->ill_phyint->phyint_ifindex;
- sdl->sdl_type = ipif->ipif_type;
+ sdl->sdl_type = ill->ill_type;
(void) ipif_get_name(ipif, sdl->sdl_data, sizeof (sdl->sdl_data));
- length = mi_strlen(sdl->sdl_data);
- ASSERT(length < 256);
- sdl->sdl_nlen = (uchar_t)length;
+ len = strlen(sdl->sdl_data);
+ ASSERT(len < 256);
+ sdl->sdl_nlen = (uchar_t)len;
sdl->sdl_alen = ill->ill_phys_addr_length;
- mutex_enter(&ill->ill_lock);
- if (ill->ill_phys_addr_length != 0 && ill->ill_phys_addr != NULL) {
- bcopy(ill->ill_phys_addr, &sdl->sdl_data[length],
- ill->ill_phys_addr_length);
- }
- mutex_exit(&ill->ill_lock);
sdl->sdl_slen = 0;
+ if (ill->ill_phys_addr_length != 0 && ill->ill_phys_addr != NULL)
+ bcopy(ill->ill_phys_addr, &sdl->sdl_data[len], sdl->sdl_alen);
+
return (sizeof (struct sockaddr_dl));
}
@@ -6219,6 +6220,7 @@ ipif_ill_refrele_tail(ill_t *ill)
conn_t *connp;
ipsq_t *ipsq;
ipif_t *ipif;
+ dl_notify_ind_t *dlindp;
ASSERT(MUTEX_HELD(&ill->ill_lock));
@@ -6295,17 +6297,34 @@ ipif_ill_refrele_tail(ill_t *ill)
ASSERT(mp != NULL);
switch (mp->b_datap->db_type) {
+ case M_PCPROTO:
+ case M_PROTO:
+ /*
+ * For now, only DL_NOTIFY_IND messages can use this facility.
+ */
+ dlindp = (dl_notify_ind_t *)mp->b_rptr;
+ ASSERT(dlindp->dl_primitive == DL_NOTIFY_IND);
+
+ switch (dlindp->dl_notification) {
+ case DL_NOTE_PHYS_ADDR:
+ qwriter_ip(NULL, ill, ill->ill_rq, mp,
+ ill_set_phys_addr_tail, CUR_OP, B_TRUE);
+ return;
+ default:
+ ASSERT(0);
+ }
+ break;
+
case M_ERROR:
case M_HANGUP:
- (void) qwriter_ip(NULL, ill, ill->ill_rq, mp,
- ipif_all_down_tail, CUR_OP, B_TRUE);
+ qwriter_ip(NULL, ill, ill->ill_rq, mp, ipif_all_down_tail,
+ CUR_OP, B_TRUE);
return;
case M_IOCTL:
case M_IOCDATA:
- (void) qwriter_ip(NULL, ill,
- (connp != NULL ? CONNP_TO_WQ(connp) : ill->ill_wq), mp,
- ip_reprocess_ioctl, CUR_OP, B_TRUE);
+ qwriter_ip(NULL, ill, (connp != NULL ? CONNP_TO_WQ(connp) :
+ ill->ill_wq), mp, ip_reprocess_ioctl, CUR_OP, B_TRUE);
return;
default:
@@ -7978,6 +7997,68 @@ again:
}
/*
+ * Start the current exclusive operation on `ipsq'; associate it with `ipif'
+ * and `ioccmd'.
+ */
+void
+ipsq_current_start(ipsq_t *ipsq, ipif_t *ipif, int ioccmd)
+{
+ ASSERT(IAM_WRITER_IPSQ(ipsq));
+
+ mutex_enter(&ipsq->ipsq_lock);
+ ASSERT(ipsq->ipsq_current_ipif == NULL);
+ ASSERT(ipsq->ipsq_current_ioctl == 0);
+ ipsq->ipsq_current_ipif = ipif;
+ ipsq->ipsq_current_ioctl = ioccmd;
+ mutex_exit(&ipsq->ipsq_lock);
+}
+
+/*
+ * Finish the current exclusive operation on `ipsq'. Note that other
+ * operations will not be able to proceed until an ipsq_exit() is done.
+ */
+void
+ipsq_current_finish(ipsq_t *ipsq)
+{
+ ipif_t *ipif = ipsq->ipsq_current_ipif;
+ hook_nic_event_t *info;
+
+ ASSERT(IAM_WRITER_IPSQ(ipsq));
+
+ /*
+ * For SIOCSLIFREMOVEIF, the ipif has been already been blown away
+ * (but we're careful to never set IPIF_CHANGING in that case).
+ */
+ if (ipsq->ipsq_current_ioctl != SIOCLIFREMOVEIF) {
+ mutex_enter(&ipif->ipif_ill->ill_lock);
+ ipif->ipif_state_flags &= ~IPIF_CHANGING;
+ /*
+ * Unhook the nic event message from the ill and enqueue it
+ * into the nic event taskq.
+ */
+ if ((info = ipif->ipif_ill->ill_nic_event_info) != NULL) {
+ if (ddi_taskq_dispatch(eventq_queue_nic,
+ ip_ne_queue_func, info, DDI_SLEEP) == DDI_FAILURE) {
+ ip2dbg(("ipsq_current_finish: "
+ "ddi_taskq_dispatch failed\n"));
+ if (info->hne_data != NULL)
+ kmem_free(info->hne_data,
+ info->hne_datalen);
+ kmem_free(info, sizeof (hook_nic_event_t));
+ }
+ ipif->ipif_ill->ill_nic_event_info = NULL;
+ }
+ mutex_exit(&ipif->ipif_ill->ill_lock);
+ }
+
+ mutex_enter(&ipsq->ipsq_lock);
+ ASSERT(ipsq->ipsq_current_ipif != NULL);
+ ipsq->ipsq_current_ipif = NULL;
+ ipsq->ipsq_current_ioctl = 0;
+ mutex_exit(&ipsq->ipsq_lock);
+}
+
+/*
* The ill is closing. Flush all messages on the ipsq that originated
* from this ill. Usually there wont' be any messages on the ipsq_xopq_mphead
* for this ill since ipsq_enter could not have entered until then.
@@ -10556,7 +10637,7 @@ ip_sioctl_iocack(queue_t *q, mblk_t *mp)
ire_refrele(ire);
freemsg(mp);
ip_ioctl_finish(q, orig_ioc_mp,
- EINVAL, NO_COPYOUT, NULL, NULL);
+ EINVAL, NO_COPYOUT, NULL);
return;
}
*flagsp |= ATF_COM;
@@ -10582,7 +10663,7 @@ ip_sioctl_iocack(queue_t *q, mblk_t *mp)
/* Ditch the internal IOCTL. */
freemsg(mp);
ire_refrele(ire);
- ip_ioctl_finish(q, orig_ioc_mp, 0, COPYOUT, NULL, NULL);
+ ip_ioctl_finish(q, orig_ioc_mp, 0, COPYOUT, NULL);
return;
}
}
@@ -10626,7 +10707,7 @@ errack:
if (iocp->ioc_error || iocp->ioc_cmd != AR_ENTRY_SQUERY) {
err = iocp->ioc_error;
freemsg(mp);
- ip_ioctl_finish(q, orig_ioc_mp, err, NO_COPYOUT, NULL, NULL);
+ ip_ioctl_finish(q, orig_ioc_mp, err, NO_COPYOUT, NULL);
return;
}
@@ -10639,8 +10720,8 @@ errack:
if ((ill->ill_phys_addr_length + ill->ill_name_length) >
sizeof (xar->xarp_ha.sdl_data)) {
freemsg(mp);
- ip_ioctl_finish(q, orig_ioc_mp, EINVAL,
- NO_COPYOUT, NULL, NULL);
+ ip_ioctl_finish(q, orig_ioc_mp, EINVAL, NO_COPYOUT,
+ NULL);
return;
}
}
@@ -10667,7 +10748,7 @@ errack:
/* Ditch the internal IOCTL. */
freemsg(mp);
/* Complete the original. */
- ip_ioctl_finish(q, orig_ioc_mp, 0, COPYOUT, NULL, NULL);
+ ip_ioctl_finish(q, orig_ioc_mp, 0, COPYOUT, NULL);
}
/*
@@ -13853,9 +13934,8 @@ ipif_resolver_up(ipif_t *ipif, enum ip_resolver_action res_act)
* Copy the new hardware address and length into
* arp_add_mp to be sent to ARP.
*/
- area->area_hw_addr_length =
- ill->ill_phys_addr_length;
- bcopy((char *)ill->ill_phys_addr,
+ area->area_hw_addr_length = ill->ill_phys_addr_length;
+ bcopy(ill->ill_phys_addr,
((char *)area + area->area_hw_addr_offset),
area->area_hw_addr_length);
}
@@ -14950,6 +15030,7 @@ ill_merge_groups(ill_t *from_ill, ill_t *to_ill, char *groupname, mblk_t *mp,
*/
mutex_enter(&old_ipsq->ipsq_lock);
old_ipsq->ipsq_current_ipif = NULL;
+ old_ipsq->ipsq_current_ioctl = 0;
mutex_exit(&old_ipsq->ipsq_lock);
return (EINPROGRESS);
}
@@ -19757,7 +19838,7 @@ ipif_up(ipif_t *ipif, queue_t *q, mblk_t *mp)
/* Skip arp/ndp for any loopback interface. */
if (ill->ill_wq != NULL) {
- conn_t *connp = Q_TO_CONN(q);
+ conn_t *connp = CONN_Q(q) ? Q_TO_CONN(q) : NULL;
ipsq_t *ipsq = ill->ill_phyint->phyint_ipsq;
if (!ill->ill_dl_up) {
@@ -19783,13 +19864,15 @@ ipif_up(ipif_t *ipif, queue_t *q, mblk_t *mp)
* EINPROGRESS and we will complete in ip_arp_done.
*/
- ASSERT(connp != NULL);
+ ASSERT(connp != NULL || !CONN_Q(q));
ASSERT(ipsq->ipsq_pending_mp == NULL);
- mutex_enter(&connp->conn_lock);
+ if (connp != NULL)
+ mutex_enter(&connp->conn_lock);
mutex_enter(&ill->ill_lock);
success = ipsq_pending_mp_add(connp, ipif, q, mp, 0);
mutex_exit(&ill->ill_lock);
- mutex_exit(&connp->conn_lock);
+ if (connp != NULL)
+ mutex_exit(&connp->conn_lock);
if (!success)
return (EINTR);
@@ -19802,8 +19885,7 @@ ipif_up(ipif_t *ipif, queue_t *q, mblk_t *mp)
* That ioctl will complete in ip_rput.
*/
if (isv6) {
- err = ipif_ndp_up(ipif, &ipif->ipif_v6lcl_addr,
- B_FALSE);
+ err = ipif_ndp_up(ipif, &ipif->ipif_v6lcl_addr);
if (err != 0) {
if (err != EINPROGRESS)
mp = ipsq_pending_mp_get(ipsq, &connp);
@@ -19887,17 +19969,14 @@ ill_dl_up(ill_t *ill, ipif_t *ipif, mblk_t *mp, queue_t *q)
* Record state needed to complete this operation when the
* DL_BIND_ACK shows up. Also remember the pre-allocated mblks.
*/
- if (WR(q)->q_next == NULL) {
- connp = Q_TO_CONN(q);
- mutex_enter(&connp->conn_lock);
- } else {
- connp = NULL;
- }
+ ASSERT(WR(q)->q_next == NULL);
+ connp = Q_TO_CONN(q);
+
+ mutex_enter(&connp->conn_lock);
mutex_enter(&ipif->ipif_ill->ill_lock);
success = ipsq_pending_mp_add(connp, ipif, q, mp, 0);
mutex_exit(&ipif->ipif_ill->ill_lock);
- if (connp != NULL)
- mutex_exit(&connp->conn_lock);
+ mutex_exit(&connp->conn_lock);
if (!success)
goto bad;
@@ -19943,10 +20022,8 @@ bad:
* groups.
*/
- if (bind_mp != NULL)
- freemsg(bind_mp);
- if (unbind_mp != NULL)
- freemsg(unbind_mp);
+ freemsg(bind_mp);
+ freemsg(unbind_mp);
return (ENOMEM);
}
@@ -22981,13 +23058,13 @@ ipif_set_values(queue_t *q, mblk_t *mp, char *interf_name, uint_t *new_ppa_ptr)
return (EINPROGRESS);
/*
- * Need to set the ipsq_current_ipif now, if we have changed ipsq
- * due to the phyint merge in ill_phyint_reinit.
+ * If ill_phyint_reinit() changed our ipsq, then start on the new ipsq.
*/
- ASSERT(ipsq->ipsq_current_ipif == NULL ||
- ipsq->ipsq_current_ipif == ipif);
- ipsq->ipsq_current_ipif = ipif;
- ipsq->ipsq_last_cmd = SIOCSLIFNAME;
+ if (ipsq->ipsq_current_ipif == NULL)
+ ipsq_current_start(ipsq, ipif, SIOCSLIFNAME);
+ else
+ ASSERT(ipsq->ipsq_current_ipif == ipif);
+
error = ipif_set_values_tail(ill, ipif, mp, q);
ipsq_exit(ipsq, B_TRUE, B_TRUE);
if (error != 0 && error != EINPROGRESS) {
@@ -24188,3 +24265,150 @@ ipif_getby_indexes(uint_t ifindex, uint_t lifidx, boolean_t isv6)
ill_refrele(ill);
return (ipif);
}
+
+/*
+ * Flush the fastpath by deleting any IRE's that are waiting for the fastpath,
+ * and any IRE's that are using the fastpath. There are two exceptions:
+ * IRE_MIPRTUN and IRE_BROADCAST are difficult to recreate, so instead we just
+ * nuke their nce_fp_mp's; see ire_fastpath_flush() for details.
+ */
+void
+ill_fastpath_flush(ill_t *ill)
+{
+ if (ill->ill_isv6) {
+ nce_fastpath_list_dispatch(ill, NULL, NULL);
+ ndp_walk(ill, (pfi_t)ndp_fastpath_flush, NULL);
+ } else {
+ ire_fastpath_list_dispatch(ill, NULL, NULL);
+ ire_walk_ill_v4(MATCH_IRE_WQ | MATCH_IRE_TYPE,
+ IRE_CACHE | IRE_BROADCAST, ire_fastpath_flush, NULL, ill);
+ mutex_enter(&ire_mrtun_lock);
+ if (ire_mrtun_count != 0) {
+ mutex_exit(&ire_mrtun_lock);
+ ire_walk_ill_mrtun(MATCH_IRE_WQ, IRE_MIPRTUN,
+ ire_fastpath_flush, NULL, ill);
+ } else {
+ mutex_exit(&ire_mrtun_lock);
+ }
+ }
+}
+
+/*
+ * Set the physical address information for `ill' to the contents of the
+ * dl_notify_ind_t pointed to by `mp'. Must be called as writer, and will be
+ * asynchronous if `ill' cannot immediately be quiesced -- in which case
+ * EINPROGRESS will be returned.
+ */
+int
+ill_set_phys_addr(ill_t *ill, mblk_t *mp)
+{
+ ipsq_t *ipsq = ill->ill_phyint->phyint_ipsq;
+ dl_notify_ind_t *dlindp = (dl_notify_ind_t *)mp->b_rptr;
+
+ ASSERT(IAM_WRITER_IPSQ(ipsq));
+
+ if (dlindp->dl_data != DL_IPV6_LINK_LAYER_ADDR &&
+ dlindp->dl_data != DL_CURR_PHYS_ADDR) {
+ /* Changing DL_IPV6_TOKEN is not yet supported */
+ return (0);
+ }
+
+ /*
+ * We need to store up to two copies of `mp' in `ill'. Due to the
+ * design of ipsq_pending_mp_add(), we can't pass them as separate
+ * arguments to ill_set_phys_addr_tail(). Instead, chain them
+ * together here, then pull 'em apart in ill_set_phys_addr_tail().
+ */
+ if ((mp = copyb(mp)) == NULL || (mp->b_cont = copyb(mp)) == NULL) {
+ freemsg(mp);
+ return (ENOMEM);
+ }
+
+ ipsq_current_start(ipsq, ill->ill_ipif, 0);
+
+ /*
+ * If we can quiesce the ill, then set the address. If not, then
+ * ill_set_phys_addr_tail() will be called from ipif_ill_refrele_tail().
+ */
+ ill_down_ipifs(ill, NULL, 0, B_FALSE);
+ mutex_enter(&ill->ill_lock);
+ if (!ill_is_quiescent(ill)) {
+ /* call cannot fail since `conn_t *' argument is NULL */
+ (void) ipsq_pending_mp_add(NULL, ill->ill_ipif, ill->ill_rq,
+ mp, ILL_DOWN);
+ mutex_exit(&ill->ill_lock);
+ return (EINPROGRESS);
+ }
+ mutex_exit(&ill->ill_lock);
+
+ ill_set_phys_addr_tail(ipsq, ill->ill_rq, mp, NULL);
+ return (0);
+}
+
+/*
+ * Once the ill associated with `q' has quiesced, set its physical address
+ * information to the values in `addrmp'. Note that two copies of `addrmp'
+ * are passed (linked by b_cont), since we sometimes need to save two distinct
+ * copies in the ill_t, and our context doesn't permit sleeping or allocation
+ * failure (we'll free the other copy if it's not needed). Since the ill_t
+ * is quiesced, we know any stale IREs with the old address information have
+ * already been removed, so we don't need to call ill_fastpath_flush().
+ */
+/* ARGSUSED */
+static void
+ill_set_phys_addr_tail(ipsq_t *ipsq, queue_t *q, mblk_t *addrmp, void *dummy)
+{
+ ill_t *ill = q->q_ptr;
+ mblk_t *addrmp2 = unlinkb(addrmp);
+ dl_notify_ind_t *dlindp = (dl_notify_ind_t *)addrmp->b_rptr;
+ uint_t addrlen, addroff;
+
+ ASSERT(IAM_WRITER_IPSQ(ipsq));
+ mutex_enter(&ill->ill_lock);
+ ASSERT(ill_is_quiescent(ill));
+ mutex_exit(&ill->ill_lock);
+
+ addroff = dlindp->dl_addr_offset;
+ addrlen = dlindp->dl_addr_length - ABS(ill->ill_sap_length);
+
+ switch (dlindp->dl_data) {
+ case DL_IPV6_LINK_LAYER_ADDR:
+ ill_set_ndmp(ill, addrmp, addroff, addrlen);
+ freemsg(addrmp2);
+ break;
+
+ case DL_CURR_PHYS_ADDR:
+ freemsg(ill->ill_phys_addr_mp);
+ ill->ill_phys_addr = addrmp->b_rptr + addroff;
+ ill->ill_phys_addr_mp = addrmp;
+ ill->ill_phys_addr_length = addrlen;
+
+ if (ill->ill_isv6 && !(ill->ill_flags & ILLF_XRESOLV))
+ ill_set_ndmp(ill, addrmp2, addroff, addrlen);
+ else
+ freemsg(addrmp2);
+ break;
+ default:
+ ASSERT(0);
+ }
+
+ /*
+ * If there are ipifs to bring up, ill_up_ipifs() will return nonzero,
+ * and ipsq_current_finish() will be called by ip_rput_dlpi_writer()
+ * or ip_arp_done() when the last ipif is brought up.
+ */
+ if (ill_up_ipifs(ill, q, addrmp) == 0)
+ ipsq_current_finish(ipsq);
+}
+
+/*
+ * Helper routine for setting the ill_nd_lla fields.
+ */
+void
+ill_set_ndmp(ill_t *ill, mblk_t *ndmp, uint_t addroff, uint_t addrlen)
+{
+ freemsg(ill->ill_nd_lla_mp);
+ ill->ill_nd_lla = ndmp->b_rptr + addroff;
+ ill->ill_nd_lla_mp = ndmp;
+ ill->ill_nd_lla_len = addrlen;
+}
diff --git a/usr/src/uts/common/inet/ip/ip_ndp.c b/usr/src/uts/common/inet/ip/ip_ndp.c
index 09d162d3f9..91ebbd3cc4 100644
--- a/usr/src/uts/common/inet/ip/ip_ndp.c
+++ b/usr/src/uts/common/inet/ip/ip_ndp.c
@@ -1514,7 +1514,7 @@ ip_ndp_recover(ipsq_t *ipsq, queue_t *rq, mblk_t *mp, void *dummy_arg)
mutex_exit(&ill->ill_lock);
ipif->ipif_was_dup = B_TRUE;
- if (ipif_ndp_up(ipif, addr, B_FALSE) != EINPROGRESS)
+ if (ipif_ndp_up(ipif, addr) != EINPROGRESS)
(void) ipif_up_done_v6(ipif);
}
freeb(mp);
@@ -2361,7 +2361,6 @@ nce_xmit(ill_t *ill, uint32_t operation, ill_t *hwaddr_ill,
hw_addr = NULL;
if (!(flag & NDP_PROBE)) {
- mutex_enter(&hwaddr_ill->ill_lock);
hw_addr = use_nd_lla ? hwaddr_ill->ill_nd_lla :
hwaddr_ill->ill_phys_addr;
if (hw_addr != NULL) {
@@ -2369,7 +2368,6 @@ nce_xmit(ill_t *ill, uint32_t operation, ill_t *hwaddr_ill,
opt->nd_opt_len = (uint8_t)plen;
bcopy(hw_addr, &opt[1], hwaddr_ill->ill_nd_lla_len);
}
- mutex_exit(&hwaddr_ill->ill_lock);
}
if (hw_addr == NULL) {
/* If there's no link layer address option, then strip it. */
diff --git a/usr/src/uts/common/inet/ip_if.h b/usr/src/uts/common/inet/ip_if.h
index 8b50aaed40..fd4afba556 100644
--- a/usr/src/uts/common/inet/ip_if.h
+++ b/usr/src/uts/common/inet/ip_if.h
@@ -176,6 +176,7 @@ extern int ill_dls_info(struct sockaddr_dl *, const ipif_t *);
extern void ill_fastpath_ack(ill_t *, mblk_t *);
extern void ill_fastpath_nack(ill_t *);
extern int ill_fastpath_probe(ill_t *, mblk_t *);
+extern void ill_fastpath_flush(ill_t *);
extern void ill_frag_prune(ill_t *, uint_t);
extern void ill_frag_free_pkts(ill_t *, ipfb_t *, ipf_t *, int);
extern time_t ill_frag_timeout(ill_t *, time_t);
@@ -183,8 +184,9 @@ extern int ill_init(queue_t *, ill_t *);
extern int ill_nominate_mcast_rcv(ill_group_t *);
extern boolean_t ill_setdefaulttoken(ill_t *);
extern void ill_restart_dad(ill_t *, boolean_t);
+extern int ill_set_phys_addr(ill_t *, mblk_t *);
+extern void ill_set_ndmp(ill_t *, mblk_t *, uint_t, uint_t);
-extern void ill_lock_ills(ill_t **, int);
extern mblk_t *ill_pending_mp_get(ill_t *, conn_t **, uint_t);
extern boolean_t ill_pending_mp_add(ill_t *, conn_t *, mblk_t *);
extern boolean_t ill_is_quiescent(ill_t *ill);
@@ -241,7 +243,7 @@ extern int ipif_down(ipif_t *, queue_t *, mblk_t *);
extern void ipif_down_tail(ipif_t *);
extern void ipif_multicast_up(ipif_t *);
extern void ipif_ndp_down(ipif_t *);
-extern int ipif_ndp_up(ipif_t *, const in6_addr_t *, boolean_t);
+extern int ipif_ndp_up(ipif_t *, const in6_addr_t *);
extern int ipif_ndp_setup_multicast(ipif_t *, struct nce_s **);
extern int ipif_up_done(ipif_t *);
extern int ipif_up_done_v6(ipif_t *);
@@ -263,6 +265,8 @@ extern void ipif_mask_reply(ipif_t *);
extern int illgrp_insert(ill_group_t **, ill_t *, char *, ill_group_t *,
boolean_t);
+extern void ipsq_current_start(ipsq_t *, ipif_t *, int);
+extern void ipsq_current_finish(ipsq_t *);
extern void ipsq_enq(ipsq_t *, queue_t *, mblk_t *, ipsq_func_t, int,
ill_t *);
extern boolean_t ipsq_enter(ill_t *, boolean_t);
diff --git a/usr/src/uts/common/sys/stream.h b/usr/src/uts/common/sys/stream.h
index 642cd276bf..18d9e1c495 100644
--- a/usr/src/uts/common/sys/stream.h
+++ b/usr/src/uts/common/sys/stream.h
@@ -361,6 +361,9 @@ typedef struct datab {
*/
#define DB_TCI(mp) ((mp)->b_datap->db_struioun.cksum.pad)
+#define MBLK_GETLABEL(mp) \
+ (DB_CRED(mp) != NULL ? crgetlabel(DB_CRED(mp)) : NULL)
+
/*
* Message block descriptor
*/
diff --git a/usr/src/uts/common/sys/strsun.h b/usr/src/uts/common/sys/strsun.h
index 987d25dd10..3c5b969584 100644
--- a/usr/src/uts/common/sys/strsun.h
+++ b/usr/src/uts/common/sys/strsun.h
@@ -54,9 +54,6 @@ extern "C" {
#define MBLKIN(mp, off, len) (((off) <= MBLKL(mp)) && \
(((mp)->b_rptr + (off) + (len)) <= (mp)->b_wptr))
-#define MBLK_GETLABEL(mp) \
- (DB_CRED(mp) != NULL ? crgetlabel(DB_CRED(mp)) : NULL)
-
#ifdef _KERNEL
extern void mcopyin(mblk_t *, void *, size_t, void *);
extern void mcopyout(mblk_t *, void *, size_t, void *, mblk_t *);