#include <sys/types.h>
#include <inet/common.h>
#include "sctp_impl.h"
static boolean_t sctp_do_reclaim = B_TRUE;
static void sctp_reclaim_timer(void *);
char *
sctp_display(sctp_t *sctp, char *sup_buf)
{
char *buf;
char buf1[30];
static char priv_buf[INET6_ADDRSTRLEN * 2 + 80];
char *cp;
conn_t *connp;
if (sctp == NULL)
return ("NULL_SCTP");
connp = sctp->sctp_connp;
buf = (sup_buf != NULL) ? sup_buf : priv_buf;
switch (sctp->sctp_state) {
case SCTPS_IDLE:
cp = "SCTP_IDLE";
break;
case SCTPS_BOUND:
cp = "SCTP_BOUND";
break;
case SCTPS_LISTEN:
cp = "SCTP_LISTEN";
break;
case SCTPS_COOKIE_WAIT:
cp = "SCTP_COOKIE_WAIT";
break;
case SCTPS_COOKIE_ECHOED:
cp = "SCTP_COOKIE_ECHOED";
break;
case SCTPS_ESTABLISHED:
cp = "SCTP_ESTABLISHED";
break;
case SCTPS_SHUTDOWN_PENDING:
cp = "SCTP_SHUTDOWN_PENDING";
break;
case SCTPS_SHUTDOWN_SENT:
cp = "SCTPS_SHUTDOWN_SENT";
break;
case SCTPS_SHUTDOWN_RECEIVED:
cp = "SCTPS_SHUTDOWN_RECEIVED";
break;
case SCTPS_SHUTDOWN_ACK_SENT:
cp = "SCTPS_SHUTDOWN_ACK_SENT";
break;
default:
(void) mi_sprintf(buf1, "SCTPUnkState(%d)", sctp->sctp_state);
cp = buf1;
break;
}
(void) mi_sprintf(buf, "[%u, %u] %s",
ntohs(connp->conn_lport), ntohs(connp->conn_fport), cp);
return (buf);
}
void
sctp_display_all(sctp_stack_t *sctps)
{
sctp_t *sctp_walker;
mutex_enter(&sctps->sctps_g_lock);
for (sctp_walker = list_head(&sctps->sctps_g_list);
sctp_walker != NULL;
sctp_walker = (sctp_t *)list_next(&sctps->sctps_g_list,
sctp_walker)) {
(void) sctp_display(sctp_walker, NULL);
}
mutex_exit(&sctps->sctps_g_lock);
}
uint32_t
sctp_find_listener_conf(sctp_stack_t *sctps, in_port_t port)
{
sctp_listener_t *sl;
uint32_t ratio = 0;
mutex_enter(&sctps->sctps_listener_conf_lock);
for (sl = list_head(&sctps->sctps_listener_conf); sl != NULL;
sl = list_next(&sctps->sctps_listener_conf, sl)) {
if (sl->sl_port == port) {
ratio = sl->sl_ratio;
break;
}
}
mutex_exit(&sctps->sctps_listener_conf_lock);
return (ratio);
}
void
sctp_listener_conf_cleanup(sctp_stack_t *sctps)
{
sctp_listener_t *sl;
mutex_enter(&sctps->sctps_listener_conf_lock);
while ((sl = list_head(&sctps->sctps_listener_conf)) != NULL) {
list_remove(&sctps->sctps_listener_conf, sl);
kmem_free(sl, sizeof (sctp_listener_t));
}
mutex_destroy(&sctps->sctps_listener_conf_lock);
list_destroy(&sctps->sctps_listener_conf);
}
static void
sctp_reclaim_timer(void *arg)
{
sctp_stack_t *sctps = (sctp_stack_t *)arg;
int64_t tot_assoc = 0;
int i;
extern pgcnt_t lotsfree, needfree;
for (i = 0; i < sctps->sctps_sc_cnt; i++)
tot_assoc += sctps->sctps_sc[i]->sctp_sc_assoc_cnt;
mutex_enter(&sctps->sctps_reclaim_lock);
if (!sctps->sctps_reclaim) {
mutex_exit(&sctps->sctps_reclaim_lock);
return;
}
if ((freemem >= lotsfree + needfree) || tot_assoc < maxusers) {
sctps->sctps_reclaim = B_FALSE;
sctps->sctps_reclaim_tid = 0;
} else {
sctps->sctps_reclaim_tid = timeout(sctp_reclaim_timer,
sctps, MSEC_TO_TICK(sctps->sctps_reclaim_period));
}
mutex_exit(&sctps->sctps_reclaim_lock);
}
void
sctp_conn_reclaim(void *arg)
{
netstack_handle_t nh;
netstack_t *ns;
sctp_stack_t *sctps;
extern pgcnt_t lotsfree, needfree;
if (!sctp_do_reclaim)
return;
if (freemem >= lotsfree + needfree)
return;
netstack_next_init(&nh);
while ((ns = netstack_next(&nh)) != NULL) {
int i;
int64_t tot_assoc = 0;
if ((sctps = ns->netstack_sctp) == NULL) {
netstack_rele(ns);
continue;
}
for (i = 0; i < sctps->sctps_sc_cnt; i++)
tot_assoc += sctps->sctps_sc[i]->sctp_sc_assoc_cnt;
if (tot_assoc < maxusers) {
netstack_rele(ns);
continue;
}
mutex_enter(&sctps->sctps_reclaim_lock);
if (!sctps->sctps_reclaim) {
sctps->sctps_reclaim = B_TRUE;
sctps->sctps_reclaim_tid = timeout(sctp_reclaim_timer,
sctps, MSEC_TO_TICK(sctps->sctps_reclaim_period));
SCTP_KSTAT(sctps, sctp_reclaim_cnt);
}
mutex_exit(&sctps->sctps_reclaim_lock);
netstack_rele(ns);
}
netstack_next_fini(&nh);
}
void
sctp_stack_cpu_add(sctp_stack_t *sctps, processorid_t cpu_seqid)
{
int i;
if (cpu_seqid < sctps->sctps_sc_cnt)
return;
for (i = sctps->sctps_sc_cnt; i <= cpu_seqid; i++) {
ASSERT(sctps->sctps_sc[i] == NULL);
sctps->sctps_sc[i] = kmem_zalloc(sizeof (sctp_stats_cpu_t),
KM_SLEEP);
}
membar_producer();
sctps->sctps_sc_cnt = cpu_seqid + 1;
}