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