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) 2011, Joyent Inc. All rights reserved.
25 */
26
27 #include <sys/types.h>
28 #include <sys/tihdr.h>
29 #include <sys/policy.h>
30 #include <sys/tsol/tnet.h>
31 #include <sys/kstat.h>
32
33 #include <inet/common.h>
34 #include <inet/ip.h>
35 #include <inet/tcp.h>
36 #include <inet/tcp_impl.h>
37 #include <inet/tcp_stats.h>
38 #include <inet/kstatcom.h>
39 #include <inet/snmpcom.h>
40
41 static int tcp_kstat_update(kstat_t *, int);
42 static int tcp_kstat2_update(kstat_t *, int);
43 static void tcp_sum_mib(tcp_stack_t *, mib2_tcp_t *);
44
69 return (MIB2_TCP_synReceived);
70 case TCPS_ESTABLISHED:
71 return (MIB2_TCP_established);
72 case TCPS_CLOSE_WAIT:
73 return (MIB2_TCP_closeWait);
74 case TCPS_FIN_WAIT_1:
75 return (MIB2_TCP_finWait1);
76 case TCPS_CLOSING:
77 return (MIB2_TCP_closing);
78 case TCPS_LAST_ACK:
79 return (MIB2_TCP_lastAck);
80 case TCPS_FIN_WAIT_2:
81 return (MIB2_TCP_finWait2);
82 case TCPS_TIME_WAIT:
83 return (MIB2_TCP_timeWait);
84 default:
85 return (0);
86 }
87 }
88
89 /*
90 * Return SNMP stuff in buffer in mpdata.
91 */
92 mblk_t *
93 tcp_snmp_get(queue_t *q, mblk_t *mpctl, boolean_t legacy_req)
94 {
95 mblk_t *mpdata;
96 mblk_t *mp_conn_ctl = NULL;
97 mblk_t *mp_conn_tail;
98 mblk_t *mp_attr_ctl = NULL;
99 mblk_t *mp_attr_tail;
100 mblk_t *mp6_conn_ctl = NULL;
101 mblk_t *mp6_conn_tail;
102 mblk_t *mp6_attr_ctl = NULL;
103 mblk_t *mp6_attr_tail;
104 struct opthdr *optp;
105 mib2_tcpConnEntry_t tce;
106 mib2_tcp6ConnEntry_t tce6;
107 mib2_transportMLPEntry_t mlp;
108 connf_t *connfp;
166
167 v4_conn_idx = v6_conn_idx = 0;
168 mp_conn_tail = mp_attr_tail = mp6_conn_tail = mp6_attr_tail = NULL;
169
170 for (i = 0; i < CONN_G_HASH_SIZE; i++) {
171 ipst = tcps->tcps_netstack->netstack_ip;
172
173 connfp = &ipst->ips_ipcl_globalhash_fanout[i];
174
175 connp = NULL;
176
177 while ((connp =
178 ipcl_get_next_conn(connfp, connp, IPCL_TCPCONN)) != NULL) {
179 tcp_t *tcp;
180 boolean_t needattr;
181
182 if (connp->conn_zoneid != zoneid)
183 continue; /* not in this zone */
184
185 tcp = connp->conn_tcp;
186 TCPS_UPDATE_MIB(tcps, tcpHCInSegs, tcp->tcp_ibsegs);
187 tcp->tcp_ibsegs = 0;
188 TCPS_UPDATE_MIB(tcps, tcpHCOutSegs, tcp->tcp_obsegs);
189 tcp->tcp_obsegs = 0;
190
191 tce6.tcp6ConnState = tce.tcpConnState =
192 tcp_snmp_state(tcp);
193 if (tce.tcpConnState == MIB2_TCP_established ||
194 tce.tcpConnState == MIB2_TCP_closeWait)
195 BUMP_MIB(&tcp_mib, tcpCurrEstab);
196
197 needattr = B_FALSE;
198 bzero(&mlp, sizeof (mlp));
199 if (connp->conn_mlp_type != mlptSingle) {
200 if (connp->conn_mlp_type == mlptShared ||
201 connp->conn_mlp_type == mlptBoth)
202 mlp.tme_flags |= MIB2_TMEF_SHARED;
203 if (connp->conn_mlp_type == mlptPrivate ||
204 connp->conn_mlp_type == mlptBoth)
205 mlp.tme_flags |= MIB2_TMEF_PRIVATE;
206 needattr = B_TRUE;
207 }
208 if (connp->conn_anon_mlp) {
209 mlp.tme_flags |= MIB2_TMEF_ANONMLP;
210 needattr = B_TRUE;
226
227 tsl = connp->conn_ixa->ixa_tsl;
228 mlp.tme_flags |= MIB2_TMEF_IS_LABELED;
229 mlp.tme_doi = label2doi(tsl);
230 mlp.tme_label = *label2bslabel(tsl);
231 needattr = B_TRUE;
232 }
233
234 /* Create a message to report on IPv6 entries */
235 if (connp->conn_ipversion == IPV6_VERSION) {
236 tce6.tcp6ConnLocalAddress = connp->conn_laddr_v6;
237 tce6.tcp6ConnRemAddress = connp->conn_faddr_v6;
238 tce6.tcp6ConnLocalPort = ntohs(connp->conn_lport);
239 tce6.tcp6ConnRemPort = ntohs(connp->conn_fport);
240 if (connp->conn_ixa->ixa_flags & IXAF_SCOPEID_SET) {
241 tce6.tcp6ConnIfIndex =
242 connp->conn_ixa->ixa_scopeid;
243 } else {
244 tce6.tcp6ConnIfIndex = connp->conn_bound_if;
245 }
246 /* Don't want just anybody seeing these... */
247 if (ispriv) {
248 tce6.tcp6ConnEntryInfo.ce_snxt =
249 tcp->tcp_snxt;
250 tce6.tcp6ConnEntryInfo.ce_suna =
251 tcp->tcp_suna;
252 tce6.tcp6ConnEntryInfo.ce_rnxt =
253 tcp->tcp_rnxt;
254 tce6.tcp6ConnEntryInfo.ce_rack =
255 tcp->tcp_rack;
256 } else {
257 /*
258 * Netstat, unfortunately, uses this to
259 * get send/receive queue sizes. How to fix?
260 * Why not compute the difference only?
261 */
262 tce6.tcp6ConnEntryInfo.ce_snxt =
263 tcp->tcp_snxt - tcp->tcp_suna;
264 tce6.tcp6ConnEntryInfo.ce_suna = 0;
265 tce6.tcp6ConnEntryInfo.ce_rnxt =
266 tcp->tcp_rnxt - tcp->tcp_rack;
267 tce6.tcp6ConnEntryInfo.ce_rack = 0;
268 }
269
270 tce6.tcp6ConnEntryInfo.ce_swnd = tcp->tcp_swnd;
271 tce6.tcp6ConnEntryInfo.ce_rwnd = tcp->tcp_rwnd;
272 tce6.tcp6ConnEntryInfo.ce_rto = tcp->tcp_rto;
273 tce6.tcp6ConnEntryInfo.ce_mss = tcp->tcp_mss;
274 tce6.tcp6ConnEntryInfo.ce_state = tcp->tcp_state;
275
276 tce6.tcp6ConnCreationProcess =
277 (connp->conn_cpid < 0) ? MIB2_UNKNOWN_PROCESS :
278 connp->conn_cpid;
279 tce6.tcp6ConnCreationTime = connp->conn_open_time;
280
281 (void) snmp_append_data2(mp6_conn_ctl->b_cont,
282 &mp6_conn_tail, (char *)&tce6, tce6_size);
283
284 mlp.tme_connidx = v6_conn_idx++;
285 if (needattr)
286 (void) snmp_append_data2(mp6_attr_ctl->b_cont,
287 &mp6_attr_tail, (char *)&mlp, sizeof (mlp));
288 }
289 /*
290 * Create an IPv4 table entry for IPv4 entries and also
291 * for IPv6 entries which are bound to in6addr_any
292 * but don't have IPV6_V6ONLY set.
293 * (i.e. anything an IPv4 peer could connect to)
294 */
295 if (connp->conn_ipversion == IPV4_VERSION ||
296 (tcp->tcp_state <= TCPS_LISTEN &&
297 !connp->conn_ipv6_v6only &&
298 IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6))) {
299 if (connp->conn_ipversion == IPV6_VERSION) {
300 tce.tcpConnRemAddress = INADDR_ANY;
301 tce.tcpConnLocalAddress = INADDR_ANY;
302 } else {
303 tce.tcpConnRemAddress =
304 connp->conn_faddr_v4;
305 tce.tcpConnLocalAddress =
306 connp->conn_laddr_v4;
307 }
308 tce.tcpConnLocalPort = ntohs(connp->conn_lport);
309 tce.tcpConnRemPort = ntohs(connp->conn_fport);
310 /* Don't want just anybody seeing these... */
311 if (ispriv) {
312 tce.tcpConnEntryInfo.ce_snxt =
313 tcp->tcp_snxt;
314 tce.tcpConnEntryInfo.ce_suna =
315 tcp->tcp_suna;
316 tce.tcpConnEntryInfo.ce_rnxt =
317 tcp->tcp_rnxt;
318 tce.tcpConnEntryInfo.ce_rack =
319 tcp->tcp_rack;
320 } else {
321 /*
322 * Netstat, unfortunately, uses this to
323 * get send/receive queue sizes. How
324 * to fix?
325 * Why not compute the difference only?
326 */
327 tce.tcpConnEntryInfo.ce_snxt =
328 tcp->tcp_snxt - tcp->tcp_suna;
329 tce.tcpConnEntryInfo.ce_suna = 0;
330 tce.tcpConnEntryInfo.ce_rnxt =
331 tcp->tcp_rnxt - tcp->tcp_rack;
332 tce.tcpConnEntryInfo.ce_rack = 0;
333 }
334
335 tce.tcpConnEntryInfo.ce_swnd = tcp->tcp_swnd;
336 tce.tcpConnEntryInfo.ce_rwnd = tcp->tcp_rwnd;
337 tce.tcpConnEntryInfo.ce_rto = tcp->tcp_rto;
338 tce.tcpConnEntryInfo.ce_mss = tcp->tcp_mss;
339 tce.tcpConnEntryInfo.ce_state =
340 tcp->tcp_state;
341
342 tce.tcpConnCreationProcess =
343 (connp->conn_cpid < 0) ?
344 MIB2_UNKNOWN_PROCESS :
345 connp->conn_cpid;
346 tce.tcpConnCreationTime = connp->conn_open_time;
347
348 (void) snmp_append_data2(mp_conn_ctl->b_cont,
349 &mp_conn_tail, (char *)&tce, tce_size);
350
351 mlp.tme_connidx = v4_conn_idx++;
352 if (needattr)
353 (void) snmp_append_data2(
354 mp_attr_ctl->b_cont,
355 &mp_attr_tail, (char *)&mlp,
356 sizeof (mlp));
357 }
358 }
359 }
360
|
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) 2011, Joyent Inc. All rights reserved.
25 * Copyright (c) 2015, 2016 by Delphix. All rights reserved.
26 */
27
28 #include <sys/types.h>
29 #include <sys/tihdr.h>
30 #include <sys/policy.h>
31 #include <sys/tsol/tnet.h>
32 #include <sys/kstat.h>
33
34 #include <inet/common.h>
35 #include <inet/ip.h>
36 #include <inet/tcp.h>
37 #include <inet/tcp_impl.h>
38 #include <inet/tcp_stats.h>
39 #include <inet/kstatcom.h>
40 #include <inet/snmpcom.h>
41
42 static int tcp_kstat_update(kstat_t *, int);
43 static int tcp_kstat2_update(kstat_t *, int);
44 static void tcp_sum_mib(tcp_stack_t *, mib2_tcp_t *);
45
70 return (MIB2_TCP_synReceived);
71 case TCPS_ESTABLISHED:
72 return (MIB2_TCP_established);
73 case TCPS_CLOSE_WAIT:
74 return (MIB2_TCP_closeWait);
75 case TCPS_FIN_WAIT_1:
76 return (MIB2_TCP_finWait1);
77 case TCPS_CLOSING:
78 return (MIB2_TCP_closing);
79 case TCPS_LAST_ACK:
80 return (MIB2_TCP_lastAck);
81 case TCPS_FIN_WAIT_2:
82 return (MIB2_TCP_finWait2);
83 case TCPS_TIME_WAIT:
84 return (MIB2_TCP_timeWait);
85 default:
86 return (0);
87 }
88 }
89
90 static void
91 tcp_set_conninfo(tcp_t *tcp, struct tcpConnEntryInfo_s *tcei, boolean_t ispriv)
92 {
93 /* Don't want just anybody seeing these... */
94 if (ispriv) {
95 tcei->ce_snxt = tcp->tcp_snxt;
96 tcei->ce_suna = tcp->tcp_suna;
97 tcei->ce_rnxt = tcp->tcp_rnxt;
98 tcei->ce_rack = tcp->tcp_rack;
99 } else {
100 /*
101 * Netstat, unfortunately, uses this to get send/receive queue
102 * sizes. How to fix? Why not compute the difference only?
103 */
104 tcei->ce_snxt = tcp->tcp_snxt - tcp->tcp_suna;
105 tcei->ce_suna = 0;
106 tcei->ce_rnxt = tcp->tcp_rnxt - tcp->tcp_rack;
107 tcei->ce_rack = 0;
108 }
109
110 tcei->ce_in_data_inorder_bytes = tcp->tcp_cs.tcp_in_data_inorder_bytes;
111 tcei->ce_in_data_inorder_segs = tcp->tcp_cs.tcp_in_data_inorder_segs;
112 tcei->ce_in_data_unorder_bytes = tcp->tcp_cs.tcp_in_data_unorder_bytes;
113 tcei->ce_in_data_unorder_segs = tcp->tcp_cs.tcp_in_data_unorder_segs;
114 tcei->ce_in_zwnd_probes = tcp->tcp_cs.tcp_in_zwnd_probes;
115
116 tcei->ce_out_data_bytes = tcp->tcp_cs.tcp_out_data_bytes;
117 tcei->ce_out_data_segs = tcp->tcp_cs.tcp_out_data_segs;
118 tcei->ce_out_retrans_bytes = tcp->tcp_cs.tcp_out_retrans_bytes;
119 tcei->ce_out_retrans_segs = tcp->tcp_cs.tcp_out_retrans_segs;
120 tcei->ce_out_zwnd_probes = tcp->tcp_cs.tcp_out_zwnd_probes;
121
122 tcei->ce_unsent = tcp->tcp_unsent;
123 tcei->ce_swnd = tcp->tcp_swnd;
124 tcei->ce_cwnd = tcp->tcp_cwnd;
125 tcei->ce_rwnd = tcp->tcp_rwnd;
126 tcei->ce_rto = tcp->tcp_rto;
127 tcei->ce_mss = tcp->tcp_mss;
128 tcei->ce_state = tcp->tcp_state;
129 tcei->ce_rtt_sa = NSEC2USEC(tcp->tcp_rtt_sa >> 3);
130 tcei->ce_rtt_sum = NSEC2USEC(tcp->tcp_rtt_sum);
131 tcei->ce_rtt_cnt = tcp->tcp_rtt_cnt;
132 }
133
134 /*
135 * Return SNMP stuff in buffer in mpdata.
136 */
137 mblk_t *
138 tcp_snmp_get(queue_t *q, mblk_t *mpctl, boolean_t legacy_req)
139 {
140 mblk_t *mpdata;
141 mblk_t *mp_conn_ctl = NULL;
142 mblk_t *mp_conn_tail;
143 mblk_t *mp_attr_ctl = NULL;
144 mblk_t *mp_attr_tail;
145 mblk_t *mp6_conn_ctl = NULL;
146 mblk_t *mp6_conn_tail;
147 mblk_t *mp6_attr_ctl = NULL;
148 mblk_t *mp6_attr_tail;
149 struct opthdr *optp;
150 mib2_tcpConnEntry_t tce;
151 mib2_tcp6ConnEntry_t tce6;
152 mib2_transportMLPEntry_t mlp;
153 connf_t *connfp;
211
212 v4_conn_idx = v6_conn_idx = 0;
213 mp_conn_tail = mp_attr_tail = mp6_conn_tail = mp6_attr_tail = NULL;
214
215 for (i = 0; i < CONN_G_HASH_SIZE; i++) {
216 ipst = tcps->tcps_netstack->netstack_ip;
217
218 connfp = &ipst->ips_ipcl_globalhash_fanout[i];
219
220 connp = NULL;
221
222 while ((connp =
223 ipcl_get_next_conn(connfp, connp, IPCL_TCPCONN)) != NULL) {
224 tcp_t *tcp;
225 boolean_t needattr;
226
227 if (connp->conn_zoneid != zoneid)
228 continue; /* not in this zone */
229
230 tcp = connp->conn_tcp;
231 tce6.tcp6ConnState = tce.tcpConnState =
232 tcp_snmp_state(tcp);
233 if (tce.tcpConnState == MIB2_TCP_established ||
234 tce.tcpConnState == MIB2_TCP_closeWait)
235 BUMP_MIB(&tcp_mib, tcpCurrEstab);
236
237 needattr = B_FALSE;
238 bzero(&mlp, sizeof (mlp));
239 if (connp->conn_mlp_type != mlptSingle) {
240 if (connp->conn_mlp_type == mlptShared ||
241 connp->conn_mlp_type == mlptBoth)
242 mlp.tme_flags |= MIB2_TMEF_SHARED;
243 if (connp->conn_mlp_type == mlptPrivate ||
244 connp->conn_mlp_type == mlptBoth)
245 mlp.tme_flags |= MIB2_TMEF_PRIVATE;
246 needattr = B_TRUE;
247 }
248 if (connp->conn_anon_mlp) {
249 mlp.tme_flags |= MIB2_TMEF_ANONMLP;
250 needattr = B_TRUE;
266
267 tsl = connp->conn_ixa->ixa_tsl;
268 mlp.tme_flags |= MIB2_TMEF_IS_LABELED;
269 mlp.tme_doi = label2doi(tsl);
270 mlp.tme_label = *label2bslabel(tsl);
271 needattr = B_TRUE;
272 }
273
274 /* Create a message to report on IPv6 entries */
275 if (connp->conn_ipversion == IPV6_VERSION) {
276 tce6.tcp6ConnLocalAddress = connp->conn_laddr_v6;
277 tce6.tcp6ConnRemAddress = connp->conn_faddr_v6;
278 tce6.tcp6ConnLocalPort = ntohs(connp->conn_lport);
279 tce6.tcp6ConnRemPort = ntohs(connp->conn_fport);
280 if (connp->conn_ixa->ixa_flags & IXAF_SCOPEID_SET) {
281 tce6.tcp6ConnIfIndex =
282 connp->conn_ixa->ixa_scopeid;
283 } else {
284 tce6.tcp6ConnIfIndex = connp->conn_bound_if;
285 }
286
287 tcp_set_conninfo(tcp, &tce6.tcp6ConnEntryInfo,
288 ispriv);
289
290 tce6.tcp6ConnCreationProcess =
291 (connp->conn_cpid < 0) ? MIB2_UNKNOWN_PROCESS :
292 connp->conn_cpid;
293 tce6.tcp6ConnCreationTime = connp->conn_open_time;
294
295 (void) snmp_append_data2(mp6_conn_ctl->b_cont,
296 &mp6_conn_tail, (char *)&tce6, tce6_size);
297
298 mlp.tme_connidx = v6_conn_idx++;
299 if (needattr)
300 (void) snmp_append_data2(mp6_attr_ctl->b_cont,
301 &mp6_attr_tail, (char *)&mlp, sizeof (mlp));
302 }
303 /*
304 * Create an IPv4 table entry for IPv4 entries and also
305 * for IPv6 entries which are bound to in6addr_any
306 * but don't have IPV6_V6ONLY set.
307 * (i.e. anything an IPv4 peer could connect to)
308 */
309 if (connp->conn_ipversion == IPV4_VERSION ||
310 (tcp->tcp_state <= TCPS_LISTEN &&
311 !connp->conn_ipv6_v6only &&
312 IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6))) {
313 if (connp->conn_ipversion == IPV6_VERSION) {
314 tce.tcpConnRemAddress = INADDR_ANY;
315 tce.tcpConnLocalAddress = INADDR_ANY;
316 } else {
317 tce.tcpConnRemAddress =
318 connp->conn_faddr_v4;
319 tce.tcpConnLocalAddress =
320 connp->conn_laddr_v4;
321 }
322 tce.tcpConnLocalPort = ntohs(connp->conn_lport);
323 tce.tcpConnRemPort = ntohs(connp->conn_fport);
324
325 tcp_set_conninfo(tcp, &tce.tcpConnEntryInfo,
326 ispriv);
327
328 tce.tcpConnCreationProcess =
329 (connp->conn_cpid < 0) ?
330 MIB2_UNKNOWN_PROCESS :
331 connp->conn_cpid;
332 tce.tcpConnCreationTime = connp->conn_open_time;
333
334 (void) snmp_append_data2(mp_conn_ctl->b_cont,
335 &mp_conn_tail, (char *)&tce, tce_size);
336
337 mlp.tme_connidx = v4_conn_idx++;
338 if (needattr)
339 (void) snmp_append_data2(
340 mp_attr_ctl->b_cont,
341 &mp_attr_tail, (char *)&mlp,
342 sizeof (mlp));
343 }
344 }
345 }
346
|