2 * Copyright (c) 2012-2013 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
)
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
, "Reached MPTCP socket limit."));
211 lck_mtx_unlock(&mppi
->mppi_lock
);
213 mpp
= zalloc(mppi
->mppi_zone
);
217 bzero(mpp
, mppi
->mppi_size
);
218 lck_mtx_init(&mpp
->mpp_lock
, mppi
->mppi_lock_grp
, mppi
->mppi_lock_attr
);
219 mpp
->mpp_pcbinfo
= mppi
;
220 mpp
->mpp_state
= MPPCB_STATE_INUSE
;
221 mpp
->mpp_socket
= so
;
224 lck_mtx_lock(&mppi
->mppi_lock
);
225 mpp
->mpp_flags
|= MPP_ATTACHED
;
226 TAILQ_INSERT_TAIL(&mppi
->mppi_pcbs
, mpp
, mpp_entry
);
228 lck_mtx_unlock(&mppi
->mppi_lock
);
234 mp_pcbdetach(struct mppcb
*mpp
)
236 struct socket
*so
= mpp
->mpp_socket
;
238 VERIFY(so
->so_pcb
== mpp
);
240 mpp
->mpp_state
= MPPCB_STATE_DEAD
;
241 if (!(so
->so_flags
& SOF_PCBCLEARING
))
242 so
->so_flags
|= SOF_PCBCLEARING
;
248 mp_pcbdispose(struct mppcb
*mpp
)
250 struct mppcbinfo
*mppi
= mpp
->mpp_pcbinfo
;
252 VERIFY(mppi
!= NULL
);
254 lck_mtx_assert(&mppi
->mppi_lock
, LCK_MTX_ASSERT_OWNED
);
255 lck_mtx_assert(&mpp
->mpp_lock
, LCK_MTX_ASSERT_OWNED
);
257 VERIFY(mpp
->mpp_state
== MPPCB_STATE_DEAD
);
259 VERIFY(mpp
->mpp_flags
& MPP_ATTACHED
);
260 mpp
->mpp_flags
&= ~MPP_ATTACHED
;
261 TAILQ_REMOVE(&mppi
->mppi_pcbs
, mpp
, mpp_entry
);
262 VERIFY(mppi
->mppi_count
!= 0);
265 VERIFY(mpp
->mpp_socket
!= NULL
);
266 VERIFY(mpp
->mpp_socket
->so_usecount
== 0);
267 mpp
->mpp_socket
->so_pcb
= NULL
;
268 mpp
->mpp_socket
= NULL
;
270 lck_mtx_unlock(&mpp
->mpp_lock
);
271 lck_mtx_destroy(&mpp
->mpp_lock
, mppi
->mppi_lock_grp
);
272 zfree(mppi
->mppi_zone
, mpp
);