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