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 */ 25 26 #ifndef _INET_TCP_STATS_H 27 #define _INET_TCP_STATS_H 28 29 /* 30 * TCP private kernel statistics declarations. 31 */ 32 33 #ifdef __cplusplus 34 extern "C" { 35 #endif 36 37 #ifdef _KERNEL 38 39 /* 40 * TCP Statistics. 41 * 42 * How TCP statistics work. 43 * 44 * There are two types of statistics invoked by two macros. 45 * 46 * TCP_STAT(name) does non-atomic increment of a named stat counter. It is 47 * supposed to be used in non MT-hot paths of the code. 48 * 49 * TCP_DBGSTAT(name) does atomic increment of a named stat counter. It is 50 * supposed to be used for DEBUG purposes and may be used on a hot path. 51 * These counters are only available in a debugged kernel. They are grouped 52 * under the TCP_DEBUG_COUNTER C pre-processor condition. 53 * 54 * Both TCP_STAT and TCP_DBGSTAT counters are available using kstat 55 * (use "kstat tcp" to get them). 56 * 57 * How to add new counters. 58 * 59 * 1) Add a field in the tcp_stat structure describing your counter. 60 * 2) Add a line in the template in tcp_kstat2_init() with the name 61 * of the counter. 62 * 3) Update tcp_clr_stats() and tcp_cp_stats() with the new counters. 63 * IMPORTANT!! - make sure that all the above functions are in sync !! 64 * 4) Use either TCP_STAT or TCP_DBGSTAT with the name. 65 * 66 * Please avoid using private counters which are not kstat-exported. 67 * 68 * Implementation note. 69 * 70 * Both the MIB2 and tcp_stat_t counters are kept per CPU in the array 71 * tcps_sc in tcp_stack_t. Each array element is a pointer to a 72 * tcp_stats_cpu_t struct. Once allocated, the tcp_stats_cpu_t struct is 73 * not freed until the tcp_stack_t is going away. So there is no need to 74 * acquire a lock before accessing the stats counters. 75 */ 76 77 #ifndef TCP_DEBUG_COUNTER 78 #ifdef DEBUG 79 #define TCP_DEBUG_COUNTER 1 80 #else 81 #define TCP_DEBUG_COUNTER 0 82 #endif 83 #endif 84 85 /* Kstats */ 86 typedef struct tcp_stat { 87 kstat_named_t tcp_time_wait_syn_success; 88 kstat_named_t tcp_clean_death_nondetached; 89 kstat_named_t tcp_eager_blowoff_q; 90 kstat_named_t tcp_eager_blowoff_q0; 91 kstat_named_t tcp_no_listener; 92 kstat_named_t tcp_listendrop; 93 kstat_named_t tcp_listendropq0; 94 kstat_named_t tcp_wsrv_called; 95 kstat_named_t tcp_flwctl_on; 96 kstat_named_t tcp_timer_fire_early; 97 kstat_named_t tcp_timer_fire_miss; 98 kstat_named_t tcp_zcopy_on; 99 kstat_named_t tcp_zcopy_off; 100 kstat_named_t tcp_zcopy_backoff; 101 kstat_named_t tcp_fusion_flowctl; 102 kstat_named_t tcp_fusion_backenabled; 103 kstat_named_t tcp_fusion_urg; 104 kstat_named_t tcp_fusion_putnext; 105 kstat_named_t tcp_fusion_unfusable; 106 kstat_named_t tcp_fusion_aborted; 107 kstat_named_t tcp_fusion_unqualified; 108 kstat_named_t tcp_fusion_rrw_busy; 109 kstat_named_t tcp_fusion_rrw_msgcnt; 110 kstat_named_t tcp_fusion_rrw_plugged; 111 kstat_named_t tcp_in_ack_unsent_drop; 112 kstat_named_t tcp_sock_fallback; 113 kstat_named_t tcp_lso_enabled; 114 kstat_named_t tcp_lso_disabled; 115 kstat_named_t tcp_lso_times; 116 kstat_named_t tcp_lso_pkt_out; 117 kstat_named_t tcp_listen_cnt_drop; 118 kstat_named_t tcp_listen_mem_drop; 119 kstat_named_t tcp_zwin_mem_drop; 120 kstat_named_t tcp_zwin_ack_syn; 121 kstat_named_t tcp_rst_unsent; 122 kstat_named_t tcp_reclaim_cnt; 123 kstat_named_t tcp_reass_timeout; 124 #ifdef TCP_DEBUG_COUNTER 125 kstat_named_t tcp_time_wait; 126 kstat_named_t tcp_rput_time_wait; 127 kstat_named_t tcp_detach_time_wait; 128 kstat_named_t tcp_timeout_calls; 129 kstat_named_t tcp_timeout_cached_alloc; 130 kstat_named_t tcp_timeout_cancel_reqs; 131 kstat_named_t tcp_timeout_canceled; 132 kstat_named_t tcp_timermp_freed; 133 kstat_named_t tcp_push_timer_cnt; 134 kstat_named_t tcp_ack_timer_cnt; 135 #endif 136 } tcp_stat_t; 137 138 /* 139 * This struct contains only the counter part of tcp_stat_t. It is used 140 * in tcp_stats_cpu_t instead of tcp_stat_t to save memory space. 141 */ 142 typedef struct tcp_stat_counter_s { 143 uint64_t tcp_time_wait_syn_success; 144 uint64_t tcp_clean_death_nondetached; 145 uint64_t tcp_eager_blowoff_q; 146 uint64_t tcp_eager_blowoff_q0; 147 uint64_t tcp_no_listener; 148 uint64_t tcp_listendrop; 149 uint64_t tcp_listendropq0; 150 uint64_t tcp_wsrv_called; 151 uint64_t tcp_flwctl_on; 152 uint64_t tcp_timer_fire_early; 153 uint64_t tcp_timer_fire_miss; 154 uint64_t tcp_zcopy_on; 155 uint64_t tcp_zcopy_off; 156 uint64_t tcp_zcopy_backoff; 157 uint64_t tcp_fusion_flowctl; 158 uint64_t tcp_fusion_backenabled; 159 uint64_t tcp_fusion_urg; 160 uint64_t tcp_fusion_putnext; 161 uint64_t tcp_fusion_unfusable; 162 uint64_t tcp_fusion_aborted; 163 uint64_t tcp_fusion_unqualified; 164 uint64_t tcp_fusion_rrw_busy; 165 uint64_t tcp_fusion_rrw_msgcnt; 166 uint64_t tcp_fusion_rrw_plugged; 167 uint64_t tcp_in_ack_unsent_drop; 168 uint64_t tcp_sock_fallback; 169 uint64_t tcp_lso_enabled; 170 uint64_t tcp_lso_disabled; 171 uint64_t tcp_lso_times; 172 uint64_t tcp_lso_pkt_out; 173 uint64_t tcp_listen_cnt_drop; 174 uint64_t tcp_listen_mem_drop; 175 uint64_t tcp_zwin_mem_drop; 176 uint64_t tcp_zwin_ack_syn; 177 uint64_t tcp_rst_unsent; 178 uint64_t tcp_reclaim_cnt; 179 uint64_t tcp_reass_timeout; 180 #ifdef TCP_DEBUG_COUNTER 181 uint64_t tcp_time_wait; 182 uint64_t tcp_rput_time_wait; 183 uint64_t tcp_detach_time_wait; 184 uint64_t tcp_timeout_calls; 185 uint64_t tcp_timeout_cached_alloc; 186 uint64_t tcp_timeout_cancel_reqs; 187 uint64_t tcp_timeout_canceled; 188 uint64_t tcp_timermp_freed; 189 uint64_t tcp_push_timer_cnt; 190 uint64_t tcp_ack_timer_cnt; 191 #endif 192 } tcp_stat_counter_t; 193 194 typedef struct tcp_g_stat { 195 kstat_named_t tcp_timermp_alloced; 196 kstat_named_t tcp_timermp_allocfail; 197 kstat_named_t tcp_timermp_allocdblfail; 198 kstat_named_t tcp_freelist_cleanup; 199 } tcp_g_stat_t; 200 201 /* Per CPU stats: TCP MIB2, TCP kstat and connection counter. */ 202 typedef struct { 203 int64_t tcp_sc_conn_cnt; 204 mib2_tcp_t tcp_sc_mib; 205 tcp_stat_counter_t tcp_sc_stats; 206 } tcp_stats_cpu_t; 207 208 #define TCPS_BUMP_MIB(tcps, x) \ 209 BUMP_MIB(&(tcps)->tcps_sc[CPU->cpu_seqid]->tcp_sc_mib, x) 210 211 #define TCPS_UPDATE_MIB(tcps, x, y) \ 212 UPDATE_MIB(&(tcps)->tcps_sc[CPU->cpu_seqid]->tcp_sc_mib, x, y) 213 214 #if TCP_DEBUG_COUNTER 215 #define TCP_DBGSTAT(tcps, x) \ 216 atomic_inc_64( \ 217 &((tcps)->tcps_sc[CPU->cpu_seqid]->tcp_sc_stats.x)) 218 #define TCP_G_DBGSTAT(x) \ 219 atomic_inc_64(&(tcp_g_statistics.x.value.ui64)) 220 #else 221 #define TCP_DBGSTAT(tcps, x) 222 #define TCP_G_DBGSTAT(x) 223 #endif 224 225 #define TCP_G_STAT(x) (tcp_g_statistics.x.value.ui64++) 226 227 #define TCP_STAT(tcps, x) \ 228 ((tcps)->tcps_sc[CPU->cpu_seqid]->tcp_sc_stats.x++) 229 #define TCP_STAT_UPDATE(tcps, x, n) \ 230 ((tcps)->tcps_sc[CPU->cpu_seqid]->tcp_sc_stats.x += (n)) 231 #define TCP_STAT_SET(tcps, x, n) \ 232 ((tcps)->tcps_sc[CPU->cpu_seqid]->tcp_sc_stats.x = (n)) 233 234 /* Global TCP stats for all IP stacks. */ 235 extern tcp_g_stat_t tcp_g_statistics; 236 extern kstat_t *tcp_g_kstat; 237 238 extern void *tcp_g_kstat_init(tcp_g_stat_t *); 239 extern void tcp_g_kstat_fini(kstat_t *); 240 extern void *tcp_kstat_init(netstackid_t); 241 extern void tcp_kstat_fini(netstackid_t, kstat_t *); 242 extern void *tcp_kstat2_init(netstackid_t); 243 extern void tcp_kstat2_fini(netstackid_t, kstat_t *); 244 245 #endif /* _KERNEL */ 246 247 #ifdef __cplusplus 248 } 249 #endif 250 251 #endif /* _INET_TCP_STATS_H */