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.
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.
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]
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <sys/types.h>
27 #include <inet/common.h>
28 #include <inet/sctp/sctp_impl.h>
30 /* Control whether SCTP can enter defensive mode when under memory pressure. */
31 static boolean_t sctp_do_reclaim
= B_TRUE
;
33 static void sctp_reclaim_timer(void *);
35 /* Diagnostic routine used to return a string associated with the sctp state. */
37 sctp_display(sctp_t
*sctp
, char *sup_buf
)
41 static char priv_buf
[INET6_ADDRSTRLEN
* 2 + 80];
48 connp
= sctp
->sctp_connp
;
49 buf
= (sup_buf
!= NULL
) ? sup_buf
: priv_buf
;
51 switch (sctp
->sctp_state
) {
61 case SCTPS_COOKIE_WAIT
:
62 cp
= "SCTP_COOKIE_WAIT";
64 case SCTPS_COOKIE_ECHOED
:
65 cp
= "SCTP_COOKIE_ECHOED";
67 case SCTPS_ESTABLISHED
:
68 cp
= "SCTP_ESTABLISHED";
70 case SCTPS_SHUTDOWN_PENDING
:
71 cp
= "SCTP_SHUTDOWN_PENDING";
73 case SCTPS_SHUTDOWN_SENT
:
74 cp
= "SCTPS_SHUTDOWN_SENT";
76 case SCTPS_SHUTDOWN_RECEIVED
:
77 cp
= "SCTPS_SHUTDOWN_RECEIVED";
79 case SCTPS_SHUTDOWN_ACK_SENT
:
80 cp
= "SCTPS_SHUTDOWN_ACK_SENT";
83 (void) mi_sprintf(buf1
, "SCTPUnkState(%d)", sctp
->sctp_state
);
87 (void) mi_sprintf(buf
, "[%u, %u] %s",
88 ntohs(connp
->conn_lport
), ntohs(connp
->conn_fport
), cp
);
94 sctp_display_all(sctp_stack_t
*sctps
)
98 mutex_enter(&sctps
->sctps_g_lock
);
99 for (sctp_walker
= list_head(&sctps
->sctps_g_list
);
101 sctp_walker
= (sctp_t
*)list_next(&sctps
->sctps_g_list
,
103 (void) sctp_display(sctp_walker
, NULL
);
105 mutex_exit(&sctps
->sctps_g_lock
);
109 * Given a sctp_stack_t and a port (in host byte order), find a listener
110 * configuration for that port and return the ratio.
113 sctp_find_listener_conf(sctp_stack_t
*sctps
, in_port_t port
)
118 mutex_enter(&sctps
->sctps_listener_conf_lock
);
119 for (sl
= list_head(&sctps
->sctps_listener_conf
); sl
!= NULL
;
120 sl
= list_next(&sctps
->sctps_listener_conf
, sl
)) {
121 if (sl
->sl_port
== port
) {
122 ratio
= sl
->sl_ratio
;
126 mutex_exit(&sctps
->sctps_listener_conf_lock
);
131 * To remove all listener limit configuration in a sctp_stack_t.
134 sctp_listener_conf_cleanup(sctp_stack_t
*sctps
)
138 mutex_enter(&sctps
->sctps_listener_conf_lock
);
139 while ((sl
= list_head(&sctps
->sctps_listener_conf
)) != NULL
) {
140 list_remove(&sctps
->sctps_listener_conf
, sl
);
141 kmem_free(sl
, sizeof (sctp_listener_t
));
143 mutex_destroy(&sctps
->sctps_listener_conf_lock
);
144 list_destroy(&sctps
->sctps_listener_conf
);
149 * Timeout function to reset the SCTP stack variable sctps_reclaim to false.
152 sctp_reclaim_timer(void *arg
)
154 sctp_stack_t
*sctps
= (sctp_stack_t
*)arg
;
155 int64_t tot_assoc
= 0;
157 extern pgcnt_t lotsfree
, needfree
;
159 for (i
= 0; i
< sctps
->sctps_sc_cnt
; i
++)
160 tot_assoc
+= sctps
->sctps_sc
[i
]->sctp_sc_assoc_cnt
;
163 * This happens only when a stack is going away. sctps_reclaim_tid
164 * should not be reset to 0 when returning in this case.
166 mutex_enter(&sctps
->sctps_reclaim_lock
);
167 if (!sctps
->sctps_reclaim
) {
168 mutex_exit(&sctps
->sctps_reclaim_lock
);
172 if ((freemem
>= lotsfree
+ needfree
) || tot_assoc
< maxusers
) {
173 sctps
->sctps_reclaim
= B_FALSE
;
174 sctps
->sctps_reclaim_tid
= 0;
176 /* Stay in defensive mode and restart the timer */
177 sctps
->sctps_reclaim_tid
= timeout(sctp_reclaim_timer
,
178 sctps
, MSEC_TO_TICK(sctps
->sctps_reclaim_period
));
180 mutex_exit(&sctps
->sctps_reclaim_lock
);
184 * Kmem reclaim call back function. When the system is under memory
185 * pressure, we set the SCTP stack variable sctps_reclaim to true. This
186 * variable is reset to false after sctps_reclaim_period msecs. During this
187 * period, SCTP will be more aggressive in aborting connections not making
188 * progress, meaning retransmitting for shorter time (sctp_pa_early_abort/
189 * sctp_pp_early_abort number of strikes).
193 sctp_conn_reclaim(void *arg
)
195 netstack_handle_t nh
;
198 extern pgcnt_t lotsfree
, needfree
;
200 if (!sctp_do_reclaim
)
204 * The reclaim function may be called even when the system is not
205 * really under memory pressure.
207 if (freemem
>= lotsfree
+ needfree
)
210 netstack_next_init(&nh
);
211 while ((ns
= netstack_next(&nh
)) != NULL
) {
213 int64_t tot_assoc
= 0;
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
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.
229 if ((sctps
= ns
->netstack_sctp
) == NULL
) {
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.
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
) {
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
);
254 mutex_exit(&sctps
->sctps_reclaim_lock
);
257 netstack_next_fini(&nh
);
261 * When a CPU is added, we need to allocate the per CPU stats struct.
264 sctp_stack_cpu_add(sctp_stack_t
*sctps
, processorid_t cpu_seqid
)
268 if (cpu_seqid
< sctps
->sctps_sc_cnt
)
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
),
276 sctps
->sctps_sc_cnt
= cpu_seqid
+ 1;