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