2 * Copyright (c) 2012-2016 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>
33 #include <sys/mcache.h>
34 #include <sys/syslog.h>
35 #include <sys/socket.h>
36 #include <sys/socketvar.h>
37 #include <sys/protosw.h>
38 #include <sys/proc_internal.h>
40 #include <mach/boolean.h>
41 #include <kern/zalloc.h>
42 #include <kern/locks.h>
44 #include <netinet/mp_pcb.h>
45 #include <netinet/mptcp_var.h>
47 static lck_grp_t
*mp_lock_grp
;
48 static lck_attr_t
*mp_lock_attr
;
49 static lck_grp_attr_t
*mp_lock_grp_attr
;
50 decl_lck_mtx_data(static, mp_lock
); /* global MULTIPATH lock */
51 decl_lck_mtx_data(static, mp_timeout_lock
);
53 static TAILQ_HEAD(, mppcbinfo
) mppi_head
= TAILQ_HEAD_INITIALIZER(mppi_head
);
55 static boolean_t mp_timeout_run
; /* MP timer is scheduled to run */
56 static boolean_t mp_garbage_collecting
;
57 static boolean_t mp_ticking
;
58 static void mp_sched_timeout(void);
59 static void mp_timeout(void *);
64 static int mp_initialized
= 0;
66 VERIFY(!mp_initialized
);
69 mp_lock_grp_attr
= lck_grp_attr_alloc_init();
70 mp_lock_grp
= lck_grp_alloc_init("multipath", mp_lock_grp_attr
);
71 mp_lock_attr
= lck_attr_alloc_init();
72 lck_mtx_init(&mp_lock
, mp_lock_grp
, mp_lock_attr
);
73 lck_mtx_init(&mp_timeout_lock
, mp_lock_grp
, mp_lock_attr
);
80 struct mppcbinfo
*mppi
;
86 * Update coarse-grained networking timestamp (in sec.); the idea
87 * is to piggy-back on the timeout callout to update the counter
88 * returnable via net_uptime().
92 lck_mtx_lock_spin(&mp_timeout_lock
);
93 gc
= mp_garbage_collecting
;
94 mp_garbage_collecting
= FALSE
;
100 lck_mtx_unlock(&mp_timeout_lock
);
102 lck_mtx_lock(&mp_lock
);
103 TAILQ_FOREACH(mppi
, &mppi_head
, mppi_entry
) {
104 if ((gc
&& mppi
->mppi_gc
!= NULL
) ||
105 (t
&& mppi
->mppi_timer
!= NULL
)) {
106 lck_mtx_lock(&mppi
->mppi_lock
);
107 if (gc
&& mppi
->mppi_gc
!= NULL
)
108 gc_act
+= mppi
->mppi_gc(mppi
);
109 if (t
&& mppi
->mppi_timer
!= NULL
)
110 t_act
+= mppi
->mppi_timer(mppi
);
111 lck_mtx_unlock(&mppi
->mppi_lock
);
114 lck_mtx_unlock(&mp_lock
);
116 lck_mtx_lock_spin(&mp_timeout_lock
);
119 /* lock was dropped above, so check first before overriding */
120 if (!mp_garbage_collecting
)
121 mp_garbage_collecting
= (gc_act
!= 0);
123 mp_ticking
= (t_act
!= 0);
125 /* re-arm the timer if there's work to do */
126 mp_timeout_run
= FALSE
;
128 lck_mtx_unlock(&mp_timeout_lock
);
132 mp_sched_timeout(void)
134 lck_mtx_assert(&mp_timeout_lock
, LCK_MTX_ASSERT_OWNED
);
136 if (!mp_timeout_run
&& (mp_garbage_collecting
|| mp_ticking
)) {
137 lck_mtx_convert_spin(&mp_timeout_lock
);
138 mp_timeout_run
= TRUE
;
139 timeout(mp_timeout
, NULL
, hz
);
146 lck_mtx_lock_spin(&mp_timeout_lock
);
147 mp_garbage_collecting
= TRUE
;
149 lck_mtx_unlock(&mp_timeout_lock
);
153 mptcp_timer_sched(void)
155 lck_mtx_lock_spin(&mp_timeout_lock
);
158 lck_mtx_unlock(&mp_timeout_lock
);
162 mp_pcbinfo_attach(struct mppcbinfo
*mppi
)
164 struct mppcbinfo
*mppi0
;
166 lck_mtx_lock(&mp_lock
);
167 TAILQ_FOREACH(mppi0
, &mppi_head
, mppi_entry
) {
169 panic("%s: mppi %p already in the list\n",
174 TAILQ_INSERT_TAIL(&mppi_head
, mppi
, mppi_entry
);
175 lck_mtx_unlock(&mp_lock
);
179 mp_pcbinfo_detach(struct mppcbinfo
*mppi
)
181 struct mppcbinfo
*mppi0
;
184 lck_mtx_lock(&mp_lock
);
185 TAILQ_FOREACH(mppi0
, &mppi_head
, mppi_entry
) {
190 TAILQ_REMOVE(&mppi_head
, mppi0
, mppi_entry
);
193 lck_mtx_unlock(&mp_lock
);
199 mp_pcballoc(struct socket
*so
, struct mppcbinfo
*mppi
)
201 struct mppcb
*mpp
= NULL
;
203 VERIFY(sotomppcb(so
) == NULL
);
205 lck_mtx_lock(&mppi
->mppi_lock
);
206 if (mppi
->mppi_count
>= mptcp_socket_limit
) {
207 lck_mtx_unlock(&mppi
->mppi_lock
);
208 mptcplog((LOG_ERR
, "MPTCP Socket: Reached MPTCP socket limit."),
209 MPTCP_SOCKET_DBG
, MPTCP_LOGLVL_ERR
);
211 * This limit may be reached either because of
212 * a leak or a transient condition where
213 * MPTCP connections are not released fast
215 * We return EAFNOSUPPORT here to have user
216 * space library fallback to TCP.
217 * XXX We need to revist this when we get rid
218 * of the current low limit imposed on MPTCP.
220 return (EAFNOSUPPORT
);
222 lck_mtx_unlock(&mppi
->mppi_lock
);
224 mpp
= zalloc(mppi
->mppi_zone
);
229 bzero(mpp
, mppi
->mppi_size
);
230 lck_mtx_init(&mpp
->mpp_lock
, mppi
->mppi_lock_grp
, mppi
->mppi_lock_attr
);
231 mpp
->mpp_pcbinfo
= mppi
;
232 mpp
->mpp_state
= MPPCB_STATE_INUSE
;
233 mpp
->mpp_socket
= so
;
236 if (NULL
== mppi
->mppi_pcbe_create(so
, mpp
)) {
237 lck_mtx_destroy(&mpp
->mpp_lock
, mppi
->mppi_lock_grp
);
238 zfree(mppi
->mppi_zone
, mpp
);
242 lck_mtx_lock(&mppi
->mppi_lock
);
243 mpp
->mpp_flags
|= MPP_ATTACHED
;
244 TAILQ_INSERT_TAIL(&mppi
->mppi_pcbs
, mpp
, mpp_entry
);
246 lck_mtx_unlock(&mppi
->mppi_lock
);
252 mp_pcbdetach(struct mppcb
*mpp
)
254 struct socket
*so
= mpp
->mpp_socket
;
256 VERIFY(so
->so_pcb
== mpp
);
258 mpp
->mpp_state
= MPPCB_STATE_DEAD
;
259 if (!(so
->so_flags
& SOF_PCBCLEARING
))
260 so
->so_flags
|= SOF_PCBCLEARING
;
266 mp_pcbdispose(struct mppcb
*mpp
)
268 struct mppcbinfo
*mppi
= mpp
->mpp_pcbinfo
;
270 VERIFY(mppi
!= NULL
);
272 lck_mtx_assert(&mppi
->mppi_lock
, LCK_MTX_ASSERT_OWNED
);
273 lck_mtx_assert(&mpp
->mpp_lock
, LCK_MTX_ASSERT_OWNED
);
275 VERIFY(mpp
->mpp_state
== MPPCB_STATE_DEAD
);
277 VERIFY(mpp
->mpp_flags
& MPP_ATTACHED
);
278 mpp
->mpp_flags
&= ~MPP_ATTACHED
;
279 TAILQ_REMOVE(&mppi
->mppi_pcbs
, mpp
, mpp_entry
);
280 VERIFY(mppi
->mppi_count
!= 0);
283 VERIFY(mpp
->mpp_socket
!= NULL
);
284 VERIFY(mpp
->mpp_socket
->so_usecount
== 0);
285 mpp
->mpp_socket
->so_pcb
= NULL
;
286 mpp
->mpp_socket
= NULL
;
288 lck_mtx_unlock(&mpp
->mpp_lock
);
289 lck_mtx_destroy(&mpp
->mpp_lock
, mppi
->mppi_lock_grp
);
290 zfree(mppi
->mppi_zone
, mpp
);