]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netinet/mptcp_timer.c
2 * Copyright (c) 2012-2017 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/kernel.h>
32 #include <sys/mcache.h>
33 #include <sys/socket.h>
34 #include <sys/socketvar.h>
35 #include <sys/syslog.h>
36 #include <sys/protosw.h>
37 #include <sys/sysctl.h>
41 #include <netinet/mp_pcb.h>
42 #include <netinet/mptcp_var.h>
43 #include <netinet/mptcp_timer.h>
44 #include <netinet/mptcp_seq.h>
46 #include <kern/locks.h>
49 * MPTCP Retransmission Timer comes into play only when subflow level
50 * data is acked, but Data ACK is not received. Time is in seconds.
52 static u_int32_t mptcp_rto
= 3;
53 SYSCTL_INT(_net_inet_mptcp
, OID_AUTO
, rto
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
54 &mptcp_rto
, 0, "MPTCP Retransmission Timeout");
56 static int mptcp_nrtos
= 3;
57 SYSCTL_INT(_net_inet_mptcp
, OID_AUTO
, nrto
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
58 &mptcp_rto
, 0, "MPTCP Retransmissions");
61 * MPTCP connections timewait interval in seconds.
63 static u_int32_t mptcp_tw
= 60;
64 SYSCTL_INT(_net_inet_mptcp
, OID_AUTO
, tw
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
65 &mptcp_tw
, 0, "MPTCP Timewait Period");
67 #define TIMEVAL_TO_HZ(_tv_) ((_tv_).tv_sec * hz + (_tv_).tv_usec / hz)
69 static int mptcp_cancel_urgency_timer(struct mptses
*mpte
);
72 mptcp_timer_demux(struct mptses
*mpte
, uint32_t now_msecs
)
74 struct mptcb
*mp_tp
= NULL
;
75 mp_tp
= mpte
->mpte_mptcb
;
76 int resched_timer
= 0;
78 DTRACE_MPTCP2(timer
, struct mptses
*, mpte
, struct mptcb
*, mp_tp
);
80 switch (mp_tp
->mpt_timer_vals
) {
82 if (mp_tp
->mpt_rxtstart
== 0) {
85 if ((now_msecs
- mp_tp
->mpt_rxtstart
) >
87 if (MPTCP_SEQ_GT(mp_tp
->mpt_snduna
, mp_tp
->mpt_rtseq
)) {
88 mp_tp
->mpt_timer_vals
= 0;
92 mp_tp
->mpt_rxtshift
++;
93 if (mp_tp
->mpt_rxtshift
> mptcp_nrtos
) {
94 mp_tp
->mpt_softerror
= ETIMEDOUT
;
95 DTRACE_MPTCP1(error
, struct mptcb
*, mp_tp
);
97 mp_tp
->mpt_sndnxt
= mp_tp
->mpt_rtseq
;
98 os_log_info(mptcp_log_handle
,
99 "%s: REXMT %d sndnxt %u\n",
100 __func__
, mp_tp
->mpt_rxtshift
,
101 (uint32_t)mp_tp
->mpt_sndnxt
);
109 /* Allows for break before make XXX */
110 if (mp_tp
->mpt_timewait
== 0) {
113 if ((now_msecs
- mp_tp
->mpt_timewait
) >
115 mp_tp
->mpt_softerror
= ETIMEDOUT
;
116 DTRACE_MPTCP1(error
, struct mptcb
*, mp_tp
);
128 return resched_timer
;
132 mptcp_timer(struct mppcbinfo
*mppi
)
134 struct mppcb
*mpp
, *tmpp
;
137 uint32_t resched_timer
= 0;
139 LCK_MTX_ASSERT(&mppi
->mppi_lock
, LCK_MTX_ASSERT_OWNED
);
142 now_msecs
= TIMEVAL_TO_HZ(now
);
143 TAILQ_FOREACH_SAFE(mpp
, &mppi
->mppi_pcbs
, mpp_entry
, tmpp
) {
144 struct socket
*mp_so
;
147 mp_so
= mpp
->mpp_socket
;
148 mpte
= mptompte(mpp
);
149 socket_lock(mp_so
, 1);
151 VERIFY(mpp
->mpp_flags
& MPP_ATTACHED
);
153 if (mptcp_timer_demux(mpte
, now_msecs
)) {
156 socket_unlock(mp_so
, 1);
159 return resched_timer
;
163 mptcp_start_timer(struct mptses
*mpte
, int timer_type
)
166 struct mptcb
*mp_tp
= mpte
->mpte_mptcb
;
170 DTRACE_MPTCP2(start__timer
, struct mptcb
*, mp_tp
, int, timer_type
);
171 mptcplog((LOG_DEBUG
, "MPTCP Socket: %s: %d\n", __func__
, timer_type
),
172 MPTCP_SOCKET_DBG
, MPTCP_LOGLVL_VERBOSE
);
174 socket_lock_assert_owned(mptetoso(mpte
));
176 switch (timer_type
) {
178 mp_tp
->mpt_timer_vals
|= MPTT_REXMT
;
179 mp_tp
->mpt_rxtstart
= TIMEVAL_TO_HZ(now
);
180 mp_tp
->mpt_rxtshift
= 0;
181 mp_tp
->mpt_rtseq
= mp_tp
->mpt_sndnxt
;
184 /* XXX: Not implemented yet */
185 mp_tp
->mpt_timer_vals
|= MPTT_TW
;
186 mp_tp
->mpt_timewait
= TIMEVAL_TO_HZ(now
);
199 mptcp_cancel_timer(struct mptcb
*mp_tp
, int timer_type
)
201 socket_lock_assert_owned(mptetoso(mp_tp
->mpt_mpte
));
203 switch (timer_type
) {
205 mp_tp
->mpt_rxtstart
= 0;
206 mp_tp
->mpt_rxtshift
= 0;
207 mp_tp
->mpt_timer_vals
= 0;
221 mptcp_cancel_all_timers(struct mptcb
*mp_tp
)
223 struct mptses
*mpte
= mp_tp
->mpt_mpte
;
225 if (mpte
->mpte_time_target
) {
226 mptcp_cancel_urgency_timer(mpte
);
229 mptcp_cancel_timer(mp_tp
, MPTT_REXMT
);
230 mptcp_cancel_timer(mp_tp
, MPTT_TW
);
231 mptcp_cancel_timer(mp_tp
, MPTT_FASTCLOSE
);
235 mptcp_urgency_timer_locked(struct mptses
*mpte
)
237 uint64_t time_now
= mach_continuous_time();
238 struct socket
*mp_so
= mptetoso(mpte
);
240 VERIFY(mp_so
->so_usecount
>= 0);
242 os_log(mptcp_log_handle
, "%s - %lx: timer at %llu now %llu usecount %u\n",
243 __func__
, (unsigned long)VM_KERNEL_ADDRPERM(mpte
), mpte
->mpte_time_target
, time_now
, mp_so
->so_usecount
);
245 mptcp_check_subflows_and_add(mpte
);
247 mp_so
->so_usecount
--;
251 mptcp_urgency_timer(void *param0
, __unused
void *param1
)
253 struct mptses
*mpte
= (struct mptses
*)param0
;
254 struct socket
*mp_so
= mptetoso(mpte
);
256 socket_lock(mp_so
, 1);
258 mptcp_urgency_timer_locked(mpte
);
260 socket_unlock(mp_so
, 1);
264 mptcp_init_urgency_timer(struct mptses
*mpte
)
266 /* thread_call_allocate never fails */
267 mpte
->mpte_time_thread
= thread_call_allocate(mptcp_urgency_timer
, mpte
);
271 mptcp_set_urgency_timer(struct mptses
*mpte
)
273 struct socket
*mp_so
= mptetoso(mpte
);
274 uint64_t time_now
= 0;
275 boolean_t ret
= FALSE
;
277 socket_lock_assert_owned(mp_so
);
279 VERIFY(mp_so
->so_usecount
>= 0);
280 if (mp_so
->so_usecount
== 0) {
284 if (mpte
->mpte_time_target
== 0) {
285 mptcp_cancel_urgency_timer(mpte
);
290 time_now
= mach_continuous_time();
292 if ((int64_t)(mpte
->mpte_time_target
- time_now
) > 0) {
293 mptcp_check_subflows_and_remove(mpte
);
295 ret
= thread_call_enter_delayed_with_leeway(mpte
->mpte_time_thread
, NULL
,
296 mpte
->mpte_time_target
, 0, THREAD_CALL_CONTINUOUS
);
299 mp_so
->so_usecount
++;
301 } else if ((int64_t)(mpte
->mpte_time_target
- time_now
) <= 0) {
302 mp_so
->so_usecount
++;
304 /* Already passed the deadline, trigger subflows now */
305 mptcp_urgency_timer_locked(mpte
);
309 os_log(mptcp_log_handle
, "%s - %lx: timer at %llu now %llu usecount %u ret %u\n",
310 __func__
, (unsigned long)VM_KERNEL_ADDRPERM(mpte
), mpte
->mpte_time_target
, time_now
,
311 mp_so
->so_usecount
, ret
);
315 mptcp_cancel_urgency_timer(struct mptses
*mpte
)
317 struct socket
*mp_so
= mptetoso(mpte
);
320 ret
= thread_call_cancel(mpte
->mpte_time_thread
);
322 os_log(mptcp_log_handle
, "%s - %lx: Canceled timer thread usecount %u ret %u\n",
323 __func__
, (unsigned long)VM_KERNEL_ADDRPERM(mpte
), mp_so
->so_usecount
, ret
);
325 mptcp_check_subflows_and_remove(mpte
);
328 mp_so
->so_usecount
--;