15dd46ab5SKacheong Poon /*
25dd46ab5SKacheong Poon * CDDL HEADER START
35dd46ab5SKacheong Poon *
45dd46ab5SKacheong Poon * The contents of this file are subject to the terms of the
55dd46ab5SKacheong Poon * Common Development and Distribution License (the "License").
65dd46ab5SKacheong Poon * You may not use this file except in compliance with the License.
75dd46ab5SKacheong Poon *
85dd46ab5SKacheong Poon * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95dd46ab5SKacheong Poon * or http://www.opensolaris.org/os/licensing.
105dd46ab5SKacheong Poon * See the License for the specific language governing permissions
115dd46ab5SKacheong Poon * and limitations under the License.
125dd46ab5SKacheong Poon *
135dd46ab5SKacheong Poon * When distributing Covered Code, include this CDDL HEADER in each
145dd46ab5SKacheong Poon * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155dd46ab5SKacheong Poon * If applicable, add the following below this CDDL HEADER, with the
165dd46ab5SKacheong Poon * fields enclosed by brackets "[]" replaced with your own identifying
175dd46ab5SKacheong Poon * information: Portions Copyright [yyyy] [name of copyright owner]
185dd46ab5SKacheong Poon *
195dd46ab5SKacheong Poon * CDDL HEADER END
205dd46ab5SKacheong Poon */
215dd46ab5SKacheong Poon
225dd46ab5SKacheong Poon /*
235dd46ab5SKacheong Poon * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
245dd46ab5SKacheong Poon */
255dd46ab5SKacheong Poon
265dd46ab5SKacheong Poon #include <sys/types.h>
275dd46ab5SKacheong Poon #include <sys/tihdr.h>
285dd46ab5SKacheong Poon #include <sys/policy.h>
295dd46ab5SKacheong Poon #include <sys/tsol/tnet.h>
305dd46ab5SKacheong Poon
315dd46ab5SKacheong Poon #include <inet/common.h>
325dd46ab5SKacheong Poon #include <inet/kstatcom.h>
335dd46ab5SKacheong Poon #include <inet/snmpcom.h>
345dd46ab5SKacheong Poon #include <inet/mib2.h>
355dd46ab5SKacheong Poon #include <inet/optcom.h>
365dd46ab5SKacheong Poon #include <inet/snmpcom.h>
375dd46ab5SKacheong Poon #include <inet/kstatcom.h>
385dd46ab5SKacheong Poon #include <inet/udp_impl.h>
395dd46ab5SKacheong Poon
405dd46ab5SKacheong Poon static int udp_kstat_update(kstat_t *, int);
415dd46ab5SKacheong Poon static int udp_kstat2_update(kstat_t *, int);
425dd46ab5SKacheong Poon static void udp_sum_mib(udp_stack_t *, mib2_udp_t *);
435dd46ab5SKacheong Poon static void udp_clr_stats(udp_stat_t *);
445dd46ab5SKacheong Poon static void udp_add_stats(udp_stat_counter_t *, udp_stat_t *);
455dd46ab5SKacheong Poon static void udp_add_mib(mib2_udp_t *, mib2_udp_t *);
465dd46ab5SKacheong Poon /*
475dd46ab5SKacheong Poon * return SNMP stuff in buffer in mpdata. We don't hold any lock and report
485dd46ab5SKacheong Poon * information that can be changing beneath us.
495dd46ab5SKacheong Poon */
505dd46ab5SKacheong Poon mblk_t *
udp_snmp_get(queue_t * q,mblk_t * mpctl,boolean_t legacy_req)51*6f773e29SBaban Kenkre udp_snmp_get(queue_t *q, mblk_t *mpctl, boolean_t legacy_req)
525dd46ab5SKacheong Poon {
535dd46ab5SKacheong Poon mblk_t *mpdata;
545dd46ab5SKacheong Poon mblk_t *mp_conn_ctl;
555dd46ab5SKacheong Poon mblk_t *mp_attr_ctl;
565dd46ab5SKacheong Poon mblk_t *mp6_conn_ctl;
575dd46ab5SKacheong Poon mblk_t *mp6_attr_ctl;
585dd46ab5SKacheong Poon mblk_t *mp_conn_tail;
595dd46ab5SKacheong Poon mblk_t *mp_attr_tail;
605dd46ab5SKacheong Poon mblk_t *mp6_conn_tail;
615dd46ab5SKacheong Poon mblk_t *mp6_attr_tail;
625dd46ab5SKacheong Poon struct opthdr *optp;
635dd46ab5SKacheong Poon mib2_udpEntry_t ude;
645dd46ab5SKacheong Poon mib2_udp6Entry_t ude6;
655dd46ab5SKacheong Poon mib2_transportMLPEntry_t mlp;
665dd46ab5SKacheong Poon int state;
675dd46ab5SKacheong Poon zoneid_t zoneid;
685dd46ab5SKacheong Poon int i;
695dd46ab5SKacheong Poon connf_t *connfp;
705dd46ab5SKacheong Poon conn_t *connp = Q_TO_CONN(q);
715dd46ab5SKacheong Poon int v4_conn_idx;
725dd46ab5SKacheong Poon int v6_conn_idx;
735dd46ab5SKacheong Poon boolean_t needattr;
745dd46ab5SKacheong Poon udp_t *udp;
755dd46ab5SKacheong Poon ip_stack_t *ipst = connp->conn_netstack->netstack_ip;
765dd46ab5SKacheong Poon udp_stack_t *us = connp->conn_netstack->netstack_udp;
775dd46ab5SKacheong Poon mblk_t *mp2ctl;
785dd46ab5SKacheong Poon mib2_udp_t udp_mib;
79*6f773e29SBaban Kenkre size_t udp_mib_size, ude_size, ude6_size;
80*6f773e29SBaban Kenkre
815dd46ab5SKacheong Poon
825dd46ab5SKacheong Poon /*
835dd46ab5SKacheong Poon * make a copy of the original message
845dd46ab5SKacheong Poon */
855dd46ab5SKacheong Poon mp2ctl = copymsg(mpctl);
865dd46ab5SKacheong Poon
875dd46ab5SKacheong Poon mp_conn_ctl = mp_attr_ctl = mp6_conn_ctl = NULL;
885dd46ab5SKacheong Poon if (mpctl == NULL ||
895dd46ab5SKacheong Poon (mpdata = mpctl->b_cont) == NULL ||
905dd46ab5SKacheong Poon (mp_conn_ctl = copymsg(mpctl)) == NULL ||
915dd46ab5SKacheong Poon (mp_attr_ctl = copymsg(mpctl)) == NULL ||
925dd46ab5SKacheong Poon (mp6_conn_ctl = copymsg(mpctl)) == NULL ||
935dd46ab5SKacheong Poon (mp6_attr_ctl = copymsg(mpctl)) == NULL) {
945dd46ab5SKacheong Poon freemsg(mp_conn_ctl);
955dd46ab5SKacheong Poon freemsg(mp_attr_ctl);
965dd46ab5SKacheong Poon freemsg(mp6_conn_ctl);
975dd46ab5SKacheong Poon freemsg(mpctl);
985dd46ab5SKacheong Poon freemsg(mp2ctl);
995dd46ab5SKacheong Poon return (0);
1005dd46ab5SKacheong Poon }
1015dd46ab5SKacheong Poon
1025dd46ab5SKacheong Poon zoneid = connp->conn_zoneid;
1035dd46ab5SKacheong Poon
104*6f773e29SBaban Kenkre if (legacy_req) {
105*6f773e29SBaban Kenkre udp_mib_size = LEGACY_MIB_SIZE(&udp_mib, mib2_udp_t);
106*6f773e29SBaban Kenkre ude_size = LEGACY_MIB_SIZE(&ude, mib2_udpEntry_t);
107*6f773e29SBaban Kenkre ude6_size = LEGACY_MIB_SIZE(&ude6, mib2_udp6Entry_t);
108*6f773e29SBaban Kenkre } else {
109*6f773e29SBaban Kenkre udp_mib_size = sizeof (mib2_udp_t);
110*6f773e29SBaban Kenkre ude_size = sizeof (mib2_udpEntry_t);
111*6f773e29SBaban Kenkre ude6_size = sizeof (mib2_udp6Entry_t);
112*6f773e29SBaban Kenkre }
113*6f773e29SBaban Kenkre
1145dd46ab5SKacheong Poon bzero(&udp_mib, sizeof (udp_mib));
1155dd46ab5SKacheong Poon /* fixed length structure for IPv4 and IPv6 counters */
116*6f773e29SBaban Kenkre SET_MIB(udp_mib.udpEntrySize, ude_size);
117*6f773e29SBaban Kenkre SET_MIB(udp_mib.udp6EntrySize, ude6_size);
1185dd46ab5SKacheong Poon
1195dd46ab5SKacheong Poon udp_sum_mib(us, &udp_mib);
1205dd46ab5SKacheong Poon
1215dd46ab5SKacheong Poon /*
1225dd46ab5SKacheong Poon * Synchronize 32- and 64-bit counters. Note that udpInDatagrams and
1235dd46ab5SKacheong Poon * udpOutDatagrams are not updated anywhere in UDP. The new 64 bits
1245dd46ab5SKacheong Poon * counters are used. Hence the old counters' values in us_sc_mib
1255dd46ab5SKacheong Poon * are always 0.
1265dd46ab5SKacheong Poon */
1275dd46ab5SKacheong Poon SYNC32_MIB(&udp_mib, udpInDatagrams, udpHCInDatagrams);
1285dd46ab5SKacheong Poon SYNC32_MIB(&udp_mib, udpOutDatagrams, udpHCOutDatagrams);
1295dd46ab5SKacheong Poon
1305dd46ab5SKacheong Poon optp = (struct opthdr *)&mpctl->b_rptr[sizeof (struct T_optmgmt_ack)];
1315dd46ab5SKacheong Poon optp->level = MIB2_UDP;
1325dd46ab5SKacheong Poon optp->name = 0;
133*6f773e29SBaban Kenkre (void) snmp_append_data(mpdata, (char *)&udp_mib, udp_mib_size);
1345dd46ab5SKacheong Poon optp->len = msgdsize(mpdata);
1355dd46ab5SKacheong Poon qreply(q, mpctl);
1365dd46ab5SKacheong Poon
1375dd46ab5SKacheong Poon mp_conn_tail = mp_attr_tail = mp6_conn_tail = mp6_attr_tail = NULL;
1385dd46ab5SKacheong Poon v4_conn_idx = v6_conn_idx = 0;
1395dd46ab5SKacheong Poon
1405dd46ab5SKacheong Poon for (i = 0; i < CONN_G_HASH_SIZE; i++) {
1415dd46ab5SKacheong Poon connfp = &ipst->ips_ipcl_globalhash_fanout[i];
1425dd46ab5SKacheong Poon connp = NULL;
1435dd46ab5SKacheong Poon
1445dd46ab5SKacheong Poon while ((connp = ipcl_get_next_conn(connfp, connp,
1455dd46ab5SKacheong Poon IPCL_UDPCONN))) {
1465dd46ab5SKacheong Poon udp = connp->conn_udp;
1475dd46ab5SKacheong Poon if (zoneid != connp->conn_zoneid)
1485dd46ab5SKacheong Poon continue;
1495dd46ab5SKacheong Poon
1505dd46ab5SKacheong Poon /*
1515dd46ab5SKacheong Poon * Note that the port numbers are sent in
1525dd46ab5SKacheong Poon * host byte order
1535dd46ab5SKacheong Poon */
1545dd46ab5SKacheong Poon
1555dd46ab5SKacheong Poon if (udp->udp_state == TS_UNBND)
1565dd46ab5SKacheong Poon state = MIB2_UDP_unbound;
1575dd46ab5SKacheong Poon else if (udp->udp_state == TS_IDLE)
1585dd46ab5SKacheong Poon state = MIB2_UDP_idle;
1595dd46ab5SKacheong Poon else if (udp->udp_state == TS_DATA_XFER)
1605dd46ab5SKacheong Poon state = MIB2_UDP_connected;
1615dd46ab5SKacheong Poon else
1625dd46ab5SKacheong Poon state = MIB2_UDP_unknown;
1635dd46ab5SKacheong Poon
1645dd46ab5SKacheong Poon needattr = B_FALSE;
1655dd46ab5SKacheong Poon bzero(&mlp, sizeof (mlp));
1665dd46ab5SKacheong Poon if (connp->conn_mlp_type != mlptSingle) {
1675dd46ab5SKacheong Poon if (connp->conn_mlp_type == mlptShared ||
1685dd46ab5SKacheong Poon connp->conn_mlp_type == mlptBoth)
1695dd46ab5SKacheong Poon mlp.tme_flags |= MIB2_TMEF_SHARED;
1705dd46ab5SKacheong Poon if (connp->conn_mlp_type == mlptPrivate ||
1715dd46ab5SKacheong Poon connp->conn_mlp_type == mlptBoth)
1725dd46ab5SKacheong Poon mlp.tme_flags |= MIB2_TMEF_PRIVATE;
1735dd46ab5SKacheong Poon needattr = B_TRUE;
1745dd46ab5SKacheong Poon }
1755dd46ab5SKacheong Poon if (connp->conn_anon_mlp) {
1765dd46ab5SKacheong Poon mlp.tme_flags |= MIB2_TMEF_ANONMLP;
1775dd46ab5SKacheong Poon needattr = B_TRUE;
1785dd46ab5SKacheong Poon }
1795dd46ab5SKacheong Poon switch (connp->conn_mac_mode) {
1805dd46ab5SKacheong Poon case CONN_MAC_DEFAULT:
1815dd46ab5SKacheong Poon break;
1825dd46ab5SKacheong Poon case CONN_MAC_AWARE:
1835dd46ab5SKacheong Poon mlp.tme_flags |= MIB2_TMEF_MACEXEMPT;
1845dd46ab5SKacheong Poon needattr = B_TRUE;
1855dd46ab5SKacheong Poon break;
1865dd46ab5SKacheong Poon case CONN_MAC_IMPLICIT:
1875dd46ab5SKacheong Poon mlp.tme_flags |= MIB2_TMEF_MACIMPLICIT;
1885dd46ab5SKacheong Poon needattr = B_TRUE;
1895dd46ab5SKacheong Poon break;
1905dd46ab5SKacheong Poon }
1915dd46ab5SKacheong Poon mutex_enter(&connp->conn_lock);
1925dd46ab5SKacheong Poon if (udp->udp_state == TS_DATA_XFER &&
1935dd46ab5SKacheong Poon connp->conn_ixa->ixa_tsl != NULL) {
1945dd46ab5SKacheong Poon ts_label_t *tsl;
1955dd46ab5SKacheong Poon
1965dd46ab5SKacheong Poon tsl = connp->conn_ixa->ixa_tsl;
1975dd46ab5SKacheong Poon mlp.tme_flags |= MIB2_TMEF_IS_LABELED;
1985dd46ab5SKacheong Poon mlp.tme_doi = label2doi(tsl);
1995dd46ab5SKacheong Poon mlp.tme_label = *label2bslabel(tsl);
2005dd46ab5SKacheong Poon needattr = B_TRUE;
2015dd46ab5SKacheong Poon }
2025dd46ab5SKacheong Poon mutex_exit(&connp->conn_lock);
2035dd46ab5SKacheong Poon
2045dd46ab5SKacheong Poon /*
2055dd46ab5SKacheong Poon * Create an IPv4 table entry for IPv4 entries and also
2065dd46ab5SKacheong Poon * any IPv6 entries which are bound to in6addr_any
2075dd46ab5SKacheong Poon * (i.e. anything a IPv4 peer could connect/send to).
2085dd46ab5SKacheong Poon */
2095dd46ab5SKacheong Poon if (connp->conn_ipversion == IPV4_VERSION ||
2105dd46ab5SKacheong Poon (udp->udp_state <= TS_IDLE &&
2115dd46ab5SKacheong Poon IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6))) {
2125dd46ab5SKacheong Poon ude.udpEntryInfo.ue_state = state;
2135dd46ab5SKacheong Poon /*
2145dd46ab5SKacheong Poon * If in6addr_any this will set it to
2155dd46ab5SKacheong Poon * INADDR_ANY
2165dd46ab5SKacheong Poon */
2175dd46ab5SKacheong Poon ude.udpLocalAddress = connp->conn_laddr_v4;
2185dd46ab5SKacheong Poon ude.udpLocalPort = ntohs(connp->conn_lport);
2195dd46ab5SKacheong Poon if (udp->udp_state == TS_DATA_XFER) {
2205dd46ab5SKacheong Poon /*
2215dd46ab5SKacheong Poon * Can potentially get here for
2225dd46ab5SKacheong Poon * v6 socket if another process
2235dd46ab5SKacheong Poon * (say, ping) has just done a
2245dd46ab5SKacheong Poon * sendto(), changing the state
2255dd46ab5SKacheong Poon * from the TS_IDLE above to
2265dd46ab5SKacheong Poon * TS_DATA_XFER by the time we hit
2275dd46ab5SKacheong Poon * this part of the code.
2285dd46ab5SKacheong Poon */
2295dd46ab5SKacheong Poon ude.udpEntryInfo.ue_RemoteAddress =
2305dd46ab5SKacheong Poon connp->conn_faddr_v4;
2315dd46ab5SKacheong Poon ude.udpEntryInfo.ue_RemotePort =
2325dd46ab5SKacheong Poon ntohs(connp->conn_fport);
2335dd46ab5SKacheong Poon } else {
2345dd46ab5SKacheong Poon ude.udpEntryInfo.ue_RemoteAddress = 0;
2355dd46ab5SKacheong Poon ude.udpEntryInfo.ue_RemotePort = 0;
2365dd46ab5SKacheong Poon }
2375dd46ab5SKacheong Poon
2385dd46ab5SKacheong Poon /*
2395dd46ab5SKacheong Poon * We make the assumption that all udp_t
2405dd46ab5SKacheong Poon * structs will be created within an address
2415dd46ab5SKacheong Poon * region no larger than 32-bits.
2425dd46ab5SKacheong Poon */
2435dd46ab5SKacheong Poon ude.udpInstance = (uint32_t)(uintptr_t)udp;
2445dd46ab5SKacheong Poon ude.udpCreationProcess =
2455dd46ab5SKacheong Poon (connp->conn_cpid < 0) ?
2465dd46ab5SKacheong Poon MIB2_UNKNOWN_PROCESS :
2475dd46ab5SKacheong Poon connp->conn_cpid;
2485dd46ab5SKacheong Poon ude.udpCreationTime = connp->conn_open_time;
2495dd46ab5SKacheong Poon
2505dd46ab5SKacheong Poon (void) snmp_append_data2(mp_conn_ctl->b_cont,
251*6f773e29SBaban Kenkre &mp_conn_tail, (char *)&ude, ude_size);
2525dd46ab5SKacheong Poon mlp.tme_connidx = v4_conn_idx++;
2535dd46ab5SKacheong Poon if (needattr)
2545dd46ab5SKacheong Poon (void) snmp_append_data2(
2555dd46ab5SKacheong Poon mp_attr_ctl->b_cont, &mp_attr_tail,
2565dd46ab5SKacheong Poon (char *)&mlp, sizeof (mlp));
2575dd46ab5SKacheong Poon }
2585dd46ab5SKacheong Poon if (connp->conn_ipversion == IPV6_VERSION) {
2595dd46ab5SKacheong Poon ude6.udp6EntryInfo.ue_state = state;
2605dd46ab5SKacheong Poon ude6.udp6LocalAddress = connp->conn_laddr_v6;
2615dd46ab5SKacheong Poon ude6.udp6LocalPort = ntohs(connp->conn_lport);
2625dd46ab5SKacheong Poon mutex_enter(&connp->conn_lock);
2635dd46ab5SKacheong Poon if (connp->conn_ixa->ixa_flags &
2645dd46ab5SKacheong Poon IXAF_SCOPEID_SET) {
2655dd46ab5SKacheong Poon ude6.udp6IfIndex =
2665dd46ab5SKacheong Poon connp->conn_ixa->ixa_scopeid;
2675dd46ab5SKacheong Poon } else {
2685dd46ab5SKacheong Poon ude6.udp6IfIndex = connp->conn_bound_if;
2695dd46ab5SKacheong Poon }
2705dd46ab5SKacheong Poon mutex_exit(&connp->conn_lock);
2715dd46ab5SKacheong Poon if (udp->udp_state == TS_DATA_XFER) {
2725dd46ab5SKacheong Poon ude6.udp6EntryInfo.ue_RemoteAddress =
2735dd46ab5SKacheong Poon connp->conn_faddr_v6;
2745dd46ab5SKacheong Poon ude6.udp6EntryInfo.ue_RemotePort =
2755dd46ab5SKacheong Poon ntohs(connp->conn_fport);
2765dd46ab5SKacheong Poon } else {
2775dd46ab5SKacheong Poon ude6.udp6EntryInfo.ue_RemoteAddress =
2785dd46ab5SKacheong Poon sin6_null.sin6_addr;
2795dd46ab5SKacheong Poon ude6.udp6EntryInfo.ue_RemotePort = 0;
2805dd46ab5SKacheong Poon }
2815dd46ab5SKacheong Poon /*
2825dd46ab5SKacheong Poon * We make the assumption that all udp_t
2835dd46ab5SKacheong Poon * structs will be created within an address
2845dd46ab5SKacheong Poon * region no larger than 32-bits.
2855dd46ab5SKacheong Poon */
2865dd46ab5SKacheong Poon ude6.udp6Instance = (uint32_t)(uintptr_t)udp;
2875dd46ab5SKacheong Poon ude6.udp6CreationProcess =
2885dd46ab5SKacheong Poon (connp->conn_cpid < 0) ?
2895dd46ab5SKacheong Poon MIB2_UNKNOWN_PROCESS :
2905dd46ab5SKacheong Poon connp->conn_cpid;
2915dd46ab5SKacheong Poon ude6.udp6CreationTime = connp->conn_open_time;
2925dd46ab5SKacheong Poon
2935dd46ab5SKacheong Poon (void) snmp_append_data2(mp6_conn_ctl->b_cont,
294*6f773e29SBaban Kenkre &mp6_conn_tail, (char *)&ude6, ude6_size);
2955dd46ab5SKacheong Poon mlp.tme_connidx = v6_conn_idx++;
2965dd46ab5SKacheong Poon if (needattr)
2975dd46ab5SKacheong Poon (void) snmp_append_data2(
2985dd46ab5SKacheong Poon mp6_attr_ctl->b_cont,
2995dd46ab5SKacheong Poon &mp6_attr_tail, (char *)&mlp,
3005dd46ab5SKacheong Poon sizeof (mlp));
3015dd46ab5SKacheong Poon }
3025dd46ab5SKacheong Poon }
3035dd46ab5SKacheong Poon }
3045dd46ab5SKacheong Poon
3055dd46ab5SKacheong Poon /* IPv4 UDP endpoints */
3065dd46ab5SKacheong Poon optp = (struct opthdr *)&mp_conn_ctl->b_rptr[
3075dd46ab5SKacheong Poon sizeof (struct T_optmgmt_ack)];
3085dd46ab5SKacheong Poon optp->level = MIB2_UDP;
3095dd46ab5SKacheong Poon optp->name = MIB2_UDP_ENTRY;
3105dd46ab5SKacheong Poon optp->len = msgdsize(mp_conn_ctl->b_cont);
3115dd46ab5SKacheong Poon qreply(q, mp_conn_ctl);
3125dd46ab5SKacheong Poon
3135dd46ab5SKacheong Poon /* table of MLP attributes... */
3145dd46ab5SKacheong Poon optp = (struct opthdr *)&mp_attr_ctl->b_rptr[
3155dd46ab5SKacheong Poon sizeof (struct T_optmgmt_ack)];
3165dd46ab5SKacheong Poon optp->level = MIB2_UDP;
3175dd46ab5SKacheong Poon optp->name = EXPER_XPORT_MLP;
3185dd46ab5SKacheong Poon optp->len = msgdsize(mp_attr_ctl->b_cont);
3195dd46ab5SKacheong Poon if (optp->len == 0)
3205dd46ab5SKacheong Poon freemsg(mp_attr_ctl);
3215dd46ab5SKacheong Poon else
3225dd46ab5SKacheong Poon qreply(q, mp_attr_ctl);
3235dd46ab5SKacheong Poon
3245dd46ab5SKacheong Poon /* IPv6 UDP endpoints */
3255dd46ab5SKacheong Poon optp = (struct opthdr *)&mp6_conn_ctl->b_rptr[
3265dd46ab5SKacheong Poon sizeof (struct T_optmgmt_ack)];
3275dd46ab5SKacheong Poon optp->level = MIB2_UDP6;
3285dd46ab5SKacheong Poon optp->name = MIB2_UDP6_ENTRY;
3295dd46ab5SKacheong Poon optp->len = msgdsize(mp6_conn_ctl->b_cont);
3305dd46ab5SKacheong Poon qreply(q, mp6_conn_ctl);
3315dd46ab5SKacheong Poon
3325dd46ab5SKacheong Poon /* table of MLP attributes... */
3335dd46ab5SKacheong Poon optp = (struct opthdr *)&mp6_attr_ctl->b_rptr[
3345dd46ab5SKacheong Poon sizeof (struct T_optmgmt_ack)];
3355dd46ab5SKacheong Poon optp->level = MIB2_UDP6;
3365dd46ab5SKacheong Poon optp->name = EXPER_XPORT_MLP;
3375dd46ab5SKacheong Poon optp->len = msgdsize(mp6_attr_ctl->b_cont);
3385dd46ab5SKacheong Poon if (optp->len == 0)
3395dd46ab5SKacheong Poon freemsg(mp6_attr_ctl);
3405dd46ab5SKacheong Poon else
3415dd46ab5SKacheong Poon qreply(q, mp6_attr_ctl);
3425dd46ab5SKacheong Poon
3435dd46ab5SKacheong Poon return (mp2ctl);
3445dd46ab5SKacheong Poon }
3455dd46ab5SKacheong Poon
3465dd46ab5SKacheong Poon /*
3475dd46ab5SKacheong Poon * Return 0 if invalid set request, 1 otherwise, including non-udp requests.
3485dd46ab5SKacheong Poon * NOTE: Per MIB-II, UDP has no writable data.
3495dd46ab5SKacheong Poon * TODO: If this ever actually tries to set anything, it needs to be
3505dd46ab5SKacheong Poon * to do the appropriate locking.
3515dd46ab5SKacheong Poon */
3525dd46ab5SKacheong Poon /* ARGSUSED */
3535dd46ab5SKacheong Poon int
udp_snmp_set(queue_t * q,t_scalar_t level,t_scalar_t name,uchar_t * ptr,int len)3545dd46ab5SKacheong Poon udp_snmp_set(queue_t *q, t_scalar_t level, t_scalar_t name,
3555dd46ab5SKacheong Poon uchar_t *ptr, int len)
3565dd46ab5SKacheong Poon {
3575dd46ab5SKacheong Poon switch (level) {
3585dd46ab5SKacheong Poon case MIB2_UDP:
3595dd46ab5SKacheong Poon return (0);
3605dd46ab5SKacheong Poon default:
3615dd46ab5SKacheong Poon return (1);
3625dd46ab5SKacheong Poon }
3635dd46ab5SKacheong Poon }
3645dd46ab5SKacheong Poon
3655dd46ab5SKacheong Poon void
udp_kstat_fini(netstackid_t stackid,kstat_t * ksp)3665dd46ab5SKacheong Poon udp_kstat_fini(netstackid_t stackid, kstat_t *ksp)
3675dd46ab5SKacheong Poon {
3685dd46ab5SKacheong Poon if (ksp != NULL) {
3695dd46ab5SKacheong Poon ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private);
3705dd46ab5SKacheong Poon kstat_delete_netstack(ksp, stackid);
3715dd46ab5SKacheong Poon }
3725dd46ab5SKacheong Poon }
3735dd46ab5SKacheong Poon
3745dd46ab5SKacheong Poon /*
3755dd46ab5SKacheong Poon * To add stats from one mib2_udp_t to another. Static fields are not added.
3765dd46ab5SKacheong Poon * The caller should set them up propertly.
3775dd46ab5SKacheong Poon */
3785dd46ab5SKacheong Poon static void
udp_add_mib(mib2_udp_t * from,mib2_udp_t * to)3795dd46ab5SKacheong Poon udp_add_mib(mib2_udp_t *from, mib2_udp_t *to)
3805dd46ab5SKacheong Poon {
3815dd46ab5SKacheong Poon to->udpHCInDatagrams += from->udpHCInDatagrams;
3825dd46ab5SKacheong Poon to->udpInErrors += from->udpInErrors;
3835dd46ab5SKacheong Poon to->udpHCOutDatagrams += from->udpHCOutDatagrams;
3845dd46ab5SKacheong Poon to->udpOutErrors += from->udpOutErrors;
3855dd46ab5SKacheong Poon }
3865dd46ab5SKacheong Poon
3875dd46ab5SKacheong Poon
3885dd46ab5SKacheong Poon void *
udp_kstat2_init(netstackid_t stackid)3895dd46ab5SKacheong Poon udp_kstat2_init(netstackid_t stackid)
3905dd46ab5SKacheong Poon {
3915dd46ab5SKacheong Poon kstat_t *ksp;
3925dd46ab5SKacheong Poon
3935dd46ab5SKacheong Poon udp_stat_t template = {
3945dd46ab5SKacheong Poon { "udp_sock_fallback", KSTAT_DATA_UINT64 },
3955dd46ab5SKacheong Poon { "udp_out_opt", KSTAT_DATA_UINT64 },
3965dd46ab5SKacheong Poon { "udp_out_err_notconn", KSTAT_DATA_UINT64 },
3975dd46ab5SKacheong Poon { "udp_out_err_output", KSTAT_DATA_UINT64 },
3985dd46ab5SKacheong Poon { "udp_out_err_tudr", KSTAT_DATA_UINT64 },
3995dd46ab5SKacheong Poon #ifdef DEBUG
4005dd46ab5SKacheong Poon { "udp_data_conn", KSTAT_DATA_UINT64 },
4015dd46ab5SKacheong Poon { "udp_data_notconn", KSTAT_DATA_UINT64 },
4025dd46ab5SKacheong Poon { "udp_out_lastdst", KSTAT_DATA_UINT64 },
4035dd46ab5SKacheong Poon { "udp_out_diffdst", KSTAT_DATA_UINT64 },
4045dd46ab5SKacheong Poon { "udp_out_ipv6", KSTAT_DATA_UINT64 },
4055dd46ab5SKacheong Poon { "udp_out_mapped", KSTAT_DATA_UINT64 },
4065dd46ab5SKacheong Poon { "udp_out_ipv4", KSTAT_DATA_UINT64 },
4075dd46ab5SKacheong Poon #endif
4085dd46ab5SKacheong Poon };
4095dd46ab5SKacheong Poon
4105dd46ab5SKacheong Poon ksp = kstat_create_netstack(UDP_MOD_NAME, 0, "udpstat", "net",
4115dd46ab5SKacheong Poon KSTAT_TYPE_NAMED, sizeof (template) / sizeof (kstat_named_t),
4125dd46ab5SKacheong Poon 0, stackid);
4135dd46ab5SKacheong Poon
4145dd46ab5SKacheong Poon if (ksp == NULL)
4155dd46ab5SKacheong Poon return (NULL);
4165dd46ab5SKacheong Poon
4175dd46ab5SKacheong Poon bcopy(&template, ksp->ks_data, sizeof (template));
4185dd46ab5SKacheong Poon ksp->ks_update = udp_kstat2_update;
4195dd46ab5SKacheong Poon ksp->ks_private = (void *)(uintptr_t)stackid;
4205dd46ab5SKacheong Poon
4215dd46ab5SKacheong Poon kstat_install(ksp);
4225dd46ab5SKacheong Poon return (ksp);
4235dd46ab5SKacheong Poon }
4245dd46ab5SKacheong Poon
4255dd46ab5SKacheong Poon void
udp_kstat2_fini(netstackid_t stackid,kstat_t * ksp)4265dd46ab5SKacheong Poon udp_kstat2_fini(netstackid_t stackid, kstat_t *ksp)
4275dd46ab5SKacheong Poon {
4285dd46ab5SKacheong Poon if (ksp != NULL) {
4295dd46ab5SKacheong Poon ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private);
4305dd46ab5SKacheong Poon kstat_delete_netstack(ksp, stackid);
4315dd46ab5SKacheong Poon }
4325dd46ab5SKacheong Poon }
4335dd46ab5SKacheong Poon
4345dd46ab5SKacheong Poon /*
4355dd46ab5SKacheong Poon * To copy counters from the per CPU udpp_stat_counter_t to the stack
4365dd46ab5SKacheong Poon * udp_stat_t.
4375dd46ab5SKacheong Poon */
4385dd46ab5SKacheong Poon static void
udp_add_stats(udp_stat_counter_t * from,udp_stat_t * to)4395dd46ab5SKacheong Poon udp_add_stats(udp_stat_counter_t *from, udp_stat_t *to)
4405dd46ab5SKacheong Poon {
4415dd46ab5SKacheong Poon to->udp_sock_fallback.value.ui64 += from->udp_sock_fallback;
4425dd46ab5SKacheong Poon to->udp_out_opt.value.ui64 += from->udp_out_opt;
4435dd46ab5SKacheong Poon to->udp_out_err_notconn.value.ui64 += from->udp_out_err_notconn;
4445dd46ab5SKacheong Poon to->udp_out_err_output.value.ui64 += from->udp_out_err_output;
4455dd46ab5SKacheong Poon to->udp_out_err_tudr.value.ui64 += from->udp_out_err_tudr;
4465dd46ab5SKacheong Poon #ifdef DEBUG
4475dd46ab5SKacheong Poon to->udp_data_conn.value.ui64 += from->udp_data_conn;
4485dd46ab5SKacheong Poon to->udp_data_notconn.value.ui64 += from->udp_data_notconn;
4495dd46ab5SKacheong Poon to->udp_out_lastdst.value.ui64 += from->udp_out_lastdst;
4505dd46ab5SKacheong Poon to->udp_out_diffdst.value.ui64 += from->udp_out_diffdst;
4515dd46ab5SKacheong Poon to->udp_out_ipv6.value.ui64 += from->udp_out_ipv6;
4525dd46ab5SKacheong Poon to->udp_out_mapped.value.ui64 += from->udp_out_mapped;
4535dd46ab5SKacheong Poon to->udp_out_ipv4.value.ui64 += from->udp_out_ipv4;
4545dd46ab5SKacheong Poon #endif
4555dd46ab5SKacheong Poon }
4565dd46ab5SKacheong Poon
4575dd46ab5SKacheong Poon /*
4585dd46ab5SKacheong Poon * To set all udp_stat_t counters to 0.
4595dd46ab5SKacheong Poon */
4605dd46ab5SKacheong Poon static void
udp_clr_stats(udp_stat_t * stats)4615dd46ab5SKacheong Poon udp_clr_stats(udp_stat_t *stats)
4625dd46ab5SKacheong Poon {
4635dd46ab5SKacheong Poon stats->udp_sock_fallback.value.ui64 = 0;
4645dd46ab5SKacheong Poon stats->udp_out_opt.value.ui64 = 0;
4655dd46ab5SKacheong Poon stats->udp_out_err_notconn.value.ui64 = 0;
4665dd46ab5SKacheong Poon stats->udp_out_err_output.value.ui64 = 0;
4675dd46ab5SKacheong Poon stats->udp_out_err_tudr.value.ui64 = 0;
4685dd46ab5SKacheong Poon #ifdef DEBUG
4695dd46ab5SKacheong Poon stats->udp_data_conn.value.ui64 = 0;
4705dd46ab5SKacheong Poon stats->udp_data_notconn.value.ui64 = 0;
4715dd46ab5SKacheong Poon stats->udp_out_lastdst.value.ui64 = 0;
4725dd46ab5SKacheong Poon stats->udp_out_diffdst.value.ui64 = 0;
4735dd46ab5SKacheong Poon stats->udp_out_ipv6.value.ui64 = 0;
4745dd46ab5SKacheong Poon stats->udp_out_mapped.value.ui64 = 0;
4755dd46ab5SKacheong Poon stats->udp_out_ipv4.value.ui64 = 0;
4765dd46ab5SKacheong Poon #endif
4775dd46ab5SKacheong Poon }
4785dd46ab5SKacheong Poon
4795dd46ab5SKacheong Poon int
udp_kstat2_update(kstat_t * kp,int rw)4805dd46ab5SKacheong Poon udp_kstat2_update(kstat_t *kp, int rw)
4815dd46ab5SKacheong Poon {
4825dd46ab5SKacheong Poon udp_stat_t *stats;
4835dd46ab5SKacheong Poon netstackid_t stackid = (netstackid_t)(uintptr_t)kp->ks_private;
4845dd46ab5SKacheong Poon netstack_t *ns;
4855dd46ab5SKacheong Poon udp_stack_t *us;
4865dd46ab5SKacheong Poon int i;
4875dd46ab5SKacheong Poon int cnt;
4885dd46ab5SKacheong Poon
4895dd46ab5SKacheong Poon if (rw == KSTAT_WRITE)
4905dd46ab5SKacheong Poon return (EACCES);
4915dd46ab5SKacheong Poon
4925dd46ab5SKacheong Poon ns = netstack_find_by_stackid(stackid);
4935dd46ab5SKacheong Poon if (ns == NULL)
4945dd46ab5SKacheong Poon return (-1);
4955dd46ab5SKacheong Poon us = ns->netstack_udp;
4965dd46ab5SKacheong Poon if (us == NULL) {
4975dd46ab5SKacheong Poon netstack_rele(ns);
4985dd46ab5SKacheong Poon return (-1);
4995dd46ab5SKacheong Poon }
5005dd46ab5SKacheong Poon stats = (udp_stat_t *)kp->ks_data;
5015dd46ab5SKacheong Poon udp_clr_stats(stats);
5025dd46ab5SKacheong Poon
5035dd46ab5SKacheong Poon cnt = us->us_sc_cnt;
5045dd46ab5SKacheong Poon for (i = 0; i < cnt; i++)
5055dd46ab5SKacheong Poon udp_add_stats(&us->us_sc[i]->udp_sc_stats, stats);
5065dd46ab5SKacheong Poon
5075dd46ab5SKacheong Poon netstack_rele(ns);
5085dd46ab5SKacheong Poon return (0);
5095dd46ab5SKacheong Poon }
5105dd46ab5SKacheong Poon
5115dd46ab5SKacheong Poon void *
udp_kstat_init(netstackid_t stackid)5125dd46ab5SKacheong Poon udp_kstat_init(netstackid_t stackid)
5135dd46ab5SKacheong Poon {
5145dd46ab5SKacheong Poon kstat_t *ksp;
5155dd46ab5SKacheong Poon
5165dd46ab5SKacheong Poon udp_named_kstat_t template = {
5175dd46ab5SKacheong Poon { "inDatagrams", KSTAT_DATA_UINT64, 0 },
5185dd46ab5SKacheong Poon { "inErrors", KSTAT_DATA_UINT32, 0 },
5195dd46ab5SKacheong Poon { "outDatagrams", KSTAT_DATA_UINT64, 0 },
5205dd46ab5SKacheong Poon { "entrySize", KSTAT_DATA_INT32, 0 },
5215dd46ab5SKacheong Poon { "entry6Size", KSTAT_DATA_INT32, 0 },
5225dd46ab5SKacheong Poon { "outErrors", KSTAT_DATA_UINT32, 0 },
5235dd46ab5SKacheong Poon };
5245dd46ab5SKacheong Poon
5255dd46ab5SKacheong Poon ksp = kstat_create_netstack(UDP_MOD_NAME, 0, UDP_MOD_NAME, "mib2",
5265dd46ab5SKacheong Poon KSTAT_TYPE_NAMED, NUM_OF_FIELDS(udp_named_kstat_t), 0, stackid);
5275dd46ab5SKacheong Poon
5285dd46ab5SKacheong Poon if (ksp == NULL)
5295dd46ab5SKacheong Poon return (NULL);
5305dd46ab5SKacheong Poon
5315dd46ab5SKacheong Poon template.entrySize.value.ui32 = sizeof (mib2_udpEntry_t);
5325dd46ab5SKacheong Poon template.entry6Size.value.ui32 = sizeof (mib2_udp6Entry_t);
5335dd46ab5SKacheong Poon
5345dd46ab5SKacheong Poon bcopy(&template, ksp->ks_data, sizeof (template));
5355dd46ab5SKacheong Poon ksp->ks_update = udp_kstat_update;
5365dd46ab5SKacheong Poon ksp->ks_private = (void *)(uintptr_t)stackid;
5375dd46ab5SKacheong Poon
5385dd46ab5SKacheong Poon kstat_install(ksp);
5395dd46ab5SKacheong Poon return (ksp);
5405dd46ab5SKacheong Poon }
5415dd46ab5SKacheong Poon
5425dd46ab5SKacheong Poon /*
5435dd46ab5SKacheong Poon * To sum up all MIB2 stats for a udp_stack_t from all per CPU stats. The
5445dd46ab5SKacheong Poon * caller should initialize the target mib2_udp_t properly as this function
5455dd46ab5SKacheong Poon * just adds up all the per CPU stats.
5465dd46ab5SKacheong Poon */
5475dd46ab5SKacheong Poon static void
udp_sum_mib(udp_stack_t * us,mib2_udp_t * udp_mib)5485dd46ab5SKacheong Poon udp_sum_mib(udp_stack_t *us, mib2_udp_t *udp_mib)
5495dd46ab5SKacheong Poon {
5505dd46ab5SKacheong Poon int i;
5515dd46ab5SKacheong Poon int cnt;
5525dd46ab5SKacheong Poon
5535dd46ab5SKacheong Poon cnt = us->us_sc_cnt;
5545dd46ab5SKacheong Poon for (i = 0; i < cnt; i++)
5555dd46ab5SKacheong Poon udp_add_mib(&us->us_sc[i]->udp_sc_mib, udp_mib);
5565dd46ab5SKacheong Poon }
5575dd46ab5SKacheong Poon
5585dd46ab5SKacheong Poon static int
udp_kstat_update(kstat_t * kp,int rw)5595dd46ab5SKacheong Poon udp_kstat_update(kstat_t *kp, int rw)
5605dd46ab5SKacheong Poon {
5615dd46ab5SKacheong Poon udp_named_kstat_t *udpkp;
5625dd46ab5SKacheong Poon netstackid_t stackid = (netstackid_t)(uintptr_t)kp->ks_private;
5635dd46ab5SKacheong Poon netstack_t *ns;
5645dd46ab5SKacheong Poon udp_stack_t *us;
5655dd46ab5SKacheong Poon mib2_udp_t udp_mib;
5665dd46ab5SKacheong Poon
5675dd46ab5SKacheong Poon if (rw == KSTAT_WRITE)
5685dd46ab5SKacheong Poon return (EACCES);
5695dd46ab5SKacheong Poon
5705dd46ab5SKacheong Poon ns = netstack_find_by_stackid(stackid);
5715dd46ab5SKacheong Poon if (ns == NULL)
5725dd46ab5SKacheong Poon return (-1);
5735dd46ab5SKacheong Poon us = ns->netstack_udp;
5745dd46ab5SKacheong Poon if (us == NULL) {
5755dd46ab5SKacheong Poon netstack_rele(ns);
5765dd46ab5SKacheong Poon return (-1);
5775dd46ab5SKacheong Poon }
5785dd46ab5SKacheong Poon udpkp = (udp_named_kstat_t *)kp->ks_data;
5795dd46ab5SKacheong Poon
5805dd46ab5SKacheong Poon bzero(&udp_mib, sizeof (udp_mib));
5815dd46ab5SKacheong Poon udp_sum_mib(us, &udp_mib);
5825dd46ab5SKacheong Poon
5835dd46ab5SKacheong Poon udpkp->inDatagrams.value.ui64 = udp_mib.udpHCInDatagrams;
5845dd46ab5SKacheong Poon udpkp->inErrors.value.ui32 = udp_mib.udpInErrors;
5855dd46ab5SKacheong Poon udpkp->outDatagrams.value.ui64 = udp_mib.udpHCOutDatagrams;
5865dd46ab5SKacheong Poon udpkp->outErrors.value.ui32 = udp_mib.udpOutErrors;
5875dd46ab5SKacheong Poon netstack_rele(ns);
5885dd46ab5SKacheong Poon return (0);
5895dd46ab5SKacheong Poon }
590