@@ -283,6 +283,10 @@ static void mptcp_reset_timer(struct sock *sk)
283283void mptcp_data_acked (struct sock * sk )
284284{
285285 mptcp_reset_timer (sk );
286+
287+ if (!sk_stream_is_writeable (sk ) &&
288+ schedule_work (& mptcp_sk (sk )-> work ))
289+ sock_hold (sk );
286290}
287291
288292static void mptcp_stop_timer (struct sock * sk )
@@ -900,10 +904,13 @@ static void mptcp_retransmit_handler(struct sock *sk)
900904{
901905 struct mptcp_sock * msk = mptcp_sk (sk );
902906
903- if (atomic64_read (& msk -> snd_una ) == msk -> write_seq )
907+ if (atomic64_read (& msk -> snd_una ) == msk -> write_seq ) {
904908 mptcp_stop_timer (sk );
905- else
906- mptcp_reset_timer (sk );
909+ } else {
910+ set_bit (MPTCP_WORK_RTX , & msk -> flags );
911+ if (schedule_work (& msk -> work ))
912+ sock_hold (sk );
913+ }
907914}
908915
909916static void mptcp_retransmit_timer (struct timer_list * t )
@@ -925,6 +932,37 @@ static void mptcp_retransmit_timer(struct timer_list *t)
925932 sock_put (sk );
926933}
927934
935+ /* Find an idle subflow. Return NULL if there is unacked data at tcp
936+ * level.
937+ *
938+ * A backup subflow is returned only if that is the only kind available.
939+ */
940+ static struct sock * mptcp_subflow_get_retrans (const struct mptcp_sock * msk )
941+ {
942+ struct mptcp_subflow_context * subflow ;
943+ struct sock * backup = NULL ;
944+
945+ sock_owned_by_me ((const struct sock * )msk );
946+
947+ mptcp_for_each_subflow (msk , subflow ) {
948+ struct sock * ssk = mptcp_subflow_tcp_sock (subflow );
949+
950+ /* still data outstanding at TCP level? Don't retransmit. */
951+ if (!tcp_write_queue_empty (ssk ))
952+ return NULL ;
953+
954+ if (subflow -> backup ) {
955+ if (!backup )
956+ backup = ssk ;
957+ continue ;
958+ }
959+
960+ return ssk ;
961+ }
962+
963+ return backup ;
964+ }
965+
928966/* subflow sockets can be either outgoing (connect) or incoming
929967 * (accept).
930968 *
@@ -958,11 +996,62 @@ static unsigned int mptcp_sync_mss(struct sock *sk, u32 pmtu)
958996static void mptcp_worker (struct work_struct * work )
959997{
960998 struct mptcp_sock * msk = container_of (work , struct mptcp_sock , work );
961- struct sock * sk = & msk -> sk .icsk_inet .sk ;
999+ struct sock * ssk , * sk = & msk -> sk .icsk_inet .sk ;
1000+ int orig_len , orig_offset , ret , mss_now = 0 , size_goal = 0 ;
1001+ struct mptcp_data_frag * dfrag ;
1002+ u64 orig_write_seq ;
1003+ size_t copied = 0 ;
1004+ struct msghdr msg ;
1005+ long timeo = 0 ;
9621006
9631007 lock_sock (sk );
1008+ mptcp_clean_una (sk );
9641009 __mptcp_flush_join_list (msk );
9651010 __mptcp_move_skbs (msk );
1011+
1012+ if (!test_and_clear_bit (MPTCP_WORK_RTX , & msk -> flags ))
1013+ goto unlock ;
1014+
1015+ dfrag = mptcp_rtx_head (sk );
1016+ if (!dfrag )
1017+ goto unlock ;
1018+
1019+ ssk = mptcp_subflow_get_retrans (msk );
1020+ if (!ssk )
1021+ goto reset_unlock ;
1022+
1023+ lock_sock (ssk );
1024+
1025+ msg .msg_flags = MSG_DONTWAIT ;
1026+ orig_len = dfrag -> data_len ;
1027+ orig_offset = dfrag -> offset ;
1028+ orig_write_seq = dfrag -> data_seq ;
1029+ while (dfrag -> data_len > 0 ) {
1030+ ret = mptcp_sendmsg_frag (sk , ssk , & msg , dfrag , & timeo , & mss_now ,
1031+ & size_goal );
1032+ if (ret < 0 )
1033+ break ;
1034+
1035+ copied += ret ;
1036+ dfrag -> data_len -= ret ;
1037+ dfrag -> offset += ret ;
1038+ }
1039+ if (copied )
1040+ tcp_push (ssk , msg .msg_flags , mss_now , tcp_sk (ssk )-> nonagle ,
1041+ size_goal );
1042+
1043+ dfrag -> data_seq = orig_write_seq ;
1044+ dfrag -> offset = orig_offset ;
1045+ dfrag -> data_len = orig_len ;
1046+
1047+ mptcp_set_timeout (sk , ssk );
1048+ release_sock (ssk );
1049+
1050+ reset_unlock :
1051+ if (!mptcp_timer_pending (sk ))
1052+ mptcp_reset_timer (sk );
1053+
1054+ unlock :
9661055 release_sock (sk );
9671056 sock_put (sk );
9681057}
@@ -1124,6 +1213,7 @@ static int mptcp_disconnect(struct sock *sk, int flags)
11241213 lock_sock (sk );
11251214 __mptcp_clear_xmit (sk );
11261215 release_sock (sk );
1216+ mptcp_cancel_work (sk );
11271217 return tcp_disconnect (sk , flags );
11281218}
11291219
0 commit comments