Mercurial > illumos > illumos-gate
changeset 6979:c28789e83536
6709252 DL_{EN,DIS}ABMULTI_REQs can still trigger ASSERT() in ill_move_to_new_ipsq()
6715867 ip_rput_dlpi() could be simplified a bit
author | meem |
---|---|
date | Sat, 28 Jun 2008 01:47:43 -0700 |
parents | 75d541818603 |
children | f9acf54be1af |
files | usr/src/uts/common/inet/ip/ip.c usr/src/uts/common/inet/ip/ip_multi.c |
diffstat | 2 files changed, 110 insertions(+), 97 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/inet/ip/ip.c Fri Jun 27 21:26:48 2008 -0700 +++ b/usr/src/uts/common/inet/ip/ip.c Sat Jun 28 01:47:43 2008 -0700 @@ -15451,91 +15451,75 @@ { dl_ok_ack_t *dloa = (dl_ok_ack_t *)mp->b_rptr; dl_error_ack_t *dlea = (dl_error_ack_t *)dloa; - ill_t *ill = (ill_t *)q->q_ptr; - boolean_t pending; + ill_t *ill = q->q_ptr; + t_uscalar_t prim = dloa->dl_primitive; + t_uscalar_t reqprim = DL_PRIM_INVAL; ip1dbg(("ip_rput_dlpi")); - if (dloa->dl_primitive == DL_ERROR_ACK) { - ip2dbg(("ip_rput_dlpi(%s): DL_ERROR_ACK %s (0x%x): " - "%s (0x%x), unix %u\n", ill->ill_name, - dl_primstr(dlea->dl_error_primitive), - dlea->dl_error_primitive, - dl_errstr(dlea->dl_errno), - dlea->dl_errno, - dlea->dl_unix_errno)); - } /* * If we received an ACK but didn't send a request for it, then it * can't be part of any pending operation; discard up-front. */ - switch (dloa->dl_primitive) { - case DL_NOTIFY_IND: - pending = B_TRUE; - break; + switch (prim) { case DL_ERROR_ACK: - pending = ill_dlpi_pending(ill, dlea->dl_error_primitive); + reqprim = dlea->dl_error_primitive; + ip2dbg(("ip_rput_dlpi(%s): DL_ERROR_ACK for %s (0x%x): %s " + "(0x%x), unix %u\n", ill->ill_name, dl_primstr(reqprim), + reqprim, dl_errstr(dlea->dl_errno), dlea->dl_errno, + dlea->dl_unix_errno)); break; case DL_OK_ACK: - pending = ill_dlpi_pending(ill, dloa->dl_correct_primitive); + reqprim = dloa->dl_correct_primitive; break; case DL_INFO_ACK: - pending = ill_dlpi_pending(ill, DL_INFO_REQ); + reqprim = DL_INFO_REQ; break; case DL_BIND_ACK: - pending = ill_dlpi_pending(ill, DL_BIND_REQ); + reqprim = DL_BIND_REQ; break; case DL_PHYS_ADDR_ACK: - pending = ill_dlpi_pending(ill, DL_PHYS_ADDR_REQ); + reqprim = DL_PHYS_ADDR_REQ; break; case DL_NOTIFY_ACK: - pending = ill_dlpi_pending(ill, DL_NOTIFY_REQ); + reqprim = DL_NOTIFY_REQ; break; case DL_CONTROL_ACK: - pending = ill_dlpi_pending(ill, DL_CONTROL_REQ); + reqprim = DL_CONTROL_REQ; break; case DL_CAPABILITY_ACK: - pending = ill_dlpi_pending(ill, DL_CAPABILITY_REQ); - break; - default: - /* Not a DLPI message we support or were expecting */ - freemsg(mp); - return; - } - - if (!pending) { - freemsg(mp); - return; - } - - switch (dloa->dl_primitive) { - case DL_ERROR_ACK: - if (dlea->dl_error_primitive == DL_UNBIND_REQ) { - mutex_enter(&ill->ill_lock); - ill->ill_state_flags &= ~ILL_DL_UNBIND_IN_PROGRESS; - cv_signal(&ill->ill_cv); - mutex_exit(&ill->ill_lock); - } - break; - - case DL_OK_ACK: - ip1dbg(("ip_rput: DL_OK_ACK for %s\n", - dl_primstr((int)dloa->dl_correct_primitive))); - switch (dloa->dl_correct_primitive) { - case DL_UNBIND_REQ: - mutex_enter(&ill->ill_lock); - ill->ill_state_flags &= ~ILL_DL_UNBIND_IN_PROGRESS; - cv_signal(&ill->ill_cv); - mutex_exit(&ill->ill_lock); - break; - - case DL_ENABMULTI_REQ: + reqprim = DL_CAPABILITY_REQ; + break; + } + + if (prim != DL_NOTIFY_IND) { + if (reqprim == DL_PRIM_INVAL || + !ill_dlpi_pending(ill, reqprim)) { + /* Not a DLPI message we support or expected */ + freemsg(mp); + return; + } + ip1dbg(("ip_rput: received %s for %s\n", dl_primstr(prim), + dl_primstr(reqprim))); + } + + switch (reqprim) { + case DL_UNBIND_REQ: + /* + * NOTE: we mark the unbind as complete even if we got a + * DL_ERROR_ACK, since there's not much else we can do. + */ + mutex_enter(&ill->ill_lock); + ill->ill_state_flags &= ~ILL_DL_UNBIND_IN_PROGRESS; + cv_signal(&ill->ill_cv); + mutex_exit(&ill->ill_lock); + break; + + case DL_ENABMULTI_REQ: + if (prim == DL_OK_ACK) { if (ill->ill_dlpi_multicast_state == IDS_INPROGRESS) ill->ill_dlpi_multicast_state = IDS_OK; - break; - } - break; - default: + } break; } @@ -15551,7 +15535,7 @@ * refcount without doing ILL_CAN_LOOKUP(). */ ill_refhold(ill); - if (dloa->dl_primitive == DL_NOTIFY_IND) + if (prim == DL_NOTIFY_IND) qwriter_ip(ill, q, mp, ip_rput_dlpi_writer, NEW_OP, B_FALSE); else qwriter_ip(ill, q, mp, ip_rput_dlpi_writer, CUR_OP, B_FALSE); @@ -15610,9 +15594,13 @@ dl_primstr(dlea->dl_error_primitive))); switch (dlea->dl_error_primitive) { + case DL_DISABMULTI_REQ: + if (!ill->ill_isv6) + ipsq_current_finish(ipsq); + ill_dlpi_done(ill, dlea->dl_error_primitive); + break; case DL_PROMISCON_REQ: case DL_PROMISCOFF_REQ: - case DL_DISABMULTI_REQ: case DL_UNBIND_REQ: case DL_ATTACH_REQ: case DL_INFO_REQ: @@ -15697,6 +15685,8 @@ } break; case DL_ENABMULTI_REQ: + if (!ill->ill_isv6) + ipsq_current_finish(ipsq); ill_dlpi_done(ill, DL_ENABMULTI_REQ); if (ill->ill_dlpi_multicast_state == IDS_INPROGRESS) @@ -16214,10 +16204,14 @@ dl_primstr((int)dloa->dl_correct_primitive), dloa->dl_correct_primitive)); switch (dloa->dl_correct_primitive) { + case DL_ENABMULTI_REQ: + case DL_DISABMULTI_REQ: + if (!ill->ill_isv6) + ipsq_current_finish(ipsq); + ill_dlpi_done(ill, dloa->dl_correct_primitive); + break; case DL_PROMISCON_REQ: case DL_PROMISCOFF_REQ: - case DL_ENABMULTI_REQ: - case DL_DISABMULTI_REQ: case DL_UNBIND_REQ: case DL_ATTACH_REQ: ill_dlpi_done(ill, dloa->dl_correct_primitive);
--- a/usr/src/uts/common/inet/ip/ip_multi.c Fri Jun 27 21:26:48 2008 -0700 +++ b/usr/src/uts/common/inet/ip/ip_multi.c Sat Jun 28 01:47:43 2008 -0700 @@ -1331,9 +1331,8 @@ } /* - * Create a dlpi message with room for phys+sap. When we come back in - * ip_wput_ctl() we will strip the sap for those primitives which - * only need a physical address. + * Create a DLPI message; for DL_{ENAB,DISAB}MULTI_REQ, room is left for + * the hardware address. */ static mblk_t * ill_create_dl(ill_t *ill, uint32_t dl_primitive, uint32_t length, @@ -1407,41 +1406,61 @@ return (mp); } -void -ip_wput_ctl(queue_t *q, mblk_t *mp_orig) +/* + * Writer processing for ip_wput_ctl(): send the DL_{ENAB,DISAB}MULTI_REQ + * messages that had been delayed until we'd heard back from ARP. One catch: + * we need to ensure that no one else becomes writer on the IPSQ before we've + * received the replies, or they'll incorrectly process our replies as part of + * their unrelated IPSQ operation. To do this, we start a new IPSQ operation, + * which will complete when we process the reply in ip_rput_dlpi_writer(). + */ +/* ARGSUSED */ +static void +ip_wput_ctl_writer(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *arg) { - ill_t *ill = (ill_t *)q->q_ptr; - mblk_t *mp = mp_orig; + ill_t *ill = q->q_ptr; + t_uscalar_t prim = ((union DL_primitives *)mp->b_rptr)->dl_primitive; + + ASSERT(IAM_WRITER_ILL(ill)); + ASSERT(prim == DL_ENABMULTI_REQ || prim == DL_DISABMULTI_REQ); + ip1dbg(("ip_wput_ctl_writer: %s\n", dl_primstr(prim))); + + if (prim == DL_ENABMULTI_REQ) { + /* Track the state if this is the first enabmulti */ + if (ill->ill_dlpi_multicast_state == IDS_UNKNOWN) + ill->ill_dlpi_multicast_state = IDS_INPROGRESS; + } + + ipsq_current_start(ipsq, ill->ill_ipif, 0); + ill_dlpi_send(ill, mp); +} + +void +ip_wput_ctl(queue_t *q, mblk_t *mp) +{ + ill_t *ill = q->q_ptr; + mblk_t *dlmp = mp->b_cont; area_t *area = (area_t *)mp->b_rptr; - - /* Check that we have a AR_ENTRY_SQUERY with a tacked on mblk */ - if (MBLKL(mp) < sizeof (area_t) || mp->b_cont == NULL || - area->area_cmd != AR_ENTRY_SQUERY) { + t_uscalar_t prim; + + /* Check that we have an AR_ENTRY_SQUERY with a tacked on mblk */ + if (MBLKL(mp) < sizeof (area_t) || area->area_cmd != AR_ENTRY_SQUERY || + dlmp == NULL) { putnext(q, mp); return; } - mp = mp->b_cont; - - /* - * Update dl_addr_length and dl_addr_offset for primitives that - * have physical addresses as opposed to full saps - */ - switch (((union DL_primitives *)mp->b_rptr)->dl_primitive) { - case DL_ENABMULTI_REQ: - /* Track the state if this is the first enabmulti */ - if (ill->ill_dlpi_multicast_state == IDS_UNKNOWN) - ill->ill_dlpi_multicast_state = IDS_INPROGRESS; - ip1dbg(("ip_wput_ctl: ENABMULTI\n")); - break; - case DL_DISABMULTI_REQ: - ip1dbg(("ip_wput_ctl: DISABMULTI\n")); - break; - default: - ip1dbg(("ip_wput_ctl: default\n")); - break; + + /* Check that the tacked on mblk is a DL_{DISAB,ENAB}MULTI_REQ */ + prim = ((union DL_primitives *)dlmp->b_rptr)->dl_primitive; + if (prim != DL_DISABMULTI_REQ && prim != DL_ENABMULTI_REQ) { + putnext(q, mp); + return; } - freeb(mp_orig); - ill_dlpi_send(ill, mp); + freeb(mp); + + /* See comments above ip_wput_ctl_writer() for details */ + ill_refhold(ill); + qwriter_ip(ill, ill->ill_wq, dlmp, ip_wput_ctl_writer, NEW_OP, B_FALSE); } /*