Print this page
XXXX adding PID information to netstat output
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/inet/udp/udp_stats.c
+++ new/usr/src/uts/common/inet/udp/udp_stats.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 26 #include <sys/types.h>
27 27 #include <sys/tihdr.h>
28 28 #include <sys/policy.h>
29 29 #include <sys/tsol/tnet.h>
30 30
31 31 #include <inet/common.h>
32 32 #include <inet/kstatcom.h>
33 33 #include <inet/snmpcom.h>
34 34 #include <inet/mib2.h>
35 35 #include <inet/optcom.h>
36 36 #include <inet/snmpcom.h>
37 37 #include <inet/kstatcom.h>
38 38 #include <inet/udp_impl.h>
39 39
40 40 static int udp_kstat_update(kstat_t *, int);
41 41 static int udp_kstat2_update(kstat_t *, int);
42 42 static void udp_sum_mib(udp_stack_t *, mib2_udp_t *);
43 43 static void udp_clr_stats(udp_stat_t *);
44 44 static void udp_add_stats(udp_stat_counter_t *, udp_stat_t *);
45 45 static void udp_add_mib(mib2_udp_t *, mib2_udp_t *);
↓ open down ↓ |
45 lines elided |
↑ open up ↑ |
46 46 /*
47 47 * return SNMP stuff in buffer in mpdata. We don't hold any lock and report
48 48 * information that can be changing beneath us.
49 49 */
50 50 mblk_t *
51 51 udp_snmp_get(queue_t *q, mblk_t *mpctl, boolean_t legacy_req)
52 52 {
53 53 mblk_t *mpdata;
54 54 mblk_t *mp_conn_ctl;
55 55 mblk_t *mp_attr_ctl;
56 + mblk_t *mp_pidnode_ctl;
56 57 mblk_t *mp6_conn_ctl;
57 58 mblk_t *mp6_attr_ctl;
59 + mblk_t *mp6_pidnode_ctl;
58 60 mblk_t *mp_conn_tail;
59 61 mblk_t *mp_attr_tail;
62 + mblk_t *mp_pidnode_tail;
60 63 mblk_t *mp6_conn_tail;
61 64 mblk_t *mp6_attr_tail;
65 + mblk_t *mp6_pidnode_tail;
62 66 struct opthdr *optp;
63 67 mib2_udpEntry_t ude;
64 68 mib2_udp6Entry_t ude6;
65 69 mib2_transportMLPEntry_t mlp;
66 70 int state;
67 71 zoneid_t zoneid;
68 72 int i;
69 73 connf_t *connfp;
70 74 conn_t *connp = Q_TO_CONN(q);
71 75 int v4_conn_idx;
72 76 int v6_conn_idx;
73 77 boolean_t needattr;
74 78 udp_t *udp;
75 79 ip_stack_t *ipst = connp->conn_netstack->netstack_ip;
76 80 udp_stack_t *us = connp->conn_netstack->netstack_udp;
77 81 mblk_t *mp2ctl;
78 82 mib2_udp_t udp_mib;
79 83 size_t udp_mib_size, ude_size, ude6_size;
80 84
85 + conn_pid_node_list_hdr_t *cph;
86 +
81 87
82 88 /*
83 89 * make a copy of the original message
84 90 */
85 91 mp2ctl = copymsg(mpctl);
86 92
87 93 mp_conn_ctl = mp_attr_ctl = mp6_conn_ctl = NULL;
88 94 if (mpctl == NULL ||
89 95 (mpdata = mpctl->b_cont) == NULL ||
90 96 (mp_conn_ctl = copymsg(mpctl)) == NULL ||
91 97 (mp_attr_ctl = copymsg(mpctl)) == NULL ||
98 + (mp_pidnode_ctl = copymsg(mpctl)) == NULL ||
92 99 (mp6_conn_ctl = copymsg(mpctl)) == NULL ||
93 - (mp6_attr_ctl = copymsg(mpctl)) == NULL) {
100 + (mp6_attr_ctl = copymsg(mpctl)) == NULL ||
101 + (mp6_pidnode_ctl = copymsg(mpctl)) == NULL) {
94 102 freemsg(mp_conn_ctl);
95 103 freemsg(mp_attr_ctl);
104 + freemsg(mp_pidnode_ctl);
96 105 freemsg(mp6_conn_ctl);
106 + freemsg(mp6_attr_ctl);
107 + freemsg(mp6_pidnode_ctl);
97 108 freemsg(mpctl);
98 109 freemsg(mp2ctl);
99 110 return (0);
100 111 }
101 112
102 113 zoneid = connp->conn_zoneid;
103 114
104 115 if (legacy_req) {
105 116 udp_mib_size = LEGACY_MIB_SIZE(&udp_mib, mib2_udp_t);
106 117 ude_size = LEGACY_MIB_SIZE(&ude, mib2_udpEntry_t);
107 118 ude6_size = LEGACY_MIB_SIZE(&ude6, mib2_udp6Entry_t);
108 119 } else {
109 120 udp_mib_size = sizeof (mib2_udp_t);
110 121 ude_size = sizeof (mib2_udpEntry_t);
111 122 ude6_size = sizeof (mib2_udp6Entry_t);
112 123 }
113 124
114 125 bzero(&udp_mib, sizeof (udp_mib));
115 126 /* fixed length structure for IPv4 and IPv6 counters */
116 127 SET_MIB(udp_mib.udpEntrySize, ude_size);
117 128 SET_MIB(udp_mib.udp6EntrySize, ude6_size);
118 129
119 130 udp_sum_mib(us, &udp_mib);
120 131
121 132 /*
122 133 * Synchronize 32- and 64-bit counters. Note that udpInDatagrams and
123 134 * udpOutDatagrams are not updated anywhere in UDP. The new 64 bits
124 135 * counters are used. Hence the old counters' values in us_sc_mib
125 136 * are always 0.
126 137 */
127 138 SYNC32_MIB(&udp_mib, udpInDatagrams, udpHCInDatagrams);
↓ open down ↓ |
21 lines elided |
↑ open up ↑ |
128 139 SYNC32_MIB(&udp_mib, udpOutDatagrams, udpHCOutDatagrams);
129 140
130 141 optp = (struct opthdr *)&mpctl->b_rptr[sizeof (struct T_optmgmt_ack)];
131 142 optp->level = MIB2_UDP;
132 143 optp->name = 0;
133 144 (void) snmp_append_data(mpdata, (char *)&udp_mib, udp_mib_size);
134 145 optp->len = msgdsize(mpdata);
135 146 qreply(q, mpctl);
136 147
137 148 mp_conn_tail = mp_attr_tail = mp6_conn_tail = mp6_attr_tail = NULL;
149 + mp_pidnode_tail = mp6_pidnode_tail = NULL;
138 150 v4_conn_idx = v6_conn_idx = 0;
139 151
140 152 for (i = 0; i < CONN_G_HASH_SIZE; i++) {
141 153 connfp = &ipst->ips_ipcl_globalhash_fanout[i];
142 154 connp = NULL;
143 155
144 156 while ((connp = ipcl_get_next_conn(connfp, connp,
145 157 IPCL_UDPCONN))) {
146 158 udp = connp->conn_udp;
147 159 if (zoneid != connp->conn_zoneid)
148 160 continue;
149 161
150 162 /*
151 163 * Note that the port numbers are sent in
152 164 * host byte order
153 165 */
154 166
155 167 if (udp->udp_state == TS_UNBND)
156 168 state = MIB2_UDP_unbound;
157 169 else if (udp->udp_state == TS_IDLE)
158 170 state = MIB2_UDP_idle;
159 171 else if (udp->udp_state == TS_DATA_XFER)
160 172 state = MIB2_UDP_connected;
161 173 else
162 174 state = MIB2_UDP_unknown;
163 175
164 176 needattr = B_FALSE;
165 177 bzero(&mlp, sizeof (mlp));
166 178 if (connp->conn_mlp_type != mlptSingle) {
167 179 if (connp->conn_mlp_type == mlptShared ||
168 180 connp->conn_mlp_type == mlptBoth)
169 181 mlp.tme_flags |= MIB2_TMEF_SHARED;
170 182 if (connp->conn_mlp_type == mlptPrivate ||
171 183 connp->conn_mlp_type == mlptBoth)
172 184 mlp.tme_flags |= MIB2_TMEF_PRIVATE;
173 185 needattr = B_TRUE;
174 186 }
175 187 if (connp->conn_anon_mlp) {
176 188 mlp.tme_flags |= MIB2_TMEF_ANONMLP;
177 189 needattr = B_TRUE;
178 190 }
179 191 switch (connp->conn_mac_mode) {
180 192 case CONN_MAC_DEFAULT:
181 193 break;
182 194 case CONN_MAC_AWARE:
183 195 mlp.tme_flags |= MIB2_TMEF_MACEXEMPT;
184 196 needattr = B_TRUE;
185 197 break;
186 198 case CONN_MAC_IMPLICIT:
187 199 mlp.tme_flags |= MIB2_TMEF_MACIMPLICIT;
188 200 needattr = B_TRUE;
189 201 break;
190 202 }
191 203 mutex_enter(&connp->conn_lock);
192 204 if (udp->udp_state == TS_DATA_XFER &&
193 205 connp->conn_ixa->ixa_tsl != NULL) {
194 206 ts_label_t *tsl;
195 207
196 208 tsl = connp->conn_ixa->ixa_tsl;
197 209 mlp.tme_flags |= MIB2_TMEF_IS_LABELED;
198 210 mlp.tme_doi = label2doi(tsl);
199 211 mlp.tme_label = *label2bslabel(tsl);
200 212 needattr = B_TRUE;
201 213 }
202 214 mutex_exit(&connp->conn_lock);
203 215
204 216 /*
205 217 * Create an IPv4 table entry for IPv4 entries and also
206 218 * any IPv6 entries which are bound to in6addr_any
207 219 * (i.e. anything a IPv4 peer could connect/send to).
208 220 */
209 221 if (connp->conn_ipversion == IPV4_VERSION ||
210 222 (udp->udp_state <= TS_IDLE &&
211 223 IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6))) {
212 224 ude.udpEntryInfo.ue_state = state;
213 225 /*
214 226 * If in6addr_any this will set it to
215 227 * INADDR_ANY
216 228 */
217 229 ude.udpLocalAddress = connp->conn_laddr_v4;
218 230 ude.udpLocalPort = ntohs(connp->conn_lport);
219 231 if (udp->udp_state == TS_DATA_XFER) {
220 232 /*
221 233 * Can potentially get here for
222 234 * v6 socket if another process
223 235 * (say, ping) has just done a
224 236 * sendto(), changing the state
225 237 * from the TS_IDLE above to
226 238 * TS_DATA_XFER by the time we hit
227 239 * this part of the code.
228 240 */
229 241 ude.udpEntryInfo.ue_RemoteAddress =
230 242 connp->conn_faddr_v4;
231 243 ude.udpEntryInfo.ue_RemotePort =
232 244 ntohs(connp->conn_fport);
233 245 } else {
234 246 ude.udpEntryInfo.ue_RemoteAddress = 0;
235 247 ude.udpEntryInfo.ue_RemotePort = 0;
236 248 }
237 249
238 250 /*
239 251 * We make the assumption that all udp_t
240 252 * structs will be created within an address
241 253 * region no larger than 32-bits.
↓ open down ↓ |
94 lines elided |
↑ open up ↑ |
242 254 */
243 255 ude.udpInstance = (uint32_t)(uintptr_t)udp;
244 256 ude.udpCreationProcess =
245 257 (connp->conn_cpid < 0) ?
246 258 MIB2_UNKNOWN_PROCESS :
247 259 connp->conn_cpid;
248 260 ude.udpCreationTime = connp->conn_open_time;
249 261
250 262 (void) snmp_append_data2(mp_conn_ctl->b_cont,
251 263 &mp_conn_tail, (char *)&ude, ude_size);
264 + /* my data */
265 + (void) snmp_append_data2(mp_pidnode_ctl->b_cont,
266 + &mp_pidnode_tail, (char *)&ude, ude_size);
267 +
268 + cph = conn_get_pid_list(connp);
269 + (void) snmp_append_data2(mp_pidnode_ctl->b_cont,
270 + &mp_pidnode_tail, (char *)cph,
271 + cph->cph_tot_size);
272 +
273 + kmem_free(cph, cph->cph_tot_size);
274 + /* end of my data */
275 +
252 276 mlp.tme_connidx = v4_conn_idx++;
253 277 if (needattr)
254 278 (void) snmp_append_data2(
255 279 mp_attr_ctl->b_cont, &mp_attr_tail,
256 280 (char *)&mlp, sizeof (mlp));
257 281 }
258 282 if (connp->conn_ipversion == IPV6_VERSION) {
259 283 ude6.udp6EntryInfo.ue_state = state;
260 284 ude6.udp6LocalAddress = connp->conn_laddr_v6;
261 285 ude6.udp6LocalPort = ntohs(connp->conn_lport);
262 286 mutex_enter(&connp->conn_lock);
263 287 if (connp->conn_ixa->ixa_flags &
264 288 IXAF_SCOPEID_SET) {
265 289 ude6.udp6IfIndex =
266 290 connp->conn_ixa->ixa_scopeid;
267 291 } else {
268 292 ude6.udp6IfIndex = connp->conn_bound_if;
269 293 }
270 294 mutex_exit(&connp->conn_lock);
271 295 if (udp->udp_state == TS_DATA_XFER) {
272 296 ude6.udp6EntryInfo.ue_RemoteAddress =
273 297 connp->conn_faddr_v6;
274 298 ude6.udp6EntryInfo.ue_RemotePort =
275 299 ntohs(connp->conn_fport);
276 300 } else {
277 301 ude6.udp6EntryInfo.ue_RemoteAddress =
278 302 sin6_null.sin6_addr;
279 303 ude6.udp6EntryInfo.ue_RemotePort = 0;
280 304 }
281 305 /*
282 306 * We make the assumption that all udp_t
283 307 * structs will be created within an address
284 308 * region no larger than 32-bits.
↓ open down ↓ |
23 lines elided |
↑ open up ↑ |
285 309 */
286 310 ude6.udp6Instance = (uint32_t)(uintptr_t)udp;
287 311 ude6.udp6CreationProcess =
288 312 (connp->conn_cpid < 0) ?
289 313 MIB2_UNKNOWN_PROCESS :
290 314 connp->conn_cpid;
291 315 ude6.udp6CreationTime = connp->conn_open_time;
292 316
293 317 (void) snmp_append_data2(mp6_conn_ctl->b_cont,
294 318 &mp6_conn_tail, (char *)&ude6, ude6_size);
319 + /* my dat */
320 + (void) snmp_append_data2(
321 + mp6_pidnode_ctl->b_cont, &mp6_pidnode_tail,
322 + (char *)&ude6, ude6_size);
323 +
324 + cph = conn_get_pid_list(connp);
325 + (void) snmp_append_data2(
326 + mp6_pidnode_ctl->b_cont, &mp6_pidnode_tail,
327 + (char *)cph, cph->cph_tot_size);
328 +
329 + kmem_free(cph, cph->cph_tot_size);
330 + /* end of my data */
295 331 mlp.tme_connidx = v6_conn_idx++;
296 332 if (needattr)
297 333 (void) snmp_append_data2(
298 334 mp6_attr_ctl->b_cont,
299 335 &mp6_attr_tail, (char *)&mlp,
300 336 sizeof (mlp));
301 337 }
302 338 }
303 339 }
304 340
305 341 /* IPv4 UDP endpoints */
306 342 optp = (struct opthdr *)&mp_conn_ctl->b_rptr[
307 343 sizeof (struct T_optmgmt_ack)];
308 344 optp->level = MIB2_UDP;
309 345 optp->name = MIB2_UDP_ENTRY;
310 346 optp->len = msgdsize(mp_conn_ctl->b_cont);
311 347 qreply(q, mp_conn_ctl);
312 348
313 349 /* table of MLP attributes... */
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
314 350 optp = (struct opthdr *)&mp_attr_ctl->b_rptr[
315 351 sizeof (struct T_optmgmt_ack)];
316 352 optp->level = MIB2_UDP;
317 353 optp->name = EXPER_XPORT_MLP;
318 354 optp->len = msgdsize(mp_attr_ctl->b_cont);
319 355 if (optp->len == 0)
320 356 freemsg(mp_attr_ctl);
321 357 else
322 358 qreply(q, mp_attr_ctl);
323 359
360 + /* table of EXPER_XPORT_PROC_INFO ipv4 */
361 + optp = (struct opthdr *)&mp_pidnode_ctl->b_rptr[
362 + sizeof (struct T_optmgmt_ack)];
363 + optp->level = MIB2_UDP;
364 + optp->name = EXPER_XPORT_PROC_INFO;
365 + optp->len = msgdsize(mp_pidnode_ctl->b_cont);
366 + if (optp->len == 0)
367 + freemsg(mp_pidnode_ctl);
368 + else
369 + qreply(q, mp_pidnode_ctl);
370 +
324 371 /* IPv6 UDP endpoints */
325 372 optp = (struct opthdr *)&mp6_conn_ctl->b_rptr[
326 373 sizeof (struct T_optmgmt_ack)];
327 374 optp->level = MIB2_UDP6;
328 375 optp->name = MIB2_UDP6_ENTRY;
329 376 optp->len = msgdsize(mp6_conn_ctl->b_cont);
330 377 qreply(q, mp6_conn_ctl);
331 378
332 379 /* table of MLP attributes... */
333 380 optp = (struct opthdr *)&mp6_attr_ctl->b_rptr[
334 381 sizeof (struct T_optmgmt_ack)];
335 382 optp->level = MIB2_UDP6;
336 383 optp->name = EXPER_XPORT_MLP;
337 384 optp->len = msgdsize(mp6_attr_ctl->b_cont);
338 385 if (optp->len == 0)
339 386 freemsg(mp6_attr_ctl);
340 387 else
341 388 qreply(q, mp6_attr_ctl);
389 +
390 + /* table of EXPER_XPORT_PROC_INFO ipv6 */
391 + optp = (struct opthdr *)&mp6_pidnode_ctl->b_rptr[
392 + sizeof (struct T_optmgmt_ack)];
393 + optp->level = MIB2_UDP6;
394 + optp->name = EXPER_XPORT_PROC_INFO;
395 + optp->len = msgdsize(mp6_pidnode_ctl->b_cont);
396 + if (optp->len == 0)
397 + freemsg(mp6_pidnode_ctl);
398 + else
399 + qreply(q, mp6_pidnode_ctl);
342 400
343 401 return (mp2ctl);
344 402 }
345 403
346 404 /*
347 405 * Return 0 if invalid set request, 1 otherwise, including non-udp requests.
348 406 * NOTE: Per MIB-II, UDP has no writable data.
349 407 * TODO: If this ever actually tries to set anything, it needs to be
350 408 * to do the appropriate locking.
351 409 */
352 410 /* ARGSUSED */
353 411 int
354 412 udp_snmp_set(queue_t *q, t_scalar_t level, t_scalar_t name,
355 413 uchar_t *ptr, int len)
356 414 {
357 415 switch (level) {
358 416 case MIB2_UDP:
359 417 return (0);
360 418 default:
361 419 return (1);
362 420 }
363 421 }
364 422
365 423 void
366 424 udp_kstat_fini(netstackid_t stackid, kstat_t *ksp)
367 425 {
368 426 if (ksp != NULL) {
369 427 ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private);
370 428 kstat_delete_netstack(ksp, stackid);
371 429 }
372 430 }
373 431
374 432 /*
375 433 * To add stats from one mib2_udp_t to another. Static fields are not added.
376 434 * The caller should set them up propertly.
377 435 */
378 436 static void
379 437 udp_add_mib(mib2_udp_t *from, mib2_udp_t *to)
380 438 {
381 439 to->udpHCInDatagrams += from->udpHCInDatagrams;
382 440 to->udpInErrors += from->udpInErrors;
383 441 to->udpHCOutDatagrams += from->udpHCOutDatagrams;
384 442 to->udpOutErrors += from->udpOutErrors;
385 443 }
386 444
387 445
388 446 void *
389 447 udp_kstat2_init(netstackid_t stackid)
390 448 {
391 449 kstat_t *ksp;
392 450
393 451 udp_stat_t template = {
394 452 { "udp_sock_fallback", KSTAT_DATA_UINT64 },
395 453 { "udp_out_opt", KSTAT_DATA_UINT64 },
396 454 { "udp_out_err_notconn", KSTAT_DATA_UINT64 },
397 455 { "udp_out_err_output", KSTAT_DATA_UINT64 },
398 456 { "udp_out_err_tudr", KSTAT_DATA_UINT64 },
399 457 #ifdef DEBUG
400 458 { "udp_data_conn", KSTAT_DATA_UINT64 },
401 459 { "udp_data_notconn", KSTAT_DATA_UINT64 },
402 460 { "udp_out_lastdst", KSTAT_DATA_UINT64 },
403 461 { "udp_out_diffdst", KSTAT_DATA_UINT64 },
404 462 { "udp_out_ipv6", KSTAT_DATA_UINT64 },
405 463 { "udp_out_mapped", KSTAT_DATA_UINT64 },
406 464 { "udp_out_ipv4", KSTAT_DATA_UINT64 },
407 465 #endif
408 466 };
409 467
410 468 ksp = kstat_create_netstack(UDP_MOD_NAME, 0, "udpstat", "net",
411 469 KSTAT_TYPE_NAMED, sizeof (template) / sizeof (kstat_named_t),
412 470 0, stackid);
413 471
414 472 if (ksp == NULL)
415 473 return (NULL);
416 474
417 475 bcopy(&template, ksp->ks_data, sizeof (template));
418 476 ksp->ks_update = udp_kstat2_update;
419 477 ksp->ks_private = (void *)(uintptr_t)stackid;
420 478
421 479 kstat_install(ksp);
422 480 return (ksp);
423 481 }
424 482
425 483 void
426 484 udp_kstat2_fini(netstackid_t stackid, kstat_t *ksp)
427 485 {
428 486 if (ksp != NULL) {
429 487 ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private);
430 488 kstat_delete_netstack(ksp, stackid);
431 489 }
432 490 }
433 491
434 492 /*
435 493 * To copy counters from the per CPU udpp_stat_counter_t to the stack
436 494 * udp_stat_t.
437 495 */
438 496 static void
439 497 udp_add_stats(udp_stat_counter_t *from, udp_stat_t *to)
440 498 {
441 499 to->udp_sock_fallback.value.ui64 += from->udp_sock_fallback;
442 500 to->udp_out_opt.value.ui64 += from->udp_out_opt;
443 501 to->udp_out_err_notconn.value.ui64 += from->udp_out_err_notconn;
444 502 to->udp_out_err_output.value.ui64 += from->udp_out_err_output;
445 503 to->udp_out_err_tudr.value.ui64 += from->udp_out_err_tudr;
446 504 #ifdef DEBUG
447 505 to->udp_data_conn.value.ui64 += from->udp_data_conn;
448 506 to->udp_data_notconn.value.ui64 += from->udp_data_notconn;
449 507 to->udp_out_lastdst.value.ui64 += from->udp_out_lastdst;
450 508 to->udp_out_diffdst.value.ui64 += from->udp_out_diffdst;
451 509 to->udp_out_ipv6.value.ui64 += from->udp_out_ipv6;
452 510 to->udp_out_mapped.value.ui64 += from->udp_out_mapped;
453 511 to->udp_out_ipv4.value.ui64 += from->udp_out_ipv4;
454 512 #endif
455 513 }
456 514
457 515 /*
458 516 * To set all udp_stat_t counters to 0.
459 517 */
460 518 static void
461 519 udp_clr_stats(udp_stat_t *stats)
462 520 {
463 521 stats->udp_sock_fallback.value.ui64 = 0;
464 522 stats->udp_out_opt.value.ui64 = 0;
465 523 stats->udp_out_err_notconn.value.ui64 = 0;
466 524 stats->udp_out_err_output.value.ui64 = 0;
467 525 stats->udp_out_err_tudr.value.ui64 = 0;
468 526 #ifdef DEBUG
469 527 stats->udp_data_conn.value.ui64 = 0;
470 528 stats->udp_data_notconn.value.ui64 = 0;
471 529 stats->udp_out_lastdst.value.ui64 = 0;
472 530 stats->udp_out_diffdst.value.ui64 = 0;
473 531 stats->udp_out_ipv6.value.ui64 = 0;
474 532 stats->udp_out_mapped.value.ui64 = 0;
475 533 stats->udp_out_ipv4.value.ui64 = 0;
476 534 #endif
477 535 }
478 536
479 537 int
480 538 udp_kstat2_update(kstat_t *kp, int rw)
481 539 {
482 540 udp_stat_t *stats;
483 541 netstackid_t stackid = (netstackid_t)(uintptr_t)kp->ks_private;
484 542 netstack_t *ns;
485 543 udp_stack_t *us;
486 544 int i;
487 545 int cnt;
488 546
489 547 if (rw == KSTAT_WRITE)
490 548 return (EACCES);
491 549
492 550 ns = netstack_find_by_stackid(stackid);
493 551 if (ns == NULL)
494 552 return (-1);
495 553 us = ns->netstack_udp;
496 554 if (us == NULL) {
497 555 netstack_rele(ns);
498 556 return (-1);
499 557 }
500 558 stats = (udp_stat_t *)kp->ks_data;
501 559 udp_clr_stats(stats);
502 560
503 561 cnt = us->us_sc_cnt;
504 562 for (i = 0; i < cnt; i++)
505 563 udp_add_stats(&us->us_sc[i]->udp_sc_stats, stats);
506 564
507 565 netstack_rele(ns);
508 566 return (0);
509 567 }
510 568
511 569 void *
512 570 udp_kstat_init(netstackid_t stackid)
513 571 {
514 572 kstat_t *ksp;
515 573
516 574 udp_named_kstat_t template = {
517 575 { "inDatagrams", KSTAT_DATA_UINT64, 0 },
518 576 { "inErrors", KSTAT_DATA_UINT32, 0 },
519 577 { "outDatagrams", KSTAT_DATA_UINT64, 0 },
520 578 { "entrySize", KSTAT_DATA_INT32, 0 },
521 579 { "entry6Size", KSTAT_DATA_INT32, 0 },
522 580 { "outErrors", KSTAT_DATA_UINT32, 0 },
523 581 };
524 582
525 583 ksp = kstat_create_netstack(UDP_MOD_NAME, 0, UDP_MOD_NAME, "mib2",
526 584 KSTAT_TYPE_NAMED, NUM_OF_FIELDS(udp_named_kstat_t), 0, stackid);
527 585
528 586 if (ksp == NULL)
529 587 return (NULL);
530 588
531 589 template.entrySize.value.ui32 = sizeof (mib2_udpEntry_t);
532 590 template.entry6Size.value.ui32 = sizeof (mib2_udp6Entry_t);
533 591
534 592 bcopy(&template, ksp->ks_data, sizeof (template));
535 593 ksp->ks_update = udp_kstat_update;
536 594 ksp->ks_private = (void *)(uintptr_t)stackid;
537 595
538 596 kstat_install(ksp);
539 597 return (ksp);
540 598 }
541 599
542 600 /*
543 601 * To sum up all MIB2 stats for a udp_stack_t from all per CPU stats. The
544 602 * caller should initialize the target mib2_udp_t properly as this function
545 603 * just adds up all the per CPU stats.
546 604 */
547 605 static void
548 606 udp_sum_mib(udp_stack_t *us, mib2_udp_t *udp_mib)
549 607 {
550 608 int i;
551 609 int cnt;
552 610
553 611 cnt = us->us_sc_cnt;
554 612 for (i = 0; i < cnt; i++)
555 613 udp_add_mib(&us->us_sc[i]->udp_sc_mib, udp_mib);
556 614 }
557 615
558 616 static int
559 617 udp_kstat_update(kstat_t *kp, int rw)
560 618 {
561 619 udp_named_kstat_t *udpkp;
562 620 netstackid_t stackid = (netstackid_t)(uintptr_t)kp->ks_private;
563 621 netstack_t *ns;
564 622 udp_stack_t *us;
565 623 mib2_udp_t udp_mib;
566 624
567 625 if (rw == KSTAT_WRITE)
568 626 return (EACCES);
569 627
570 628 ns = netstack_find_by_stackid(stackid);
571 629 if (ns == NULL)
572 630 return (-1);
573 631 us = ns->netstack_udp;
574 632 if (us == NULL) {
575 633 netstack_rele(ns);
576 634 return (-1);
577 635 }
578 636 udpkp = (udp_named_kstat_t *)kp->ks_data;
579 637
580 638 bzero(&udp_mib, sizeof (udp_mib));
581 639 udp_sum_mib(us, &udp_mib);
582 640
583 641 udpkp->inDatagrams.value.ui64 = udp_mib.udpHCInDatagrams;
584 642 udpkp->inErrors.value.ui32 = udp_mib.udpInErrors;
585 643 udpkp->outDatagrams.value.ui64 = udp_mib.udpHCOutDatagrams;
586 644 udpkp->outErrors.value.ui32 = udp_mib.udpOutErrors;
587 645 netstack_rele(ns);
588 646 return (0);
589 647 }
↓ open down ↓ |
238 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX