]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet/mptcp_timer.c
xnu-2782.1.97.tar.gz
[apple/xnu.git] / bsd / netinet / mptcp_timer.c
CommitLineData
39236c6e
A
1/*
2 * Copyright (c) 2012-2013 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
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>
38
39#include <mach/sdt.h>
40
41#include <netinet/mp_pcb.h>
42#include <netinet/mptcp_var.h>
43#include <netinet/mptcp_timer.h>
44#include <netinet/mptcp_seq.h>
45
46#include <kern/locks.h>
47
48/*
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.
51 */
52static u_int32_t mptcp_rto = 3;
53SYSCTL_INT(_net_inet_mptcp, OID_AUTO, rto, CTLFLAG_RW | CTLFLAG_LOCKED,
54 &mptcp_rto, 0, "MPTCP Retransmission Timeout");
55
56static int mptcp_nrtos = 3;
57SYSCTL_INT(_net_inet_mptcp, OID_AUTO, nrto, CTLFLAG_RW | CTLFLAG_LOCKED,
58 &mptcp_rto, 0, "MPTCP Retransmissions");
59
60/*
61 * MPTCP connections timewait interval in seconds.
62 */
63static u_int32_t mptcp_tw = 60;
64SYSCTL_INT(_net_inet_mptcp, OID_AUTO, tw, CTLFLAG_RW | CTLFLAG_LOCKED,
65 &mptcp_tw, 0, "MPTCP Timewait Period");
66
67#define TIMEVAL_TO_HZ(_tv_) ((_tv_).tv_sec * hz + (_tv_).tv_usec / hz)
68
69static int
70mptcp_timer_demux(struct mptses *mpte, uint32_t now_msecs)
71{
72 struct mptcb *mp_tp = NULL;
73 mp_tp = mpte->mpte_mptcb;
74 int resched_timer = 0;
75
76 DTRACE_MPTCP2(timer, struct mptses *, mpte, struct mptcb *, mp_tp);
77 mptcplog2((LOG_DEBUG, "%s: running %d\n", __func__,
78 mp_tp->mpt_timer_vals));
79
80 MPTE_LOCK_ASSERT_HELD(mpte);
81 MPT_LOCK(mp_tp);
82 switch (mp_tp->mpt_timer_vals) {
83 case MPTT_REXMT:
84 if (mp_tp->mpt_rxtstart == 0)
85 break;
86 if ((now_msecs - mp_tp->mpt_rxtstart) >
87 (mptcp_rto*hz)) {
88 if (MPTCP_SEQ_GT(mp_tp->mpt_snduna,
89 mp_tp->mpt_rtseq)) {
90 mp_tp->mpt_timer_vals = 0;
91 mp_tp->mpt_rtseq = 0;
92 break;
93 }
94 mp_tp->mpt_rxtshift++;
95 if (mp_tp->mpt_rxtshift > mptcp_nrtos) {
96 mp_tp->mpt_softerror = ETIMEDOUT;
97 DTRACE_MPTCP1(error, struct mptcb *, mp_tp);
98 } else {
99 mp_tp->mpt_sndnxt = mp_tp->mpt_rtseq;
100 MPT_UNLOCK(mp_tp);
101 mptcplog((LOG_DEBUG, "%s: REXMT %d times.\n",
102 __func__, mp_tp->mpt_rxtshift));
103 mptcp_output(mpte);
104 MPT_LOCK(mp_tp);
105 }
106 } else {
107 resched_timer = 1;
108 }
109 break;
110 case MPTT_TW:
111 /* Allows for break before make XXX */
112 if (mp_tp->mpt_timewait == 0)
113 VERIFY(0);
114 if ((now_msecs - mp_tp->mpt_timewait) >
115 (mptcp_tw * hz)) {
116 mp_tp->mpt_softerror = ETIMEDOUT;
117 DTRACE_MPTCP1(error, struct mptcb *, mp_tp);
118 } else {
119 resched_timer = 1;
120 }
121 break;
122 case MPTT_FASTCLOSE:
123 /* TODO XXX */
124 break;
125 default:
126 break;
127 }
128 MPT_UNLOCK(mp_tp);
129
130 return (resched_timer);
131}
132
133uint32_t
134mptcp_timer(struct mppcbinfo *mppi)
135{
136 struct mppcb *mpp, *tmpp;
137 struct timeval now;
138 u_int32_t now_msecs;
139 uint32_t resched_timer = 0;
140
141 lck_mtx_assert(&mppi->mppi_lock, LCK_MTX_ASSERT_OWNED);
142
143 microuptime(&now);
144 now_msecs = TIMEVAL_TO_HZ(now);
145 TAILQ_FOREACH_SAFE(mpp, &mppi->mppi_pcbs, mpp_entry, tmpp) {
146 struct socket *mp_so;
147 struct mptses *mpte;
148
149 mp_so = mpp->mpp_socket;
150 VERIFY(mp_so != NULL);
151 mpte = mptompte(mpp);
152 VERIFY(mpte != NULL);
153 MPTE_LOCK(mpte);
154 VERIFY(mpp->mpp_flags & MPP_ATTACHED);
155
156 if (mpp->mpp_flags & MPP_DEFUNCT) {
157 MPTE_UNLOCK(mpte);
158 continue;
159 }
160
161 if (mptcp_timer_demux(mpte, now_msecs))
162 resched_timer = 1;
163 MPTE_UNLOCK(mpte);
164 }
165
166 return (resched_timer);
167}
168
169void
170mptcp_start_timer(struct mptcb *mp_tp, int timer_type)
171{
172 struct timeval now;
173
174 microuptime(&now);
175
176 MPT_LOCK_ASSERT_HELD(mp_tp);
177
178 DTRACE_MPTCP2(start__timer, struct mptcb *, mp_tp, int, timer_type);
179 mptcplog((LOG_DEBUG, "%s %d\n", __func__, timer_type));
180
181 switch (timer_type) {
182 case MPTT_REXMT:
183 mp_tp->mpt_timer_vals |= MPTT_REXMT;
184 mp_tp->mpt_rxtstart = TIMEVAL_TO_HZ(now);
185 mp_tp->mpt_rxtshift = 0;
186 mp_tp->mpt_rtseq = mp_tp->mpt_sndnxt;
187 break;
188 case MPTT_TW:
189 mp_tp->mpt_timer_vals |= MPTT_TW;
190 mp_tp->mpt_timewait = TIMEVAL_TO_HZ(now);
191 break;
192 case MPTT_FASTCLOSE:
193 /* NO-OP */
194 break;
195 default:
196 VERIFY(0);
197 /* NOTREACHED */
198 }
199 mptcp_timer_sched();
200}
201
202void
203mptcp_cancel_timer(struct mptcb *mp_tp, int timer_type)
204{
205 MPT_LOCK_ASSERT_HELD(mp_tp);
206
207 DTRACE_MPTCP2(cancel__timer, struct mptcb *, mp_tp, int, timer_type);
208 mptcplog3((LOG_DEBUG, "%s %d\n", __func__, timer_type));
209
210 switch (timer_type) {
211 case MPTT_REXMT:
212 mp_tp->mpt_rxtstart = 0;
213 mp_tp->mpt_rxtshift = 0;
214 mp_tp->mpt_timer_vals = 0;
215 break;
216 case MPTT_TW:
217 /* NO-OP */
218 break;
219 case MPTT_FASTCLOSE:
220 /* NO-OP */
221 break;
222 default:
223 break;
224 }
225}
226
227void
228mptcp_cancel_all_timers(struct mptcb *mp_tp)
229{
230 mptcp_cancel_timer(mp_tp, MPTT_REXMT);
231 mptcp_cancel_timer(mp_tp, MPTT_TW);
232 mptcp_cancel_timer(mp_tp, MPTT_FASTCLOSE);
233}