Print this page
OS-7088 cyclics corked on overlay socket with full queue
*** 8,18 ****
* source. A copy of the CDDL is also available via the Internet at
* http://www.illumos.org/license/CDDL.
*/
/*
! * Copyright 2016 Joyent, Inc.
*/
/*
* Overlay Devices
*
--- 8,18 ----
* source. A copy of the CDDL is also available via the Internet at
* http://www.illumos.org/license/CDDL.
*/
/*
! * Copyright 2018 Joyent, Inc.
*/
/*
* Overlay Devices
*
*** 1052,1061 ****
--- 1052,1062 ----
int ret;
ovep_encap_info_t einfo;
struct msghdr hdr;
mutex_enter(&odd->odd_lock);
+ ASSERT0(odd->odd_flags & OVERLAY_F_TXSTOPPED);
if ((odd->odd_flags & OVERLAY_F_MDDROP) ||
!(odd->odd_flags & OVERLAY_F_IN_MUX)) {
mutex_exit(&odd->odd_lock);
freemsgchain(mp_chain);
return (NULL);
*** 1069,1078 ****
--- 1070,1083 ----
einfo.ovdi_id = odd->odd_vid;
mp = mp_chain;
while (mp != NULL) {
socklen_t slen;
struct sockaddr_storage storage;
+ #ifdef OVERLAY_FC_TEST
+ /* Can deal with it being NULL later... */
+ mblk_t *save_mp = msgpullup(mp, -1);
+ #endif
mp_chain = mp->b_next;
mp->b_next = NULL;
ep = NULL;
*** 1080,1113 ****
(struct sockaddr *)&storage, &slen);
if (ret != OVERLAY_TARGET_OK) {
if (ret == OVERLAY_TARGET_DROP)
freemsg(mp);
mp = mp_chain;
continue;
}
hdr.msg_name = &storage;
hdr.msg_namelen = slen;
ret = odd->odd_plugin->ovp_ops->ovpo_encap(odd->odd_mh, mp,
&einfo, &ep);
if (ret != 0 || ep == NULL) {
freemsg(mp);
goto out;
}
ASSERT(ep->b_cont == mp || ep == mp);
ret = overlay_mux_tx(odd->odd_mux, &hdr, ep);
! if (ret != 0)
goto out;
mp = mp_chain;
}
out:
mutex_enter(&odd->odd_lock);
overlay_io_done(odd, OVERLAY_F_IN_TX);
mutex_exit(&odd->odd_lock);
return (mp_chain);
}
/* ARGSUSED */
--- 1085,1159 ----
(struct sockaddr *)&storage, &slen);
if (ret != OVERLAY_TARGET_OK) {
if (ret == OVERLAY_TARGET_DROP)
freemsg(mp);
mp = mp_chain;
+ #ifdef OVERLAY_FC_TEST
+ freemsg(save_mp); /* Handles NULL and non-NULL */
+ #endif
continue;
}
hdr.msg_name = &storage;
hdr.msg_namelen = slen;
ret = odd->odd_plugin->ovp_ops->ovpo_encap(odd->odd_mh, mp,
&einfo, &ep);
if (ret != 0 || ep == NULL) {
+ #ifdef OVERLAY_FC_TEST
+ freemsg(save_mp); /* Handles NULL and non-NULL */
+ #endif
freemsg(mp);
goto out;
}
ASSERT(ep->b_cont == mp || ep == mp);
ret = overlay_mux_tx(odd->odd_mux, &hdr, ep);
! if (ret != 0) {
! if (ret != EWOULDBLOCK) {
! /*
! * Get rid of the packets, something ELSE is
! * wrong with the socket, and we really should
! * just drop the packets for now.
! */
! #ifdef OVERLAY_FC_TEST
! freemsg(save_mp);
! save_mp = NULL;
! #endif
! freemsgchain(mp_chain);
! mp_chain = NULL;
! }
! #ifdef OVERLAY_FC_TEST
! if (save_mp != NULL) {
! /*
! * Return the dropped mp here to see how
! * upper-layer MAC reacts to it.
! */
! save_mp->b_next = mp_chain;
! mp_chain = save_mp;
! }
! #endif
! /*
! * EWOULDBLOCK is a special case. Return the rest of
! * the mp_chain to MAC and have this instance be
! * marked as unable to transmit. Re-enable this
! * instance when the mux's socket is able to send data
! * again ("cansend" callback).
! */
goto out;
+ }
mp = mp_chain;
}
out:
mutex_enter(&odd->odd_lock);
overlay_io_done(odd, OVERLAY_F_IN_TX);
+ if (mp_chain != NULL) {
+ /* Note that we're returning an unsent chain to MAC. */
+ odd->odd_flags |= OVERLAY_F_TXSTOPPED;
+ }
mutex_exit(&odd->odd_lock);
return (mp_chain);
}
/* ARGSUSED */