1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
25 */
26
27 #include <sys/types.h>
28 #include <sys/vmsystm.h>
29 #include <inet/common.h>
30 #include "sctp_impl.h"
31
32 /* Control whether SCTP can enter defensive mode when under memory pressure. */
33 static boolean_t sctp_do_reclaim = B_TRUE;
34
35 static void sctp_reclaim_timer(void *);
36
37 /* Diagnostic routine used to return a string associated with the sctp state. */
38 char *
39 sctp_display(sctp_t *sctp, char *sup_buf)
40 {
41 char *buf;
42 char buf1[30];
43 static char priv_buf[INET6_ADDRSTRLEN * 2 + 80];
44 char *cp;
45 conn_t *connp;
46
47 if (sctp == NULL)
48 return ("NULL_SCTP");
49
50 connp = sctp->sctp_connp;
51 buf = (sup_buf != NULL) ? sup_buf : priv_buf;
52
53 switch (sctp->sctp_state) {
54 case SCTPS_IDLE:
55 cp = "SCTP_IDLE";
56 break;
57 case SCTPS_BOUND:
58 cp = "SCTP_BOUND";
59 break;
60 case SCTPS_LISTEN:
61 cp = "SCTP_LISTEN";
62 break;
63 case SCTPS_COOKIE_WAIT:
64 cp = "SCTP_COOKIE_WAIT";
65 break;
66 case SCTPS_COOKIE_ECHOED:
67 cp = "SCTP_COOKIE_ECHOED";
68 break;
69 case SCTPS_ESTABLISHED:
70 cp = "SCTP_ESTABLISHED";
71 break;
72 case SCTPS_SHUTDOWN_PENDING:
73 cp = "SCTP_SHUTDOWN_PENDING";
74 break;
75 case SCTPS_SHUTDOWN_SENT:
76 cp = "SCTPS_SHUTDOWN_SENT";
77 break;
78 case SCTPS_SHUTDOWN_RECEIVED:
79 cp = "SCTPS_SHUTDOWN_RECEIVED";
80 break;
81 case SCTPS_SHUTDOWN_ACK_SENT:
82 cp = "SCTPS_SHUTDOWN_ACK_SENT";
83 break;
84 default:
85 (void) mi_sprintf(buf1, "SCTPUnkState(%d)", sctp->sctp_state);
86 cp = buf1;
87 break;
88 }
89 (void) mi_sprintf(buf, "[%u, %u] %s",
90 ntohs(connp->conn_lport), ntohs(connp->conn_fport), cp);
91
92 return (buf);
93 }
94
95 void
96 sctp_display_all(sctp_stack_t *sctps)
97 {
98 sctp_t *sctp_walker;
99
100 mutex_enter(&sctps->sctps_g_lock);
101 for (sctp_walker = list_head(&sctps->sctps_g_list);
102 sctp_walker != NULL;
103 sctp_walker = (sctp_t *)list_next(&sctps->sctps_g_list,
104 sctp_walker)) {
105 (void) sctp_display(sctp_walker, NULL);
106 }
107 mutex_exit(&sctps->sctps_g_lock);
108 }
109
110 /*
111 * Given a sctp_stack_t and a port (in host byte order), find a listener
112 * configuration for that port and return the ratio.
113 */
114 uint32_t
115 sctp_find_listener_conf(sctp_stack_t *sctps, in_port_t port)
116 {
117 sctp_listener_t *sl;
118 uint32_t ratio = 0;
119
120 mutex_enter(&sctps->sctps_listener_conf_lock);
121 for (sl = list_head(&sctps->sctps_listener_conf); sl != NULL;
122 sl = list_next(&sctps->sctps_listener_conf, sl)) {
123 if (sl->sl_port == port) {
124 ratio = sl->sl_ratio;
125 break;
126 }
127 }
128 mutex_exit(&sctps->sctps_listener_conf_lock);
129 return (ratio);
130 }
131
132 /*
133 * To remove all listener limit configuration in a sctp_stack_t.
134 */
135 void
136 sctp_listener_conf_cleanup(sctp_stack_t *sctps)
137 {
138 sctp_listener_t *sl;
139
140 mutex_enter(&sctps->sctps_listener_conf_lock);
141 while ((sl = list_head(&sctps->sctps_listener_conf)) != NULL) {
142 list_remove(&sctps->sctps_listener_conf, sl);
143 kmem_free(sl, sizeof (sctp_listener_t));
144 }
145 mutex_destroy(&sctps->sctps_listener_conf_lock);
146 list_destroy(&sctps->sctps_listener_conf);
147 }
148
149
150 /*
151 * Timeout function to reset the SCTP stack variable sctps_reclaim to false.
152 */
153 static void
154 sctp_reclaim_timer(void *arg)
155 {
156 sctp_stack_t *sctps = (sctp_stack_t *)arg;
157 int64_t tot_assoc = 0;
158 int i;
159
160 for (i = 0; i < sctps->sctps_sc_cnt; i++)
161 tot_assoc += sctps->sctps_sc[i]->sctp_sc_assoc_cnt;
162
163 /*
164 * This happens only when a stack is going away. sctps_reclaim_tid
165 * should not be reset to 0 when returning in this case.
166 */
167 mutex_enter(&sctps->sctps_reclaim_lock);
168 if (!sctps->sctps_reclaim) {
169 mutex_exit(&sctps->sctps_reclaim_lock);
170 return;
171 }
172
173 if ((freemem >= lotsfree + needfree) || tot_assoc < maxusers) {
174 sctps->sctps_reclaim = B_FALSE;
175 sctps->sctps_reclaim_tid = 0;
176 } else {
177 /* Stay in defensive mode and restart the timer */
178 sctps->sctps_reclaim_tid = timeout(sctp_reclaim_timer,
179 sctps, MSEC_TO_TICK(sctps->sctps_reclaim_period));
180 }
181 mutex_exit(&sctps->sctps_reclaim_lock);
182 }
183
184 /*
185 * Kmem reclaim call back function. When the system is under memory
186 * pressure, we set the SCTP stack variable sctps_reclaim to true. This
187 * variable is reset to false after sctps_reclaim_period msecs. During this
188 * period, SCTP will be more aggressive in aborting connections not making
189 * progress, meaning retransmitting for shorter time (sctp_pa_early_abort/
190 * sctp_pp_early_abort number of strikes).
191 */
192 /* ARGSUSED */
193 void
194 sctp_conn_reclaim(void *arg)
195 {
196 netstack_handle_t nh;
197 netstack_t *ns;
198 sctp_stack_t *sctps;
199
200 if (!sctp_do_reclaim)
201 return;
202
203 /*
204 * The reclaim function may be called even when the system is not
205 * really under memory pressure.
206 */
207 if (freemem >= lotsfree + needfree)
208 return;
209
210 netstack_next_init(&nh);
211 while ((ns = netstack_next(&nh)) != NULL) {
212 int i;
213 int64_t tot_assoc = 0;
214
215 /*
216 * During boot time, the first netstack_t is created and
217 * initialized before SCTP has registered with the netstack
218 * framework. If this reclaim function is called before SCTP
219 * has finished its initialization, netstack_next() will
220 * return the first netstack_t (since its netstack_flags is
221 * not NSF_UNINIT). And its netstack_sctp will be NULL. We
222 * need to catch it.
223 *
224 * All subsequent netstack_t creation will not have this
225 * problem since the initialization is not finished until SCTP
226 * has finished its own sctp_stack_t initialization. Hence
227 * netstack_next() will not return one with NULL netstack_sctp.
228 */
229 if ((sctps = ns->netstack_sctp) == NULL) {
230 netstack_rele(ns);
231 continue;
232 }
233
234 /*
235 * Even if the system is under memory pressure, the reason may
236 * not be because of SCTP activity. Check the number of
237 * associations in each stack. If the number exceeds the
238 * threshold (maxusers), turn on defensive mode.
239 */
240 for (i = 0; i < sctps->sctps_sc_cnt; i++)
241 tot_assoc += sctps->sctps_sc[i]->sctp_sc_assoc_cnt;
242 if (tot_assoc < maxusers) {
243 netstack_rele(ns);
244 continue;
245 }
246
247 mutex_enter(&sctps->sctps_reclaim_lock);
248 if (!sctps->sctps_reclaim) {
249 sctps->sctps_reclaim = B_TRUE;
250 sctps->sctps_reclaim_tid = timeout(sctp_reclaim_timer,
251 sctps, MSEC_TO_TICK(sctps->sctps_reclaim_period));
252 SCTP_KSTAT(sctps, sctp_reclaim_cnt);
253 }
254 mutex_exit(&sctps->sctps_reclaim_lock);
255 netstack_rele(ns);
256 }
257 netstack_next_fini(&nh);
258 }
259
260 /*
261 * When a CPU is added, we need to allocate the per CPU stats struct.
262 */
263 void
264 sctp_stack_cpu_add(sctp_stack_t *sctps, processorid_t cpu_seqid)
265 {
266 int i;
267
268 if (cpu_seqid < sctps->sctps_sc_cnt)
269 return;
270 for (i = sctps->sctps_sc_cnt; i <= cpu_seqid; i++) {
271 ASSERT(sctps->sctps_sc[i] == NULL);
272 sctps->sctps_sc[i] = kmem_zalloc(sizeof (sctp_stats_cpu_t),
273 KM_SLEEP);
274 }
275 membar_producer();
276 sctps->sctps_sc_cnt = cpu_seqid + 1;
277 }