+#if MPTCP
+ if ((so->so_flags & SOF_MP_SUBFLOW) &&
+ !(tp->t_mpflags & TMPF_TCP_FALLBACK)) {
+ int newlen = len;
+ if (tp->t_state >= TCPS_ESTABLISHED &&
+ (tp->t_mpflags & TMPF_SND_MPPRIO ||
+ tp->t_mpflags & TMPF_SND_REM_ADDR ||
+ tp->t_mpflags & TMPF_SND_MPFAIL ||
+ tp->t_mpflags & TMPF_SND_KEYS ||
+ tp->t_mpflags & TMPF_SND_JACK)) {
+ if (len > 0) {
+ len = 0;
+ }
+ /*
+ * On a new subflow, don't try to send again, because
+ * we are still waiting for the fourth ack.
+ */
+ if (!(tp->t_mpflags & TMPF_PREESTABLISHED))
+ sendalot = 1;
+ mptcp_acknow = TRUE;
+ } else {
+ mptcp_acknow = FALSE;
+ }
+ /*
+ * The contiguous bytes in the subflow socket buffer can be
+ * discontiguous at the MPTCP level. Since only one DSS
+ * option can be sent in one packet, reduce length to match
+ * the contiguous MPTCP level. Set sendalot to send remainder.
+ */
+ if (len > 0)
+ newlen = mptcp_adj_sendlen(so, off);
+ if (newlen < len) {
+ len = newlen;
+ sendalot = 1;
+ }
+ }
+#endif /* MPTCP */
+
+ /*
+ * If the socket is capable of doing unordered send,
+ * pull the amount of data that can be sent from the
+ * unordered priority queues to the serial queue in
+ * the socket buffer. If bytes are not yet available
+ * in the highest priority message, we may not be able
+ * to send any new data.
+ */
+ if (so->so_flags & SOF_ENABLE_MSGS) {
+ if ((off + len) >
+ so->so_msg_state->msg_serial_bytes) {
+ sbpull_unordered_data(so, off, len);
+
+ /* check if len needs to be modified */
+ if ((off + len) >
+ so->so_msg_state->msg_serial_bytes) {
+ len = so->so_msg_state->msg_serial_bytes - off;
+ if (len <= 0) {
+ len = 0;
+ tcpstat.tcps_msg_sndwaithipri++;
+ }
+ }
+ }
+ }
+
+ if (sack_rxmit) {
+ if (SEQ_LT(p->rxmit + len, tp->snd_una + so->so_snd.sb_cc))
+ flags &= ~TH_FIN;
+ } else {
+ if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc))
+ flags &= ~TH_FIN;
+ }
+ /*
+ * Compare available window to amount of window
+ * known to peer (as advertised window less
+ * next expected input). If the difference is at least two
+ * max size segments, or at least 25% of the maximum possible
+ * window, then want to send a window update to peer.
+ * Skip this if the connection is in T/TCP half-open state.
+ */
+ recwin = tcp_sbspace(tp);
+#if MPTCP
+ if (so->so_flags & SOF_MP_SUBFLOW) {
+ struct mptcb *mp_tp = tptomptp(tp);
+
+ if (mp_tp != NULL) {
+ mpte_lock_assert_held(mp_tp->mpt_mpte);
+ recwin = imin(recwin, mptcp_sbspace(mp_tp));
+ }
+ }
+#endif
+
+ if (recwin < (int32_t)(so->so_rcv.sb_hiwat / 4) &&
+ recwin < (int)tp->t_maxseg)
+ recwin = 0;
+
+#if TRAFFIC_MGT
+ if (tcp_recv_bg == 1 || IS_TCP_RECV_BG(so)) {
+ if (recwin > 0 && tcp_recv_throttle(tp)) {
+ uint32_t min_iaj_win = tcp_min_iaj_win * tp->t_maxseg;
+ uint32_t bg_rwintop = tp->rcv_adv;
+ if (SEQ_LT(bg_rwintop, tp->rcv_nxt + min_iaj_win))
+ bg_rwintop = tp->rcv_nxt + min_iaj_win;
+ recwin = imin((int32_t)(bg_rwintop - tp->rcv_nxt),
+ recwin);
+ if (recwin < 0)
+ recwin = 0;
+ }
+ }
+#endif /* TRAFFIC_MGT */
+
+ if (recwin > (int32_t)(TCP_MAXWIN << tp->rcv_scale))
+ recwin = (int32_t)(TCP_MAXWIN << tp->rcv_scale);
+
+ /*
+ * MPTCP needs to be able to announce a smaller window than previously,
+ * because the other subflow may have filled up the available window-
+ * space. So we have to be able to go backwards and announce a smaller
+ * window.
+ */
+ if (!(so->so_flags & SOF_MP_SUBFLOW) &&
+ recwin < (int32_t)(tp->rcv_adv - tp->rcv_nxt))
+ recwin = (int32_t)(tp->rcv_adv - tp->rcv_nxt);
+
+ /*
+ * Sender silly window avoidance. We transmit under the following
+ * conditions when len is non-zero:
+ *
+ * - we've timed out (e.g. persist timer)
+ * - we need to retransmit
+ * - We have a full segment (or more with TSO)
+ * - This is the last buffer in a write()/send() and we are
+ * either idle or running NODELAY
+ * - we have more then 1/2 the maximum send window's worth of
+ * data (receiver may be limited the window size)
+ */
+ if (len) {
+ if (tp->t_flagsext & TF_FORCE)
+ goto send;
+ if (SEQ_LT(tp->snd_nxt, tp->snd_max))
+ goto send;
+ if (sack_rxmit)
+ goto send;
+
+ /*
+ * Send new data on the connection only if it is
+ * not flow controlled
+ */
+ if (!INP_WAIT_FOR_IF_FEEDBACK(inp) ||
+ tp->t_state != TCPS_ESTABLISHED) {
+ if (len >= tp->t_maxseg)
+ goto send;
+
+ if (!(tp->t_flags & TF_MORETOCOME) &&
+ (idle || tp->t_flags & TF_NODELAY ||
+ (tp->t_flags & TF_MAXSEGSNT) ||
+ ALLOW_LIMITED_TRANSMIT(tp)) &&
+ (tp->t_flags & TF_NOPUSH) == 0 &&
+ (len + off >= so->so_snd.sb_cc ||
+ /*
+ * MPTCP needs to respect the DSS-mappings. So, it
+ * may be sending data that *could* have been
+ * coalesced, but cannot because of
+ * mptcp_adj_sendlen().
+ */
+ so->so_flags & SOF_MP_SUBFLOW))
+ goto send;
+ if (len >= tp->max_sndwnd / 2 && tp->max_sndwnd > 0)
+ goto send;
+ } else {
+ tcpstat.tcps_fcholdpacket++;
+ }
+ }
+
+ if (recwin > 0 && !(tp->t_flags & TF_NEEDSYN)) {
+ /*
+ * "adv" is the amount we can increase the window,
+ * taking into account that we are limited by
+ * TCP_MAXWIN << tp->rcv_scale.
+ */
+ int32_t adv, oldwin = 0;
+ adv = imin(recwin, (int)TCP_MAXWIN << tp->rcv_scale) -
+ (tp->rcv_adv - tp->rcv_nxt);
+
+ if (SEQ_GT(tp->rcv_adv, tp->rcv_nxt))
+ oldwin = tp->rcv_adv - tp->rcv_nxt;
+
+ if (adv >= (int32_t) (2 * tp->t_maxseg)) {
+ /*
+ * Update only if the resulting scaled value of
+ * the window changed, or if there is a change in
+ * the sequence since the last ack. This avoids
+ * what appears as dupe ACKS (see rdar://5640997)
+ *
+ * If streaming is detected avoid sending too many
+ * window updates. We will depend on the delack
+ * timer to send a window update when needed.
+ */
+ if (!(tp->t_flags & TF_STRETCHACK) &&
+ (tp->last_ack_sent != tp->rcv_nxt ||
+ ((oldwin + adv) >> tp->rcv_scale) >
+ (oldwin >> tp->rcv_scale))) {
+ goto send;
+ }
+
+ }
+ if (4 * adv >= (int32_t) so->so_rcv.sb_hiwat)
+ goto send;
+
+ /*
+ * Make sure that the delayed ack timer is set if
+ * we delayed sending a window update because of
+ * streaming detection.
+ */
+ if ((tp->t_flags & TF_STRETCHACK) &&
+ !(tp->t_flags & TF_DELACK)) {
+ tp->t_flags |= TF_DELACK;
+ tp->t_timer[TCPT_DELACK] =
+ OFFSET_FROM_START(tp, tcp_delack);
+ }
+ }
+
+ /*
+ * Send if we owe the peer an ACK, RST, SYN, or urgent data. ACKNOW
+ * is also a catch-all for the retransmit timer timeout case.
+ */