5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon/*
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * CDDL HEADER START
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon *
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * The contents of this file are subject to the terms of the
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * Common Development and Distribution License (the "License").
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * You may not use this file except in compliance with the License.
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon *
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * or http://www.opensolaris.org/os/licensing.
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * See the License for the specific language governing permissions
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * and limitations under the License.
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon *
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * When distributing Covered Code, include this CDDL HEADER in each
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * If applicable, add the following below this CDDL HEADER, with the
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * fields enclosed by brackets "[]" replaced with your own identifying
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * information: Portions Copyright [yyyy] [name of copyright owner]
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon *
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * CDDL HEADER END
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon */
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon/*
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon */
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon#include <sys/types.h>
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon#include <inet/common.h>
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon#include "sctp_impl.h"
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon/* Control whether SCTP can enter defensive mode when under memory pressure. */
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poonstatic boolean_t sctp_do_reclaim = B_TRUE;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poonstatic void sctp_reclaim_timer(void *);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon/* Diagnostic routine used to return a string associated with the sctp state. */
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poonchar *
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poonsctp_display(sctp_t *sctp, char *sup_buf)
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon{
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon char *buf;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon char buf1[30];
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon static char priv_buf[INET6_ADDRSTRLEN * 2 + 80];
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon char *cp;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon conn_t *connp;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon if (sctp == NULL)
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon return ("NULL_SCTP");
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon connp = sctp->sctp_connp;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon buf = (sup_buf != NULL) ? sup_buf : priv_buf;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon switch (sctp->sctp_state) {
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon case SCTPS_IDLE:
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon cp = "SCTP_IDLE";
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon break;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon case SCTPS_BOUND:
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon cp = "SCTP_BOUND";
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon break;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon case SCTPS_LISTEN:
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon cp = "SCTP_LISTEN";
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon break;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon case SCTPS_COOKIE_WAIT:
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon cp = "SCTP_COOKIE_WAIT";
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon break;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon case SCTPS_COOKIE_ECHOED:
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon cp = "SCTP_COOKIE_ECHOED";
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon break;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon case SCTPS_ESTABLISHED:
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon cp = "SCTP_ESTABLISHED";
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon break;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon case SCTPS_SHUTDOWN_PENDING:
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon cp = "SCTP_SHUTDOWN_PENDING";
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon break;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon case SCTPS_SHUTDOWN_SENT:
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon cp = "SCTPS_SHUTDOWN_SENT";
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon break;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon case SCTPS_SHUTDOWN_RECEIVED:
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon cp = "SCTPS_SHUTDOWN_RECEIVED";
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon break;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon case SCTPS_SHUTDOWN_ACK_SENT:
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon cp = "SCTPS_SHUTDOWN_ACK_SENT";
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon break;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon default:
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon (void) mi_sprintf(buf1, "SCTPUnkState(%d)", sctp->sctp_state);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon cp = buf1;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon break;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon }
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon (void) mi_sprintf(buf, "[%u, %u] %s",
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon ntohs(connp->conn_lport), ntohs(connp->conn_fport), cp);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon return (buf);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon}
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poonvoid
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poonsctp_display_all(sctp_stack_t *sctps)
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon{
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon sctp_t *sctp_walker;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon mutex_enter(&sctps->sctps_g_lock);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon for (sctp_walker = list_head(&sctps->sctps_g_list);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon sctp_walker != NULL;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon sctp_walker = (sctp_t *)list_next(&sctps->sctps_g_list,
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon sctp_walker)) {
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon (void) sctp_display(sctp_walker, NULL);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon }
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon mutex_exit(&sctps->sctps_g_lock);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon}
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon/*
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * Given a sctp_stack_t and a port (in host byte order), find a listener
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * configuration for that port and return the ratio.
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon */
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poonuint32_t
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poonsctp_find_listener_conf(sctp_stack_t *sctps, in_port_t port)
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon{
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon sctp_listener_t *sl;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon uint32_t ratio = 0;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon mutex_enter(&sctps->sctps_listener_conf_lock);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon for (sl = list_head(&sctps->sctps_listener_conf); sl != NULL;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon sl = list_next(&sctps->sctps_listener_conf, sl)) {
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon if (sl->sl_port == port) {
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon ratio = sl->sl_ratio;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon break;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon }
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon }
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon mutex_exit(&sctps->sctps_listener_conf_lock);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon return (ratio);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon}
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon/*
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * To remove all listener limit configuration in a sctp_stack_t.
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon */
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poonvoid
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poonsctp_listener_conf_cleanup(sctp_stack_t *sctps)
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon{
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon sctp_listener_t *sl;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon mutex_enter(&sctps->sctps_listener_conf_lock);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon while ((sl = list_head(&sctps->sctps_listener_conf)) != NULL) {
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon list_remove(&sctps->sctps_listener_conf, sl);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon kmem_free(sl, sizeof (sctp_listener_t));
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon }
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon mutex_destroy(&sctps->sctps_listener_conf_lock);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon list_destroy(&sctps->sctps_listener_conf);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon}
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon/*
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * Timeout function to reset the SCTP stack variable sctps_reclaim to false.
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon */
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poonstatic void
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poonsctp_reclaim_timer(void *arg)
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon{
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon sctp_stack_t *sctps = (sctp_stack_t *)arg;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon int64_t tot_assoc = 0;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon int i;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon extern pgcnt_t lotsfree, needfree;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon for (i = 0; i < sctps->sctps_sc_cnt; i++)
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon tot_assoc += sctps->sctps_sc[i]->sctp_sc_assoc_cnt;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon /*
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * This happens only when a stack is going away. sctps_reclaim_tid
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * should not be reset to 0 when returning in this case.
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon */
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon mutex_enter(&sctps->sctps_reclaim_lock);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon if (!sctps->sctps_reclaim) {
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon mutex_exit(&sctps->sctps_reclaim_lock);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon return;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon }
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon if ((freemem >= lotsfree + needfree) || tot_assoc < maxusers) {
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon sctps->sctps_reclaim = B_FALSE;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon sctps->sctps_reclaim_tid = 0;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon } else {
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon /* Stay in defensive mode and restart the timer */
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon sctps->sctps_reclaim_tid = timeout(sctp_reclaim_timer,
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon sctps, MSEC_TO_TICK(sctps->sctps_reclaim_period));
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon }
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon mutex_exit(&sctps->sctps_reclaim_lock);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon}
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon/*
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * Kmem reclaim call back function. When the system is under memory
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * pressure, we set the SCTP stack variable sctps_reclaim to true. This
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * variable is reset to false after sctps_reclaim_period msecs. During this
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * period, SCTP will be more aggressive in aborting connections not making
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * progress, meaning retransmitting for shorter time (sctp_pa_early_abort/
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * sctp_pp_early_abort number of strikes).
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon */
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon/* ARGSUSED */
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poonvoid
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poonsctp_conn_reclaim(void *arg)
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon{
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon netstack_handle_t nh;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon netstack_t *ns;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon sctp_stack_t *sctps;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon extern pgcnt_t lotsfree, needfree;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon if (!sctp_do_reclaim)
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon return;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon /*
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * The reclaim function may be called even when the system is not
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * really under memory pressure.
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon */
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon if (freemem >= lotsfree + needfree)
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon return;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon netstack_next_init(&nh);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon while ((ns = netstack_next(&nh)) != NULL) {
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon int i;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon int64_t tot_assoc = 0;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon /*
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * During boot time, the first netstack_t is created and
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * initialized before SCTP has registered with the netstack
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * framework. If this reclaim function is called before SCTP
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * has finished its initialization, netstack_next() will
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * return the first netstack_t (since its netstack_flags is
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * not NSF_UNINIT). And its netstack_sctp will be NULL. We
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * need to catch it.
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon *
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * All subsequent netstack_t creation will not have this
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * problem since the initialization is not finished until SCTP
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * has finished its own sctp_stack_t initialization. Hence
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * netstack_next() will not return one with NULL netstack_sctp.
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon */
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon if ((sctps = ns->netstack_sctp) == NULL) {
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon netstack_rele(ns);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon continue;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon }
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon /*
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * Even if the system is under memory pressure, the reason may
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * not be because of SCTP activity. Check the number of
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * associations in each stack. If the number exceeds the
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * threshold (maxusers), turn on defensive mode.
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon */
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon for (i = 0; i < sctps->sctps_sc_cnt; i++)
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon tot_assoc += sctps->sctps_sc[i]->sctp_sc_assoc_cnt;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon if (tot_assoc < maxusers) {
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon netstack_rele(ns);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon continue;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon }
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon mutex_enter(&sctps->sctps_reclaim_lock);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon if (!sctps->sctps_reclaim) {
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon sctps->sctps_reclaim = B_TRUE;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon sctps->sctps_reclaim_tid = timeout(sctp_reclaim_timer,
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon sctps, MSEC_TO_TICK(sctps->sctps_reclaim_period));
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon SCTP_KSTAT(sctps, sctp_reclaim_cnt);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon }
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon mutex_exit(&sctps->sctps_reclaim_lock);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon netstack_rele(ns);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon }
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon netstack_next_fini(&nh);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon}
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon/*
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon * When a CPU is added, we need to allocate the per CPU stats struct.
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon */
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poonvoid
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poonsctp_stack_cpu_add(sctp_stack_t *sctps, processorid_t cpu_seqid)
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon{
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon int i;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon if (cpu_seqid < sctps->sctps_sc_cnt)
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon return;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon for (i = sctps->sctps_sc_cnt; i <= cpu_seqid; i++) {
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon ASSERT(sctps->sctps_sc[i] == NULL);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon sctps->sctps_sc[i] = kmem_zalloc(sizeof (sctp_stats_cpu_t),
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon KM_SLEEP);
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon }
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon membar_producer();
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon sctps->sctps_sc_cnt = cpu_seqid + 1;
5dd46ab5742d7db1cbb08dec7b64fa14930c02f7Kacheong Poon}