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 */
25
26 #include <sys/types.h>
27 #include <sys/strlog.h>
28 #include <sys/policy.h>
29 #include <sys/strsun.h>
30 #include <sys/squeue_impl.h>
31 #include <sys/squeue.h>
32
33 #include <inet/common.h>
34 #include <inet/ip.h>
35 #include <inet/tcp.h>
36 #include <inet/tcp_impl.h>
37
38 /* Control whether TCP can enter defensive mode when under memory pressure. */
39 static boolean_t tcp_do_reclaim = B_TRUE;
40
41 /*
42 * Routines related to the TCP_IOC_ABORT_CONN ioctl command.
43 *
44 * TCP_IOC_ABORT_CONN is a non-transparent ioctl command used for aborting
45 * TCP connections. To invoke this ioctl, a tcp_ioc_abort_conn_t structure
46 * (defined in tcp.h) needs to be filled in and passed into the kernel
47 * via an I_STR ioctl command (see streamio(7I)). The tcp_ioc_abort_conn_t
48 * structure contains the four-tuple of a TCP connection and a range of TCP
49 * states (specified by ac_start and ac_end). The use of wildcard addresses
50 * and ports is allowed. Connections with a matching four tuple and a state
51 * within the specified range will be aborted. The valid states for the
487 if (mp1 != NULL) {
488 freemsg(mp1);
489 mp->b_cont = NULL;
490 }
491
492 if (err != 0)
493 miocnak(q, mp, 0, err);
494 else
495 miocack(q, mp, 0, 0);
496 }
497
498 /*
499 * Timeout function to reset the TCP stack variable tcps_reclaim to false.
500 */
501 void
502 tcp_reclaim_timer(void *arg)
503 {
504 tcp_stack_t *tcps = (tcp_stack_t *)arg;
505 int64_t tot_conn = 0;
506 int i;
507 extern pgcnt_t lotsfree, needfree;
508
509 for (i = 0; i < tcps->tcps_sc_cnt; i++)
510 tot_conn += tcps->tcps_sc[i]->tcp_sc_conn_cnt;
511
512 /*
513 * This happens only when a stack is going away. tcps_reclaim_tid
514 * should not be reset to 0 when returning in this case.
515 */
516 mutex_enter(&tcps->tcps_reclaim_lock);
517 if (!tcps->tcps_reclaim) {
518 mutex_exit(&tcps->tcps_reclaim_lock);
519 return;
520 }
521
522 if ((freemem >= lotsfree + needfree) || tot_conn < maxusers) {
523 tcps->tcps_reclaim = B_FALSE;
524 tcps->tcps_reclaim_tid = 0;
525 } else {
526 /* Stay in defensive mode and restart the timer */
527 tcps->tcps_reclaim_tid = timeout(tcp_reclaim_timer,
529 }
530 mutex_exit(&tcps->tcps_reclaim_lock);
531 }
532
533 /*
534 * Kmem reclaim call back function. When the system is under memory
535 * pressure, we set the TCP stack variable tcps_reclaim to true. This
536 * variable is reset to false after tcps_reclaim_period msecs. During this
537 * period, TCP will be more aggressive in aborting connections not making
538 * progress, meaning retransmitting for some time (tcp_early_abort seconds).
539 * TCP will also not accept new connection request for those listeners whose
540 * q or q0 is not empty.
541 */
542 /* ARGSUSED */
543 void
544 tcp_conn_reclaim(void *arg)
545 {
546 netstack_handle_t nh;
547 netstack_t *ns;
548 tcp_stack_t *tcps;
549 extern pgcnt_t lotsfree, needfree;
550
551 if (!tcp_do_reclaim)
552 return;
553
554 /*
555 * The reclaim function may be called even when the system is not
556 * really under memory pressure.
557 */
558 if (freemem >= lotsfree + needfree)
559 return;
560
561 netstack_next_init(&nh);
562 while ((ns = netstack_next(&nh)) != NULL) {
563 int i;
564 int64_t tot_conn = 0;
565
566 /*
567 * During boot time, the first netstack_t is created and
568 * initialized before TCP has registered with the netstack
569 * framework. If this reclaim function is called before TCP
|
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/strlog.h>
29 #include <sys/policy.h>
30 #include <sys/strsun.h>
31 #include <sys/squeue_impl.h>
32 #include <sys/squeue.h>
33 #include <sys/vmsystm.h>
34
35 #include <inet/common.h>
36 #include <inet/ip.h>
37 #include <inet/tcp.h>
38 #include <inet/tcp_impl.h>
39
40 /* Control whether TCP can enter defensive mode when under memory pressure. */
41 static boolean_t tcp_do_reclaim = B_TRUE;
42
43 /*
44 * Routines related to the TCP_IOC_ABORT_CONN ioctl command.
45 *
46 * TCP_IOC_ABORT_CONN is a non-transparent ioctl command used for aborting
47 * TCP connections. To invoke this ioctl, a tcp_ioc_abort_conn_t structure
48 * (defined in tcp.h) needs to be filled in and passed into the kernel
49 * via an I_STR ioctl command (see streamio(7I)). The tcp_ioc_abort_conn_t
50 * structure contains the four-tuple of a TCP connection and a range of TCP
51 * states (specified by ac_start and ac_end). The use of wildcard addresses
52 * and ports is allowed. Connections with a matching four tuple and a state
53 * within the specified range will be aborted. The valid states for the
489 if (mp1 != NULL) {
490 freemsg(mp1);
491 mp->b_cont = NULL;
492 }
493
494 if (err != 0)
495 miocnak(q, mp, 0, err);
496 else
497 miocack(q, mp, 0, 0);
498 }
499
500 /*
501 * Timeout function to reset the TCP stack variable tcps_reclaim to false.
502 */
503 void
504 tcp_reclaim_timer(void *arg)
505 {
506 tcp_stack_t *tcps = (tcp_stack_t *)arg;
507 int64_t tot_conn = 0;
508 int i;
509
510 for (i = 0; i < tcps->tcps_sc_cnt; i++)
511 tot_conn += tcps->tcps_sc[i]->tcp_sc_conn_cnt;
512
513 /*
514 * This happens only when a stack is going away. tcps_reclaim_tid
515 * should not be reset to 0 when returning in this case.
516 */
517 mutex_enter(&tcps->tcps_reclaim_lock);
518 if (!tcps->tcps_reclaim) {
519 mutex_exit(&tcps->tcps_reclaim_lock);
520 return;
521 }
522
523 if ((freemem >= lotsfree + needfree) || tot_conn < maxusers) {
524 tcps->tcps_reclaim = B_FALSE;
525 tcps->tcps_reclaim_tid = 0;
526 } else {
527 /* Stay in defensive mode and restart the timer */
528 tcps->tcps_reclaim_tid = timeout(tcp_reclaim_timer,
530 }
531 mutex_exit(&tcps->tcps_reclaim_lock);
532 }
533
534 /*
535 * Kmem reclaim call back function. When the system is under memory
536 * pressure, we set the TCP stack variable tcps_reclaim to true. This
537 * variable is reset to false after tcps_reclaim_period msecs. During this
538 * period, TCP will be more aggressive in aborting connections not making
539 * progress, meaning retransmitting for some time (tcp_early_abort seconds).
540 * TCP will also not accept new connection request for those listeners whose
541 * q or q0 is not empty.
542 */
543 /* ARGSUSED */
544 void
545 tcp_conn_reclaim(void *arg)
546 {
547 netstack_handle_t nh;
548 netstack_t *ns;
549 tcp_stack_t *tcps;
550
551 if (!tcp_do_reclaim)
552 return;
553
554 /*
555 * The reclaim function may be called even when the system is not
556 * really under memory pressure.
557 */
558 if (freemem >= lotsfree + needfree)
559 return;
560
561 netstack_next_init(&nh);
562 while ((ns = netstack_next(&nh)) != NULL) {
563 int i;
564 int64_t tot_conn = 0;
565
566 /*
567 * During boot time, the first netstack_t is created and
568 * initialized before TCP has registered with the netstack
569 * framework. If this reclaim function is called before TCP
|