10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7862SRichard.Bean@Sun.COM * Common Development and Distribution License (the "License").
6*7862SRichard.Bean@Sun.COM * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*7862SRichard.Bean@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <sys/types.h>
270Sstevel@tonic-gate #include <sys/systm.h>
280Sstevel@tonic-gate #include <sys/socket.h>
290Sstevel@tonic-gate #include <netinet/in.h>
300Sstevel@tonic-gate #include <sys/modctl.h>
310Sstevel@tonic-gate #include <sys/sunddi.h>
320Sstevel@tonic-gate #include <ipp/ipp.h>
330Sstevel@tonic-gate #include <ipp/ipp_config.h>
340Sstevel@tonic-gate #include <inet/common.h>
350Sstevel@tonic-gate #include <ipp/dscpmk/dscpmk_impl.h>
360Sstevel@tonic-gate
370Sstevel@tonic-gate #define D_SM_COMMENT "IPP dscpmk marker module"
380Sstevel@tonic-gate
390Sstevel@tonic-gate /* DDI file for dscpmk ipp module */
400Sstevel@tonic-gate
410Sstevel@tonic-gate /* default dscp map - dscp unchanged */
420Sstevel@tonic-gate uint8_t default_dscp_map[DSCPMK_ARRAY_COUNT] = {
430Sstevel@tonic-gate 0, 1, 2, 3,
440Sstevel@tonic-gate 4, 5, 6, 7,
450Sstevel@tonic-gate 8, 9, 10, 11,
460Sstevel@tonic-gate 12, 13, 14, 15,
470Sstevel@tonic-gate 16, 17, 18, 19,
480Sstevel@tonic-gate 20, 21, 22, 23,
490Sstevel@tonic-gate 24, 25, 26, 27,
500Sstevel@tonic-gate 28, 29, 30, 31,
510Sstevel@tonic-gate 32, 33, 34, 35,
520Sstevel@tonic-gate 36, 37, 38, 39,
530Sstevel@tonic-gate 40, 41, 42, 43,
540Sstevel@tonic-gate 44, 45, 46, 47,
550Sstevel@tonic-gate 48, 49, 50, 51,
560Sstevel@tonic-gate 52, 53, 54, 55,
570Sstevel@tonic-gate 56, 57, 58, 59,
580Sstevel@tonic-gate 60, 61, 62, 63
590Sstevel@tonic-gate };
600Sstevel@tonic-gate
610Sstevel@tonic-gate static int dscpmk_create_action(ipp_action_id_t, nvlist_t **, ipp_flags_t);
620Sstevel@tonic-gate static int dscpmk_modify_action(ipp_action_id_t, nvlist_t **, ipp_flags_t);
630Sstevel@tonic-gate static int dscpmk_destroy_action(ipp_action_id_t, ipp_flags_t);
640Sstevel@tonic-gate static int dscpmk_info(ipp_action_id_t, int (*)(nvlist_t *, void *), void *,
650Sstevel@tonic-gate ipp_flags_t);
660Sstevel@tonic-gate static int dscpmk_invoke_action(ipp_action_id_t, ipp_packet_t *);
670Sstevel@tonic-gate
680Sstevel@tonic-gate /* Creating and updating summary stats */
690Sstevel@tonic-gate static int dscpmk_summ_statinit(ipp_action_id_t, dscpmk_data_t *);
700Sstevel@tonic-gate static int dscpmk_update_stats(ipp_stat_t *, void *, int);
710Sstevel@tonic-gate
720Sstevel@tonic-gate /* Creating and updating per-dscp stats */
730Sstevel@tonic-gate static int dscpmk_det_statinit(ipp_action_id_t, dscpmk_data_t *, int);
740Sstevel@tonic-gate static int dscpmk_update_det_stats(ipp_stat_t *, void *, int);
750Sstevel@tonic-gate
760Sstevel@tonic-gate /* Entry points for this IPP module */
770Sstevel@tonic-gate ipp_ops_t dscpmk_ops = {
780Sstevel@tonic-gate IPPO_REV,
790Sstevel@tonic-gate dscpmk_create_action, /* ippo_action_create */
800Sstevel@tonic-gate dscpmk_modify_action, /* ippo_action_modify */
810Sstevel@tonic-gate dscpmk_destroy_action, /* ippo_action_destroy */
820Sstevel@tonic-gate dscpmk_info, /* ippo_action_info */
830Sstevel@tonic-gate dscpmk_invoke_action /* ippo_action_invoke */
840Sstevel@tonic-gate };
850Sstevel@tonic-gate
860Sstevel@tonic-gate extern struct mod_ops mod_ippops;
870Sstevel@tonic-gate
880Sstevel@tonic-gate /*
890Sstevel@tonic-gate * Module linkage information for the kernel.
900Sstevel@tonic-gate */
910Sstevel@tonic-gate static struct modlipp modlipp = {
920Sstevel@tonic-gate &mod_ippops,
93*7862SRichard.Bean@Sun.COM D_SM_COMMENT,
940Sstevel@tonic-gate &dscpmk_ops
950Sstevel@tonic-gate };
960Sstevel@tonic-gate
970Sstevel@tonic-gate static struct modlinkage modlinkage = {
980Sstevel@tonic-gate MODREV_1,
990Sstevel@tonic-gate (void *)&modlipp,
1000Sstevel@tonic-gate NULL
1010Sstevel@tonic-gate };
1020Sstevel@tonic-gate
1030Sstevel@tonic-gate
1040Sstevel@tonic-gate int
_init(void)1050Sstevel@tonic-gate _init(void)
1060Sstevel@tonic-gate {
1070Sstevel@tonic-gate return (mod_install(&modlinkage));
1080Sstevel@tonic-gate }
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate int
_fini(void)1110Sstevel@tonic-gate _fini(void)
1120Sstevel@tonic-gate {
1130Sstevel@tonic-gate return (mod_remove(&modlinkage));
1140Sstevel@tonic-gate }
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate int
_info(struct modinfo * modinfop)1170Sstevel@tonic-gate _info(struct modinfo *modinfop)
1180Sstevel@tonic-gate {
1190Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop));
1200Sstevel@tonic-gate }
1210Sstevel@tonic-gate
1220Sstevel@tonic-gate static int
dscpmk_create_action(ipp_action_id_t aid,nvlist_t ** nvlpp,ipp_flags_t flags)1230Sstevel@tonic-gate dscpmk_create_action(ipp_action_id_t aid, nvlist_t **nvlpp, ipp_flags_t flags)
1240Sstevel@tonic-gate {
1250Sstevel@tonic-gate nvlist_t *nvlp;
1260Sstevel@tonic-gate dscpmk_data_t *dscpmk_data;
1270Sstevel@tonic-gate char *next_action;
1280Sstevel@tonic-gate int err, cnt;
1290Sstevel@tonic-gate int32_t *tbl;
1300Sstevel@tonic-gate uint_t nelem = DSCPMK_ARRAY_COUNT;
1310Sstevel@tonic-gate uint32_t bstats;
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate ASSERT((nvlpp != NULL) && (*nvlpp != NULL));
1340Sstevel@tonic-gate
1350Sstevel@tonic-gate nvlp = *nvlpp;
1360Sstevel@tonic-gate *nvlpp = NULL; /* nvlist should be NULL on return */
1370Sstevel@tonic-gate
1380Sstevel@tonic-gate if ((dscpmk_data = kmem_zalloc(DSCPMK_DATA_SZ, KM_NOSLEEP)) == NULL) {
1390Sstevel@tonic-gate nvlist_free(nvlp);
1400Sstevel@tonic-gate return (ENOMEM);
1410Sstevel@tonic-gate }
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate /* parse next action name */
1440Sstevel@tonic-gate if ((err = nvlist_lookup_string(nvlp, DSCPMK_NEXT_ACTION_NAME,
1450Sstevel@tonic-gate &next_action)) != 0) {
1460Sstevel@tonic-gate nvlist_free(nvlp);
1470Sstevel@tonic-gate dscpmk0dbg(("dscpmk_create_action: invalid config, " \
1480Sstevel@tonic-gate "next_action name missing\n"));
1490Sstevel@tonic-gate kmem_free(dscpmk_data, DSCPMK_DATA_SZ);
1500Sstevel@tonic-gate return (err);
1510Sstevel@tonic-gate }
1520Sstevel@tonic-gate
1530Sstevel@tonic-gate if ((dscpmk_data->next_action = ipp_action_lookup(next_action))
1540Sstevel@tonic-gate == IPP_ACTION_INVAL) {
1550Sstevel@tonic-gate nvlist_free(nvlp);
1560Sstevel@tonic-gate dscpmk0dbg(("dscpmk_create_action: next_action "\
1570Sstevel@tonic-gate "invalid\n"));
1580Sstevel@tonic-gate kmem_free(dscpmk_data, DSCPMK_DATA_SZ);
1590Sstevel@tonic-gate return (EINVAL);
1600Sstevel@tonic-gate }
1610Sstevel@tonic-gate
1620Sstevel@tonic-gate /* Fill in the default value */
1630Sstevel@tonic-gate bcopy(default_dscp_map, dscpmk_data->dscp_map,
1640Sstevel@tonic-gate sizeof (default_dscp_map));
1650Sstevel@tonic-gate /*
1660Sstevel@tonic-gate * parse dscp_map, if present. Note that the module gets
1670Sstevel@tonic-gate * the entire array with unchanged entries marked with -1.
1680Sstevel@tonic-gate */
1690Sstevel@tonic-gate if ((err = nvlist_lookup_int32_array(nvlp, DSCPMK_DSCP_MAP,
1700Sstevel@tonic-gate &tbl, &nelem)) == 0) {
1710Sstevel@tonic-gate for (cnt = 0; cnt < DSCPMK_ARRAY_COUNT; cnt++) {
1720Sstevel@tonic-gate if ((tbl[cnt] != DSCPMK_UNCHANGED_DSCP) && (tbl[cnt] !=
1730Sstevel@tonic-gate dscpmk_data->dscp_map[cnt])) {
1740Sstevel@tonic-gate dscpmk_data->dscp_map[cnt] = tbl[cnt];
1750Sstevel@tonic-gate }
1760Sstevel@tonic-gate }
1770Sstevel@tonic-gate }
1780Sstevel@tonic-gate
1790Sstevel@tonic-gate
1800Sstevel@tonic-gate /* parse summary_stats boolean */
1810Sstevel@tonic-gate if ((err = nvlist_lookup_uint32(nvlp, IPP_ACTION_STATS_ENABLE, &bstats))
1820Sstevel@tonic-gate != 0) {
1830Sstevel@tonic-gate dscpmk_data->summary_stats = B_FALSE;
1840Sstevel@tonic-gate } else {
1850Sstevel@tonic-gate dscpmk_data->summary_stats = (bstats != 0) ? B_TRUE : B_FALSE;
1860Sstevel@tonic-gate /* If stats is needed, initialize the stats structure */
1870Sstevel@tonic-gate if (dscpmk_data->summary_stats) {
1880Sstevel@tonic-gate if ((err = dscpmk_summ_statinit(aid, dscpmk_data))
1890Sstevel@tonic-gate != 0) {
1900Sstevel@tonic-gate nvlist_free(nvlp);
1910Sstevel@tonic-gate kmem_free(dscpmk_data, DSCPMK_DATA_SZ);
1920Sstevel@tonic-gate return (err);
1930Sstevel@tonic-gate }
1940Sstevel@tonic-gate }
1950Sstevel@tonic-gate }
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate /*
1980Sstevel@tonic-gate * Initialize per-dscp stats; B_FALSE in present indicates a dscp
1990Sstevel@tonic-gate * with this value (count) is not present in the map.
2000Sstevel@tonic-gate */
2010Sstevel@tonic-gate for (cnt = 0; cnt < DSCPMK_ARRAY_COUNT; cnt++) {
2020Sstevel@tonic-gate dscpmk_data->dscp_stats[cnt].present = B_FALSE;
2030Sstevel@tonic-gate dscpmk_data->dscp_stats[cnt].npackets = 0;
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate /* parse detailed_stats boolean */
2070Sstevel@tonic-gate if ((err = nvlist_lookup_uint32(nvlp, DSCPMK_DETAILED_STATS, &bstats))
2080Sstevel@tonic-gate != 0) {
2090Sstevel@tonic-gate dscpmk_data->detailed_stats = B_FALSE;
2100Sstevel@tonic-gate } else {
2110Sstevel@tonic-gate dscpmk_data->detailed_stats = (bstats != 0) ? B_TRUE : B_FALSE;
2120Sstevel@tonic-gate /* If stats is needed, initialize the stats structure */
2130Sstevel@tonic-gate if (dscpmk_data->detailed_stats) {
2140Sstevel@tonic-gate for (cnt = 0; cnt < DSCPMK_ARRAY_COUNT; cnt++) {
2150Sstevel@tonic-gate int val = dscpmk_data->dscp_map[cnt];
2160Sstevel@tonic-gate if (dscpmk_data->dscp_stats[val].present) {
2170Sstevel@tonic-gate continue;
2180Sstevel@tonic-gate }
2190Sstevel@tonic-gate dscpmk_data->dscp_stats[val].present = B_TRUE;
2200Sstevel@tonic-gate if ((err = dscpmk_det_statinit(aid, dscpmk_data,
2210Sstevel@tonic-gate val)) != 0) {
2220Sstevel@tonic-gate nvlist_free(nvlp);
2230Sstevel@tonic-gate kmem_free(dscpmk_data, DSCPMK_DATA_SZ);
2240Sstevel@tonic-gate return (err);
225*7862SRichard.Bean@Sun.COM }
2260Sstevel@tonic-gate }
2270Sstevel@tonic-gate }
2280Sstevel@tonic-gate }
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate /* Free the nvlist */
2310Sstevel@tonic-gate nvlist_free(nvlp);
2320Sstevel@tonic-gate
2330Sstevel@tonic-gate /* set action chain reference */
2340Sstevel@tonic-gate if ((err = ipp_action_ref(aid, dscpmk_data->next_action, flags)) != 0) {
2350Sstevel@tonic-gate dscpmk0dbg(("dscpmk_create_action: ipp_action_ref " \
2360Sstevel@tonic-gate "returned with error %d\n", err));
2370Sstevel@tonic-gate if (dscpmk_data->summary_stats) {
2380Sstevel@tonic-gate ipp_stat_destroy(dscpmk_data->stats);
2390Sstevel@tonic-gate }
2400Sstevel@tonic-gate if (dscpmk_data->detailed_stats) {
2410Sstevel@tonic-gate for (cnt = 0; cnt < DSCPMK_ARRAY_COUNT; cnt++) {
2420Sstevel@tonic-gate if (dscpmk_data->dscp_stats[cnt].present) {
2430Sstevel@tonic-gate ipp_stat_destroy(
2440Sstevel@tonic-gate dscpmk_data->dscp_stats[cnt].stats);
2450Sstevel@tonic-gate }
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate }
2480Sstevel@tonic-gate kmem_free(dscpmk_data, DSCPMK_DATA_SZ);
2490Sstevel@tonic-gate return (err);
2500Sstevel@tonic-gate }
2510Sstevel@tonic-gate
2520Sstevel@tonic-gate ipp_action_set_ptr(aid, (void *)dscpmk_data);
2530Sstevel@tonic-gate return (0);
2540Sstevel@tonic-gate }
2550Sstevel@tonic-gate
2560Sstevel@tonic-gate static int
dscpmk_modify_action(ipp_action_id_t aid,nvlist_t ** nvlpp,ipp_flags_t flags)2570Sstevel@tonic-gate dscpmk_modify_action(ipp_action_id_t aid, nvlist_t **nvlpp, ipp_flags_t flags)
2580Sstevel@tonic-gate {
2590Sstevel@tonic-gate nvlist_t *nvlp;
2600Sstevel@tonic-gate int err = 0, cnt;
2610Sstevel@tonic-gate uint8_t config_type;
2620Sstevel@tonic-gate char *next_action_name;
2630Sstevel@tonic-gate uint32_t bstats;
2640Sstevel@tonic-gate uint_t nelem = DSCPMK_ARRAY_COUNT;
2650Sstevel@tonic-gate int32_t *tbl;
2660Sstevel@tonic-gate ipp_action_id_t next_action;
2670Sstevel@tonic-gate dscpmk_data_t *dscpmk_data;
2680Sstevel@tonic-gate
2690Sstevel@tonic-gate ASSERT((nvlpp != NULL) && (*nvlpp != NULL));
2700Sstevel@tonic-gate
2710Sstevel@tonic-gate nvlp = *nvlpp;
2720Sstevel@tonic-gate *nvlpp = NULL; /* nvlist should be NULL when this returns */
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate if ((err = nvlist_lookup_byte(nvlp, IPP_CONFIG_TYPE, &config_type))
2750Sstevel@tonic-gate != 0) {
2760Sstevel@tonic-gate nvlist_free(nvlp);
2770Sstevel@tonic-gate dscpmk0dbg(("dscpmk_modify_action: invalid cfg. type\n"));
2780Sstevel@tonic-gate return (err);
2790Sstevel@tonic-gate }
2800Sstevel@tonic-gate
2810Sstevel@tonic-gate if (config_type != IPP_SET) {
2820Sstevel@tonic-gate nvlist_free(nvlp);
2830Sstevel@tonic-gate dscpmk0dbg(("dscpmk_modify_action: invalid cfg. type " \
2840Sstevel@tonic-gate "%d\n", config_type));
2850Sstevel@tonic-gate return (EINVAL);
2860Sstevel@tonic-gate }
2870Sstevel@tonic-gate
2880Sstevel@tonic-gate dscpmk_data = (dscpmk_data_t *)ipp_action_get_ptr(aid);
2890Sstevel@tonic-gate ASSERT(dscpmk_data != NULL);
2900Sstevel@tonic-gate
2910Sstevel@tonic-gate /* parse next action name, if present */
2920Sstevel@tonic-gate if ((err = nvlist_lookup_string(nvlp, DSCPMK_NEXT_ACTION_NAME,
2930Sstevel@tonic-gate &next_action_name)) == 0) {
2940Sstevel@tonic-gate /* lookup action name to get action id */
2950Sstevel@tonic-gate if ((next_action = ipp_action_lookup(next_action_name))
2960Sstevel@tonic-gate == IPP_ACTION_INVAL) {
2970Sstevel@tonic-gate nvlist_free(nvlp);
2980Sstevel@tonic-gate dscpmk0dbg(("dscpmk_modify_action: next_action "\
2990Sstevel@tonic-gate "invalid\n"));
3000Sstevel@tonic-gate return (EINVAL);
3010Sstevel@tonic-gate }
3020Sstevel@tonic-gate /* reference new action */
3030Sstevel@tonic-gate if ((err = ipp_action_ref(aid, next_action, flags)) != 0) {
3040Sstevel@tonic-gate nvlist_free(nvlp);
3050Sstevel@tonic-gate dscpmk0dbg(("dscpmk_modify_action: ipp_action_ref " \
3060Sstevel@tonic-gate "returned with error %d\n", err));
3070Sstevel@tonic-gate return (err);
3080Sstevel@tonic-gate }
3090Sstevel@tonic-gate /* unref old action */
3100Sstevel@tonic-gate err = ipp_action_unref(aid, dscpmk_data->next_action, flags);
3110Sstevel@tonic-gate ASSERT(err == 0);
3120Sstevel@tonic-gate dscpmk_data->next_action = next_action;
3130Sstevel@tonic-gate }
3140Sstevel@tonic-gate
3150Sstevel@tonic-gate /*
3160Sstevel@tonic-gate * parse dscp_map, if present. Note that the module gets
3170Sstevel@tonic-gate * the entire array with unchanged entries marked with -1.
3180Sstevel@tonic-gate * If this array is absent during modification, it means revert to
3190Sstevel@tonic-gate * the default table.
3200Sstevel@tonic-gate */
3210Sstevel@tonic-gate if ((err = nvlist_lookup_int32_array(nvlp, DSCPMK_DSCP_MAP,
3220Sstevel@tonic-gate &tbl, &nelem)) == 0) {
3230Sstevel@tonic-gate for (cnt = 0; cnt < DSCPMK_ARRAY_COUNT; cnt++) {
3240Sstevel@tonic-gate if ((tbl[cnt] != DSCPMK_UNCHANGED_DSCP) && (tbl[cnt] !=
3250Sstevel@tonic-gate dscpmk_data->dscp_map[cnt])) {
3260Sstevel@tonic-gate dscpmk_data->dscp_map[cnt] = tbl[cnt];
3270Sstevel@tonic-gate }
3280Sstevel@tonic-gate }
3290Sstevel@tonic-gate } else {
3300Sstevel@tonic-gate bcopy(default_dscp_map, dscpmk_data->dscp_map,
3310Sstevel@tonic-gate sizeof (default_dscp_map));
3320Sstevel@tonic-gate }
3330Sstevel@tonic-gate
3340Sstevel@tonic-gate /* parse summary_stats boolean, if present */
3350Sstevel@tonic-gate if ((err = nvlist_lookup_uint32(nvlp, IPP_ACTION_STATS_ENABLE, &bstats))
3360Sstevel@tonic-gate == 0) {
3370Sstevel@tonic-gate boolean_t val = (bstats != 0) ? B_TRUE : B_FALSE;
3380Sstevel@tonic-gate /* Turning on stats */
3390Sstevel@tonic-gate if (!dscpmk_data->summary_stats && val) {
3400Sstevel@tonic-gate if ((err = dscpmk_summ_statinit(aid, dscpmk_data))
3410Sstevel@tonic-gate != 0) {
3420Sstevel@tonic-gate nvlist_free(nvlp);
3430Sstevel@tonic-gate return (err);
3440Sstevel@tonic-gate }
3450Sstevel@tonic-gate /* Turning off stats */
3460Sstevel@tonic-gate } else if (!val && dscpmk_data->summary_stats) {
3470Sstevel@tonic-gate ipp_stat_destroy(dscpmk_data->stats);
3480Sstevel@tonic-gate
3490Sstevel@tonic-gate }
3500Sstevel@tonic-gate dscpmk_data->summary_stats = val;
3510Sstevel@tonic-gate }
3520Sstevel@tonic-gate
3530Sstevel@tonic-gate /* parse detailed_stats boolean */
3540Sstevel@tonic-gate if ((err = nvlist_lookup_uint32(nvlp, DSCPMK_DETAILED_STATS, &bstats))
3550Sstevel@tonic-gate == 0) {
3560Sstevel@tonic-gate boolean_t val = (bstats != 0) ? B_TRUE : B_FALSE;
3570Sstevel@tonic-gate if (dscpmk_data->detailed_stats && !val) {
3580Sstevel@tonic-gate for (cnt = 0; cnt < DSCPMK_ARRAY_COUNT; cnt++) {
3590Sstevel@tonic-gate if (dscpmk_data->dscp_stats[cnt].present) {
3600Sstevel@tonic-gate dscpmk_data->dscp_stats[cnt].present =
3610Sstevel@tonic-gate B_FALSE;
3620Sstevel@tonic-gate ipp_stat_destroy(dscpmk_data->
3630Sstevel@tonic-gate dscp_stats[cnt].stats);
3640Sstevel@tonic-gate }
3650Sstevel@tonic-gate }
3660Sstevel@tonic-gate }
3670Sstevel@tonic-gate dscpmk_data->detailed_stats = val;
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate /* The map might have changed */
3710Sstevel@tonic-gate if (dscpmk_data->detailed_stats) {
3720Sstevel@tonic-gate for (cnt = 0; cnt < DSCPMK_ARRAY_COUNT; cnt++) {
3730Sstevel@tonic-gate int val = dscpmk_data->dscp_map[cnt];
3740Sstevel@tonic-gate if (!dscpmk_data->dscp_stats[val].present) {
3750Sstevel@tonic-gate dscpmk_data->dscp_stats[val].present = B_TRUE;
3760Sstevel@tonic-gate if ((err = dscpmk_det_statinit(aid, dscpmk_data,
3770Sstevel@tonic-gate val)) != 0) {
3780Sstevel@tonic-gate nvlist_free(nvlp);
3790Sstevel@tonic-gate return (err);
3800Sstevel@tonic-gate }
3810Sstevel@tonic-gate }
3820Sstevel@tonic-gate }
3830Sstevel@tonic-gate }
3840Sstevel@tonic-gate
3850Sstevel@tonic-gate /* Free the nvlist */
3860Sstevel@tonic-gate nvlist_free(nvlp);
3870Sstevel@tonic-gate return (0);
3880Sstevel@tonic-gate }
3890Sstevel@tonic-gate
3900Sstevel@tonic-gate static int
dscpmk_destroy_action(ipp_action_id_t aid,ipp_flags_t flags)3910Sstevel@tonic-gate dscpmk_destroy_action(ipp_action_id_t aid, ipp_flags_t flags)
3920Sstevel@tonic-gate {
3930Sstevel@tonic-gate dscpmk_data_t *dscpmk_data;
3940Sstevel@tonic-gate int err, cnt;
3950Sstevel@tonic-gate
3960Sstevel@tonic-gate dscpmk_data = (dscpmk_data_t *)ipp_action_get_ptr(aid);
3970Sstevel@tonic-gate ASSERT(dscpmk_data != NULL);
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate /* Destroy stats, if gathered */
4000Sstevel@tonic-gate if (dscpmk_data->summary_stats) {
4010Sstevel@tonic-gate ipp_stat_destroy(dscpmk_data->stats);
4020Sstevel@tonic-gate }
4030Sstevel@tonic-gate
4040Sstevel@tonic-gate if (dscpmk_data->detailed_stats) {
4050Sstevel@tonic-gate for (cnt = 0; cnt < DSCPMK_ARRAY_COUNT; cnt++) {
4060Sstevel@tonic-gate if (dscpmk_data->dscp_stats[cnt].present) {
4070Sstevel@tonic-gate ipp_stat_destroy(dscpmk_data->dscp_stats[cnt].
4080Sstevel@tonic-gate stats);
4090Sstevel@tonic-gate }
4100Sstevel@tonic-gate }
4110Sstevel@tonic-gate }
4120Sstevel@tonic-gate
4130Sstevel@tonic-gate /* unreference the action */
4140Sstevel@tonic-gate err = ipp_action_unref(aid, dscpmk_data->next_action, flags);
4150Sstevel@tonic-gate ASSERT(err == 0);
4160Sstevel@tonic-gate
4170Sstevel@tonic-gate kmem_free(dscpmk_data, DSCPMK_DATA_SZ);
4180Sstevel@tonic-gate return (0);
4190Sstevel@tonic-gate }
4200Sstevel@tonic-gate
4210Sstevel@tonic-gate static int
dscpmk_invoke_action(ipp_action_id_t aid,ipp_packet_t * packet)4220Sstevel@tonic-gate dscpmk_invoke_action(ipp_action_id_t aid, ipp_packet_t *packet)
4230Sstevel@tonic-gate {
4240Sstevel@tonic-gate dscpmk_data_t *dscpmk_data;
4250Sstevel@tonic-gate mblk_t *mp = NULL;
4260Sstevel@tonic-gate ip_priv_t *priv;
4270Sstevel@tonic-gate int err;
4280Sstevel@tonic-gate
4290Sstevel@tonic-gate ASSERT(packet != NULL);
4300Sstevel@tonic-gate
4310Sstevel@tonic-gate /* get mblk from ipp_packet structure */
4320Sstevel@tonic-gate mp = ipp_packet_get_data(packet);
4330Sstevel@tonic-gate priv = (ip_priv_t *)ipp_packet_get_private(packet);
4340Sstevel@tonic-gate
4350Sstevel@tonic-gate dscpmk_data = (dscpmk_data_t *)ipp_action_get_ptr(aid);
4360Sstevel@tonic-gate ASSERT(dscpmk_data != NULL);
4370Sstevel@tonic-gate
4380Sstevel@tonic-gate /* dscpmk packet as configured */
4390Sstevel@tonic-gate if ((err = dscpmk_process(&mp, dscpmk_data, priv->proc)) != 0) {
4400Sstevel@tonic-gate return (err);
4410Sstevel@tonic-gate } else {
4420Sstevel@tonic-gate /* return packet with next action set */
4430Sstevel@tonic-gate return (ipp_packet_next(packet, dscpmk_data->next_action));
4440Sstevel@tonic-gate }
4450Sstevel@tonic-gate }
4460Sstevel@tonic-gate
4470Sstevel@tonic-gate static int
dscpmk_det_statinit(ipp_action_id_t aid,dscpmk_data_t * dscpmk_data,int val)4480Sstevel@tonic-gate dscpmk_det_statinit(ipp_action_id_t aid, dscpmk_data_t *dscpmk_data, int val)
4490Sstevel@tonic-gate {
4500Sstevel@tonic-gate int err = 0;
4510Sstevel@tonic-gate dscpmk_dscp_stats_t *statp;
4520Sstevel@tonic-gate char stats_string[15];
4530Sstevel@tonic-gate
4540Sstevel@tonic-gate (void) sprintf(stats_string, "dscpmk_dscp0x%x", val);
4550Sstevel@tonic-gate
4560Sstevel@tonic-gate /* install stats entry */
4570Sstevel@tonic-gate if ((err = ipp_stat_create(aid, stats_string, DSCPMK_DSCP_STATS_COUNT,
4580Sstevel@tonic-gate dscpmk_update_det_stats, dscpmk_data,
4590Sstevel@tonic-gate &dscpmk_data->dscp_stats[val].stats)) != 0) {
4600Sstevel@tonic-gate dscpmk0dbg(("dscpmk_det_statinit: ipp_stat_create returned "\
4610Sstevel@tonic-gate "with error %d\n", err));
4620Sstevel@tonic-gate return (err);
4630Sstevel@tonic-gate }
4640Sstevel@tonic-gate
4650Sstevel@tonic-gate statp = (dscpmk_dscp_stats_t *)
4660Sstevel@tonic-gate (dscpmk_data->dscp_stats[val].stats)->ipps_data;
4670Sstevel@tonic-gate ASSERT(statp != NULL);
4680Sstevel@tonic-gate
4690Sstevel@tonic-gate if ((err = ipp_stat_named_init(dscpmk_data->dscp_stats[val].stats,
4700Sstevel@tonic-gate "dscp", IPP_STAT_UINT32, &statp->dscp)) != 0) {
4710Sstevel@tonic-gate dscpmk0dbg(("dscpmk_det_statinit: ipp_stat_named_init "\
4720Sstevel@tonic-gate "returned with error %d\n", err));
4730Sstevel@tonic-gate return (err);
4740Sstevel@tonic-gate }
4750Sstevel@tonic-gate
4760Sstevel@tonic-gate if ((err = ipp_stat_named_init(dscpmk_data->dscp_stats[val].stats,
4770Sstevel@tonic-gate "npackets", IPP_STAT_UINT64, &statp->npackets)) != 0) {
4780Sstevel@tonic-gate dscpmk0dbg(("dscpmk_det_statinit: ipp_stat_named_init "\
4790Sstevel@tonic-gate "returned with error %d\n", err));
4800Sstevel@tonic-gate return (err);
4810Sstevel@tonic-gate }
4820Sstevel@tonic-gate
4830Sstevel@tonic-gate ipp_stat_install(dscpmk_data->dscp_stats[val].stats);
4840Sstevel@tonic-gate return (0);
4850Sstevel@tonic-gate }
4860Sstevel@tonic-gate
4870Sstevel@tonic-gate
4880Sstevel@tonic-gate static int
dscpmk_summ_statinit(ipp_action_id_t aid,dscpmk_data_t * dscpmk_data)4890Sstevel@tonic-gate dscpmk_summ_statinit(ipp_action_id_t aid, dscpmk_data_t *dscpmk_data)
4900Sstevel@tonic-gate {
4910Sstevel@tonic-gate int err = 0;
4920Sstevel@tonic-gate dscpmk_stat_t *statp;
4930Sstevel@tonic-gate
4940Sstevel@tonic-gate /* install stats entry */
4950Sstevel@tonic-gate if ((err = ipp_stat_create(aid, DSCPMK_STATS_STRING, DSCPMK_STATS_COUNT,
4960Sstevel@tonic-gate dscpmk_update_stats, dscpmk_data, &dscpmk_data->stats)) != 0) {
4970Sstevel@tonic-gate dscpmk0dbg(("dscpmk_create_action: ipp_stat_create returned " \
4980Sstevel@tonic-gate "with error %d\n", err));
4990Sstevel@tonic-gate return (err);
5000Sstevel@tonic-gate }
5010Sstevel@tonic-gate
5020Sstevel@tonic-gate statp = (dscpmk_stat_t *)(dscpmk_data->stats)->ipps_data;
5030Sstevel@tonic-gate ASSERT(statp != NULL);
5040Sstevel@tonic-gate
5050Sstevel@tonic-gate if ((err = ipp_stat_named_init(dscpmk_data->stats, "npackets",
5060Sstevel@tonic-gate IPP_STAT_UINT64, &statp->npackets)) != 0) {
5070Sstevel@tonic-gate dscpmk0dbg(("dscpmk_summ_statinit: ipp_stat_named_init " \
5080Sstevel@tonic-gate "returned with error %d\n", err));
5090Sstevel@tonic-gate return (err);
5100Sstevel@tonic-gate }
5110Sstevel@tonic-gate
5120Sstevel@tonic-gate if ((err = ipp_stat_named_init(dscpmk_data->stats, "dscp_changed",
5130Sstevel@tonic-gate IPP_STAT_UINT64, &statp->dscp_changed)) != 0) {
5140Sstevel@tonic-gate dscpmk0dbg(("dscpmk_summ_statinit: ipp_stat_named_init " \
5150Sstevel@tonic-gate "returned with error %d\n", err));
5160Sstevel@tonic-gate return (err);
5170Sstevel@tonic-gate }
5180Sstevel@tonic-gate
5190Sstevel@tonic-gate if ((err = ipp_stat_named_init(dscpmk_data->stats, "dscp_unchanged",
5200Sstevel@tonic-gate IPP_STAT_UINT64, &statp->dscp_unchanged)) != 0) {
5210Sstevel@tonic-gate dscpmk0dbg(("dscpmk_summ_statinit: ipp_stat_named_init " \
5220Sstevel@tonic-gate "returned with error %d\n", err));
5230Sstevel@tonic-gate return (err);
5240Sstevel@tonic-gate }
5250Sstevel@tonic-gate
5260Sstevel@tonic-gate if ((err = ipp_stat_named_init(dscpmk_data->stats, "ipackets",
5270Sstevel@tonic-gate IPP_STAT_UINT64, &statp->ipackets)) != 0) {
5280Sstevel@tonic-gate dscpmk0dbg(("dscpmk_summ_statinit: ipp_stat_named_init " \
5290Sstevel@tonic-gate "returned with error %d\n", err));
5300Sstevel@tonic-gate return (err);
5310Sstevel@tonic-gate }
5320Sstevel@tonic-gate
5330Sstevel@tonic-gate if ((err = ipp_stat_named_init(dscpmk_data->stats, "epackets",
5340Sstevel@tonic-gate IPP_STAT_UINT64, &statp->epackets)) != 0) {
5350Sstevel@tonic-gate dscpmk0dbg(("dscpmk_summ_statinit: ipp_stat_named_init " \
5360Sstevel@tonic-gate "returned with error %d\n", err));
5370Sstevel@tonic-gate return (err);
5380Sstevel@tonic-gate }
5390Sstevel@tonic-gate
5400Sstevel@tonic-gate ipp_stat_install(dscpmk_data->stats);
5410Sstevel@tonic-gate return (0);
5420Sstevel@tonic-gate }
5430Sstevel@tonic-gate
5440Sstevel@tonic-gate /* ARGSUSED */
5450Sstevel@tonic-gate static int
dscpmk_update_det_stats(ipp_stat_t * sp,void * arg,int rw)5460Sstevel@tonic-gate dscpmk_update_det_stats(ipp_stat_t *sp, void *arg, int rw)
5470Sstevel@tonic-gate {
5480Sstevel@tonic-gate dscpmk_data_t *dscpmk_data = (dscpmk_data_t *)arg;
5490Sstevel@tonic-gate dscpmk_dscp_stats_t *statp;
5500Sstevel@tonic-gate uint32_t count;
5510Sstevel@tonic-gate
5520Sstevel@tonic-gate for (count = 0; count < DSCPMK_ARRAY_COUNT; count++) {
5530Sstevel@tonic-gate if (!dscpmk_data->dscp_stats[count].present)
5540Sstevel@tonic-gate continue;
5550Sstevel@tonic-gate statp = (dscpmk_dscp_stats_t *)
5560Sstevel@tonic-gate (dscpmk_data->dscp_stats[count].stats)->ipps_data;
5570Sstevel@tonic-gate ASSERT(statp != NULL);
5580Sstevel@tonic-gate (void) ipp_stat_named_op(&statp->npackets,
5590Sstevel@tonic-gate &dscpmk_data->dscp_stats[count].npackets, rw);
5600Sstevel@tonic-gate (void) ipp_stat_named_op(&statp->dscp, &count, rw);
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate return (0);
5630Sstevel@tonic-gate }
5640Sstevel@tonic-gate
5650Sstevel@tonic-gate static int
dscpmk_update_stats(ipp_stat_t * sp,void * arg,int rw)5660Sstevel@tonic-gate dscpmk_update_stats(ipp_stat_t *sp, void *arg, int rw)
5670Sstevel@tonic-gate {
5680Sstevel@tonic-gate dscpmk_data_t *dscpmk_data = (dscpmk_data_t *)arg;
5690Sstevel@tonic-gate dscpmk_stat_t *snames = (dscpmk_stat_t *)sp->ipps_data;
5700Sstevel@tonic-gate ASSERT(dscpmk_data != NULL);
5710Sstevel@tonic-gate ASSERT(snames != NULL);
5720Sstevel@tonic-gate
5730Sstevel@tonic-gate (void) ipp_stat_named_op(&snames->npackets, &dscpmk_data->npackets, rw);
5740Sstevel@tonic-gate (void) ipp_stat_named_op(&snames->dscp_changed, &dscpmk_data->changed,
5750Sstevel@tonic-gate rw);
5760Sstevel@tonic-gate (void) ipp_stat_named_op(&snames->dscp_unchanged,
5770Sstevel@tonic-gate &dscpmk_data->unchanged, rw);
5780Sstevel@tonic-gate (void) ipp_stat_named_op(&snames->ipackets, &dscpmk_data->ipackets, rw);
5790Sstevel@tonic-gate (void) ipp_stat_named_op(&snames->epackets, &dscpmk_data->epackets, rw);
5800Sstevel@tonic-gate
5810Sstevel@tonic-gate return (0);
5820Sstevel@tonic-gate }
5830Sstevel@tonic-gate
5840Sstevel@tonic-gate /* ARGSUSED */
5850Sstevel@tonic-gate static int
dscpmk_info(ipp_action_id_t aid,int (* fn)(nvlist_t *,void *),void * arg,ipp_flags_t flags)5860Sstevel@tonic-gate dscpmk_info(ipp_action_id_t aid, int (*fn)(nvlist_t *, void *), void *arg,
5870Sstevel@tonic-gate ipp_flags_t flags)
5880Sstevel@tonic-gate {
5890Sstevel@tonic-gate nvlist_t *nvlp;
5900Sstevel@tonic-gate dscpmk_data_t *dscpmk_data;
5910Sstevel@tonic-gate char *next_action;
5920Sstevel@tonic-gate int err, cnt;
5930Sstevel@tonic-gate int32_t dscp_map[DSCPMK_ARRAY_COUNT];
5940Sstevel@tonic-gate
5950Sstevel@tonic-gate ASSERT(fn != NULL);
5960Sstevel@tonic-gate
5970Sstevel@tonic-gate dscpmk_data = (dscpmk_data_t *)ipp_action_get_ptr(aid);
5980Sstevel@tonic-gate ASSERT(dscpmk_data != NULL);
5990Sstevel@tonic-gate
6000Sstevel@tonic-gate /* allocate nvlist to be passed back */
6010Sstevel@tonic-gate if ((err = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, KM_NOSLEEP)) != 0) {
6020Sstevel@tonic-gate dscpmk0dbg(("dscpmk_info: error allocating memory\n"));
6030Sstevel@tonic-gate return (err);
6040Sstevel@tonic-gate }
6050Sstevel@tonic-gate
6060Sstevel@tonic-gate /* look up next action with the next action id */
6070Sstevel@tonic-gate if ((err = ipp_action_name(dscpmk_data->next_action,
6080Sstevel@tonic-gate &next_action)) != 0) {
6090Sstevel@tonic-gate dscpmk0dbg(("dscpmk_info: next action not available\n"));
6100Sstevel@tonic-gate nvlist_free(nvlp);
6110Sstevel@tonic-gate return (err);
6120Sstevel@tonic-gate }
6130Sstevel@tonic-gate
6140Sstevel@tonic-gate /* add next action name */
6150Sstevel@tonic-gate if ((err = nvlist_add_string(nvlp, DSCPMK_NEXT_ACTION_NAME,
6160Sstevel@tonic-gate next_action)) != 0) {
6170Sstevel@tonic-gate dscpmk0dbg(("dscpmk_info: error adding next action\n"));
6180Sstevel@tonic-gate nvlist_free(nvlp);
6190Sstevel@tonic-gate kmem_free(next_action, (strlen(next_action) + 1));
6200Sstevel@tonic-gate return (err);
6210Sstevel@tonic-gate }
6220Sstevel@tonic-gate
6230Sstevel@tonic-gate /* free action name */
6240Sstevel@tonic-gate kmem_free(next_action, (strlen(next_action) + 1));
6250Sstevel@tonic-gate
6260Sstevel@tonic-gate /* add config type */
6270Sstevel@tonic-gate if ((err = nvlist_add_byte(nvlp, IPP_CONFIG_TYPE, IPP_SET)) != 0) {
6280Sstevel@tonic-gate dscpmk0dbg(("dscpmk_info: error adding config type\n"));
6290Sstevel@tonic-gate nvlist_free(nvlp);
6300Sstevel@tonic-gate return (err);
6310Sstevel@tonic-gate }
6320Sstevel@tonic-gate
6330Sstevel@tonic-gate /* add dscp map */
6340Sstevel@tonic-gate bcopy(dscpmk_data->dscp_map, dscp_map, sizeof (dscp_map));
6350Sstevel@tonic-gate for (cnt = 0; cnt < DSCPMK_ARRAY_COUNT; cnt++) {
636*7862SRichard.Bean@Sun.COM dscp_map[cnt] = dscpmk_data->dscp_map[cnt];
6370Sstevel@tonic-gate }
6380Sstevel@tonic-gate if ((err = nvlist_add_int32_array(nvlp, DSCPMK_DSCP_MAP,
6390Sstevel@tonic-gate dscp_map, DSCPMK_ARRAY_COUNT)) != 0) {
6400Sstevel@tonic-gate dscpmk0dbg(("dscpmk_info: error adding dscp map\n"));
6410Sstevel@tonic-gate nvlist_free(nvlp);
6420Sstevel@tonic-gate return (err);
6430Sstevel@tonic-gate }
6440Sstevel@tonic-gate
6450Sstevel@tonic-gate /* add summary stats boolean */
6460Sstevel@tonic-gate if ((err = nvlist_add_uint32(nvlp, IPP_ACTION_STATS_ENABLE,
6470Sstevel@tonic-gate (dscpmk_data->summary_stats ? 1 : 0))) != 0) {
6480Sstevel@tonic-gate dscpmk0dbg(("dscpmk_info: error adding stats status\n"));
6490Sstevel@tonic-gate nvlist_free(nvlp);
6500Sstevel@tonic-gate return (err);
6510Sstevel@tonic-gate }
6520Sstevel@tonic-gate
6530Sstevel@tonic-gate /* add detailed stats boolean */
6540Sstevel@tonic-gate if ((err = nvlist_add_uint32(nvlp, DSCPMK_DETAILED_STATS,
6550Sstevel@tonic-gate (dscpmk_data->detailed_stats ? 1 : 0))) != 0) {
6560Sstevel@tonic-gate dscpmk0dbg(("dscpmk_info: error adding det stats status\n"));
6570Sstevel@tonic-gate nvlist_free(nvlp);
6580Sstevel@tonic-gate return (err);
6590Sstevel@tonic-gate }
6600Sstevel@tonic-gate
6610Sstevel@tonic-gate /* call back with nvlist */
6620Sstevel@tonic-gate err = fn(nvlp, arg);
6630Sstevel@tonic-gate
6640Sstevel@tonic-gate nvlist_free(nvlp);
6650Sstevel@tonic-gate return (err);
6660Sstevel@tonic-gate }
667