]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netinet/mptcp_timer.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / bsd / netinet / mptcp_timer.c
index b376cea471154c0dffb08677ac86a30db1b1ba00..b1fba1579e19f6577f2d0994e23f2b625e9d5913 100644 (file)
@@ -66,8 +66,10 @@ SYSCTL_INT(_net_inet_mptcp, OID_AUTO, tw, CTLFLAG_RW | CTLFLAG_LOCKED,
 
 #define TIMEVAL_TO_HZ(_tv_)     ((_tv_).tv_sec * hz + (_tv_).tv_usec / hz)
 
+static int mptcp_cancel_urgency_timer(struct mptses *mpte);
+
 static int
-mptcp_timer_demux(struct mptses *mpte, uint32_t now_msecs)
+mptcp_timer_demux(struct mptses *mpte, uint64_t now_msecs)
 {
        struct mptcb *mp_tp = NULL;
        mp_tp = mpte->mpte_mptcb;
@@ -75,14 +77,12 @@ mptcp_timer_demux(struct mptses *mpte, uint32_t now_msecs)
 
        DTRACE_MPTCP2(timer, struct mptses *, mpte, struct mptcb *, mp_tp);
 
-       mpte_lock_assert_held(mpte);
        switch (mp_tp->mpt_timer_vals) {
        case MPTT_REXMT:
                if (mp_tp->mpt_rxtstart == 0) {
                        break;
                }
-               if ((now_msecs - mp_tp->mpt_rxtstart) >
-                   (mptcp_rto * hz)) {
+               if ((now_msecs - mp_tp->mpt_rxtstart) > (mptcp_rto * hz)) {
                        if (MPTCP_SEQ_GT(mp_tp->mpt_snduna, mp_tp->mpt_rtseq)) {
                                mp_tp->mpt_timer_vals = 0;
                                mp_tp->mpt_rtseq = 0;
@@ -132,8 +132,8 @@ mptcp_timer(struct mppcbinfo *mppi)
 {
        struct mppcb *mpp, *tmpp;
        struct timeval now;
-       u_int32_t now_msecs;
        uint32_t resched_timer = 0;
+       uint64_t now_msecs;
 
        LCK_MTX_ASSERT(&mppi->mppi_lock, LCK_MTX_ASSERT_OWNED);
 
@@ -144,16 +144,15 @@ mptcp_timer(struct mppcbinfo *mppi)
                struct mptses *mpte;
 
                mp_so = mpp->mpp_socket;
-               VERIFY(mp_so != NULL);
                mpte = mptompte(mpp);
-               VERIFY(mpte != NULL);
-               mpte_lock(mpte);
+               socket_lock(mp_so, 1);
+
                VERIFY(mpp->mpp_flags & MPP_ATTACHED);
 
                if (mptcp_timer_demux(mpte, now_msecs)) {
                        resched_timer = 1;
                }
-               mpte_unlock(mpte);
+               socket_unlock(mp_so, 1);
        }
 
        return resched_timer;
@@ -171,7 +170,7 @@ mptcp_start_timer(struct mptses *mpte, int timer_type)
        mptcplog((LOG_DEBUG, "MPTCP Socket: %s: %d\n", __func__, timer_type),
            MPTCP_SOCKET_DBG, MPTCP_LOGLVL_VERBOSE);
 
-       mpte_lock_assert_held(mpte);
+       socket_lock_assert_owned(mptetoso(mpte));
 
        switch (timer_type) {
        case MPTT_REXMT:
@@ -198,8 +197,7 @@ mptcp_start_timer(struct mptses *mpte, int timer_type)
 void
 mptcp_cancel_timer(struct mptcb *mp_tp, int timer_type)
 {
-       mpte_lock_assert_held(mp_tp->mpt_mpte);
-       DTRACE_MPTCP2(cancel__timer, struct mptcb *, mp_tp, int, timer_type);
+       socket_lock_assert_owned(mptetoso(mp_tp->mpt_mpte));
 
        switch (timer_type) {
        case MPTT_REXMT:
@@ -221,7 +219,113 @@ mptcp_cancel_timer(struct mptcb *mp_tp, int timer_type)
 void
 mptcp_cancel_all_timers(struct mptcb *mp_tp)
 {
+       struct mptses *mpte = mp_tp->mpt_mpte;
+
+       if (mpte->mpte_time_target) {
+               mptcp_cancel_urgency_timer(mpte);
+       }
+
        mptcp_cancel_timer(mp_tp, MPTT_REXMT);
        mptcp_cancel_timer(mp_tp, MPTT_TW);
        mptcp_cancel_timer(mp_tp, MPTT_FASTCLOSE);
 }
+
+static void
+mptcp_urgency_timer_locked(struct mptses *mpte)
+{
+       uint64_t time_now = mach_continuous_time();
+       struct socket *mp_so = mptetoso(mpte);
+
+       VERIFY(mp_so->so_usecount >= 0);
+
+       os_log(mptcp_log_handle, "%s - %lx: timer at %llu now %llu usecount %u\n",
+           __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte), mpte->mpte_time_target, time_now, mp_so->so_usecount);
+
+       mptcp_check_subflows_and_add(mpte);
+
+       mp_so->so_usecount--;
+}
+
+static void
+mptcp_urgency_timer(void *param0, __unused void *param1)
+{
+       struct mptses *mpte = (struct mptses *)param0;
+       struct socket *mp_so = mptetoso(mpte);
+
+       socket_lock(mp_so, 1);
+
+       mptcp_urgency_timer_locked(mpte);
+
+       socket_unlock(mp_so, 1);
+}
+
+void
+mptcp_init_urgency_timer(struct mptses *mpte)
+{
+       /* thread_call_allocate never fails */
+       mpte->mpte_time_thread = thread_call_allocate(mptcp_urgency_timer, mpte);
+}
+
+void
+mptcp_set_urgency_timer(struct mptses *mpte)
+{
+       struct socket *mp_so = mptetoso(mpte);
+       uint64_t time_now = 0;
+       boolean_t ret = FALSE;
+
+       socket_lock_assert_owned(mp_so);
+
+       VERIFY(mp_so->so_usecount >= 0);
+       if (mp_so->so_usecount == 0) {
+               goto exit_log;
+       }
+
+       if (mpte->mpte_time_target == 0) {
+               mptcp_cancel_urgency_timer(mpte);
+
+               goto exit_log;
+       }
+
+       time_now = mach_continuous_time();
+
+       if ((int64_t)(mpte->mpte_time_target - time_now) > 0) {
+               mptcp_check_subflows_and_remove(mpte);
+
+               ret = thread_call_enter_delayed_with_leeway(mpte->mpte_time_thread, NULL,
+                   mpte->mpte_time_target, 0, THREAD_CALL_CONTINUOUS);
+
+               if (!ret) {
+                       mp_so->so_usecount++;
+               }
+       } else if ((int64_t)(mpte->mpte_time_target - time_now) <= 0) {
+               mp_so->so_usecount++;
+
+               /* Already passed the deadline, trigger subflows now */
+               mptcp_urgency_timer_locked(mpte);
+       }
+
+exit_log:
+       os_log(mptcp_log_handle, "%s - %lx: timer at %llu now %llu usecount %u ret %u\n",
+           __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte), mpte->mpte_time_target, time_now,
+           mp_so->so_usecount, ret);
+}
+
+static int
+mptcp_cancel_urgency_timer(struct mptses *mpte)
+{
+       struct socket *mp_so = mptetoso(mpte);
+       boolean_t ret;
+
+       ret = thread_call_cancel(mpte->mpte_time_thread);
+
+       os_log(mptcp_log_handle, "%s - %lx: Canceled timer thread usecount %u ret %u\n",
+           __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte), mp_so->so_usecount, ret);
+
+       mptcp_check_subflows_and_remove(mpte);
+
+       if (ret) {
+               mp_so->so_usecount--;
+       }
+
+       return 0;
+}