17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*39b361b2SRichard Bean  * Common Development and Distribution License (the "License").
6*39b361b2SRichard Bean  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*39b361b2SRichard Bean  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <sys/types.h>
277c478bd9Sstevel@tonic-gate #include <sys/systm.h>
287c478bd9Sstevel@tonic-gate #include <sys/socket.h>
297c478bd9Sstevel@tonic-gate #include <netinet/in.h>
307c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
317c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
327c478bd9Sstevel@tonic-gate #include <ipp/ipp.h>
337c478bd9Sstevel@tonic-gate #include <ipp/ipp_config.h>
347c478bd9Sstevel@tonic-gate #include <inet/common.h>
357c478bd9Sstevel@tonic-gate #include <ipp/dscpmk/dscpmk_impl.h>
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #define	D_SM_COMMENT	"IPP dscpmk marker module"
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate /* DDI file for dscpmk ipp module */
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate /* default dscp map - dscp unchanged */
427c478bd9Sstevel@tonic-gate uint8_t default_dscp_map[DSCPMK_ARRAY_COUNT] = {
437c478bd9Sstevel@tonic-gate 	0,	1,	2,	3,
447c478bd9Sstevel@tonic-gate 	4,	5,	6,	7,
457c478bd9Sstevel@tonic-gate 	8,	9,	10,	11,
467c478bd9Sstevel@tonic-gate 	12,	13,	14,	15,
477c478bd9Sstevel@tonic-gate 	16,	17,	18,	19,
487c478bd9Sstevel@tonic-gate 	20,	21,	22,	23,
497c478bd9Sstevel@tonic-gate 	24,	25,	26,	27,
507c478bd9Sstevel@tonic-gate 	28,	29,	30,	31,
517c478bd9Sstevel@tonic-gate 	32,	33,	34,	35,
527c478bd9Sstevel@tonic-gate 	36,	37,	38,	39,
537c478bd9Sstevel@tonic-gate 	40,	41,	42,	43,
547c478bd9Sstevel@tonic-gate 	44,	45,	46,	47,
557c478bd9Sstevel@tonic-gate 	48,	49,	50,	51,
567c478bd9Sstevel@tonic-gate 	52,	53,	54,	55,
577c478bd9Sstevel@tonic-gate 	56,	57,	58,	59,
587c478bd9Sstevel@tonic-gate 	60,	61,	62,	63
597c478bd9Sstevel@tonic-gate };
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate static int dscpmk_create_action(ipp_action_id_t, nvlist_t **, ipp_flags_t);
627c478bd9Sstevel@tonic-gate static int dscpmk_modify_action(ipp_action_id_t, nvlist_t **, ipp_flags_t);
637c478bd9Sstevel@tonic-gate static int dscpmk_destroy_action(ipp_action_id_t, ipp_flags_t);
647c478bd9Sstevel@tonic-gate static int dscpmk_info(ipp_action_id_t, int (*)(nvlist_t *, void *), void *,
657c478bd9Sstevel@tonic-gate     ipp_flags_t);
667c478bd9Sstevel@tonic-gate static int dscpmk_invoke_action(ipp_action_id_t, ipp_packet_t *);
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate /* Creating and updating summary stats */
697c478bd9Sstevel@tonic-gate static int dscpmk_summ_statinit(ipp_action_id_t, dscpmk_data_t *);
707c478bd9Sstevel@tonic-gate static int dscpmk_update_stats(ipp_stat_t *, void *, int);
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate /* Creating and updating per-dscp stats */
737c478bd9Sstevel@tonic-gate static int dscpmk_det_statinit(ipp_action_id_t, dscpmk_data_t *, int);
747c478bd9Sstevel@tonic-gate static int dscpmk_update_det_stats(ipp_stat_t *, void *, int);
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate /* Entry points for this IPP module */
777c478bd9Sstevel@tonic-gate ipp_ops_t dscpmk_ops = {
787c478bd9Sstevel@tonic-gate 	IPPO_REV,
797c478bd9Sstevel@tonic-gate 	dscpmk_create_action,	/* ippo_action_create */
807c478bd9Sstevel@tonic-gate 	dscpmk_modify_action,	/* ippo_action_modify */
817c478bd9Sstevel@tonic-gate 	dscpmk_destroy_action,	/* ippo_action_destroy */
827c478bd9Sstevel@tonic-gate 	dscpmk_info,		/* ippo_action_info */
837c478bd9Sstevel@tonic-gate 	dscpmk_invoke_action	/* ippo_action_invoke */
847c478bd9Sstevel@tonic-gate };
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate extern struct mod_ops mod_ippops;
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate /*
897c478bd9Sstevel@tonic-gate  * Module linkage information for the kernel.
907c478bd9Sstevel@tonic-gate  */
917c478bd9Sstevel@tonic-gate static struct modlipp modlipp = {
927c478bd9Sstevel@tonic-gate 	&mod_ippops,
93*39b361b2SRichard Bean 	D_SM_COMMENT,
947c478bd9Sstevel@tonic-gate 	&dscpmk_ops
957c478bd9Sstevel@tonic-gate };
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
987c478bd9Sstevel@tonic-gate 	MODREV_1,
997c478bd9Sstevel@tonic-gate 	(void *)&modlipp,
1007c478bd9Sstevel@tonic-gate 	NULL
1017c478bd9Sstevel@tonic-gate };
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate int
_init(void)1057c478bd9Sstevel@tonic-gate _init(void)
1067c478bd9Sstevel@tonic-gate {
1077c478bd9Sstevel@tonic-gate 	return (mod_install(&modlinkage));
1087c478bd9Sstevel@tonic-gate }
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate int
_fini(void)1117c478bd9Sstevel@tonic-gate _fini(void)
1127c478bd9Sstevel@tonic-gate {
1137c478bd9Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
1147c478bd9Sstevel@tonic-gate }
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)1177c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
1187c478bd9Sstevel@tonic-gate {
1197c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
1207c478bd9Sstevel@tonic-gate }
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate static int
dscpmk_create_action(ipp_action_id_t aid,nvlist_t ** nvlpp,ipp_flags_t flags)1237c478bd9Sstevel@tonic-gate dscpmk_create_action(ipp_action_id_t aid, nvlist_t **nvlpp, ipp_flags_t flags)
1247c478bd9Sstevel@tonic-gate {
1257c478bd9Sstevel@tonic-gate 	nvlist_t *nvlp;
1267c478bd9Sstevel@tonic-gate 	dscpmk_data_t *dscpmk_data;
1277c478bd9Sstevel@tonic-gate 	char *next_action;
1287c478bd9Sstevel@tonic-gate 	int err, cnt;
1297c478bd9Sstevel@tonic-gate 	int32_t *tbl;
1307c478bd9Sstevel@tonic-gate 	uint_t nelem = DSCPMK_ARRAY_COUNT;
1317c478bd9Sstevel@tonic-gate 	uint32_t bstats;
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 	ASSERT((nvlpp != NULL) && (*nvlpp != NULL));
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	nvlp = *nvlpp;
1367c478bd9Sstevel@tonic-gate 	*nvlpp = NULL;		/* nvlist should be NULL on return */
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	if ((dscpmk_data = kmem_zalloc(DSCPMK_DATA_SZ, KM_NOSLEEP)) == NULL) {
1397c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
1407c478bd9Sstevel@tonic-gate 		return (ENOMEM);
1417c478bd9Sstevel@tonic-gate 	}
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 	/* parse next action name */
1447c478bd9Sstevel@tonic-gate 	if ((err = nvlist_lookup_string(nvlp, DSCPMK_NEXT_ACTION_NAME,
1457c478bd9Sstevel@tonic-gate 	    &next_action)) != 0) {
1467c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
1477c478bd9Sstevel@tonic-gate 		dscpmk0dbg(("dscpmk_create_action: invalid config, " \
1487c478bd9Sstevel@tonic-gate 		    "next_action name missing\n"));
1497c478bd9Sstevel@tonic-gate 		kmem_free(dscpmk_data, DSCPMK_DATA_SZ);
1507c478bd9Sstevel@tonic-gate 		return (err);
1517c478bd9Sstevel@tonic-gate 	}
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	if ((dscpmk_data->next_action = ipp_action_lookup(next_action))
1547c478bd9Sstevel@tonic-gate 	    == IPP_ACTION_INVAL) {
1557c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
1567c478bd9Sstevel@tonic-gate 		dscpmk0dbg(("dscpmk_create_action: next_action "\
1577c478bd9Sstevel@tonic-gate 		    "invalid\n"));
1587c478bd9Sstevel@tonic-gate 		kmem_free(dscpmk_data, DSCPMK_DATA_SZ);
1597c478bd9Sstevel@tonic-gate 		return (EINVAL);
1607c478bd9Sstevel@tonic-gate 	}
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate 	/* Fill in the default value */
1637c478bd9Sstevel@tonic-gate 	bcopy(default_dscp_map, dscpmk_data->dscp_map,
1647c478bd9Sstevel@tonic-gate 	    sizeof (default_dscp_map));
1657c478bd9Sstevel@tonic-gate 	/*
1667c478bd9Sstevel@tonic-gate 	 * parse dscp_map, if present. Note that the module gets
1677c478bd9Sstevel@tonic-gate 	 * the entire array with unchanged entries marked with -1.
1687c478bd9Sstevel@tonic-gate 	 */
1697c478bd9Sstevel@tonic-gate 	if ((err = nvlist_lookup_int32_array(nvlp, DSCPMK_DSCP_MAP,
1707c478bd9Sstevel@tonic-gate 	    &tbl, &nelem)) == 0) {
1717c478bd9Sstevel@tonic-gate 		for (cnt = 0; cnt < DSCPMK_ARRAY_COUNT; cnt++) {
1727c478bd9Sstevel@tonic-gate 			if ((tbl[cnt] != DSCPMK_UNCHANGED_DSCP) && (tbl[cnt] !=
1737c478bd9Sstevel@tonic-gate 			    dscpmk_data->dscp_map[cnt])) {
1747c478bd9Sstevel@tonic-gate 				dscpmk_data->dscp_map[cnt] = tbl[cnt];
1757c478bd9Sstevel@tonic-gate 			}
1767c478bd9Sstevel@tonic-gate 		}
1777c478bd9Sstevel@tonic-gate 	}
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	/* parse summary_stats boolean */
1817c478bd9Sstevel@tonic-gate 	if ((err = nvlist_lookup_uint32(nvlp, IPP_ACTION_STATS_ENABLE, &bstats))
1827c478bd9Sstevel@tonic-gate 	    != 0) {
1837c478bd9Sstevel@tonic-gate 		dscpmk_data->summary_stats = B_FALSE;
1847c478bd9Sstevel@tonic-gate 	} else {
1857c478bd9Sstevel@tonic-gate 		dscpmk_data->summary_stats = (bstats != 0) ? B_TRUE : B_FALSE;
1867c478bd9Sstevel@tonic-gate 		/* If stats is needed, initialize the stats structure */
1877c478bd9Sstevel@tonic-gate 		if (dscpmk_data->summary_stats) {
1887c478bd9Sstevel@tonic-gate 			if ((err = dscpmk_summ_statinit(aid, dscpmk_data))
1897c478bd9Sstevel@tonic-gate 			    != 0) {
1907c478bd9Sstevel@tonic-gate 				nvlist_free(nvlp);
1917c478bd9Sstevel@tonic-gate 				kmem_free(dscpmk_data, DSCPMK_DATA_SZ);
1927c478bd9Sstevel@tonic-gate 				return (err);
1937c478bd9Sstevel@tonic-gate 			}
1947c478bd9Sstevel@tonic-gate 		}
1957c478bd9Sstevel@tonic-gate 	}
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	/*
1987c478bd9Sstevel@tonic-gate 	 * Initialize per-dscp stats; B_FALSE in present indicates a dscp
1997c478bd9Sstevel@tonic-gate 	 * with this value (count) is not present in the map.
2007c478bd9Sstevel@tonic-gate 	 */
2017c478bd9Sstevel@tonic-gate 	for (cnt = 0; cnt < DSCPMK_ARRAY_COUNT; cnt++) {
2027c478bd9Sstevel@tonic-gate 		dscpmk_data->dscp_stats[cnt].present = B_FALSE;
2037c478bd9Sstevel@tonic-gate 		dscpmk_data->dscp_stats[cnt].npackets = 0;
2047c478bd9Sstevel@tonic-gate 	}
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	/* parse detailed_stats boolean */
2077c478bd9Sstevel@tonic-gate 	if ((err = nvlist_lookup_uint32(nvlp, DSCPMK_DETAILED_STATS, &bstats))
2087c478bd9Sstevel@tonic-gate 	    != 0) {
2097c478bd9Sstevel@tonic-gate 		dscpmk_data->detailed_stats = B_FALSE;
2107c478bd9Sstevel@tonic-gate 	} else {
2117c478bd9Sstevel@tonic-gate 		dscpmk_data->detailed_stats = (bstats != 0) ? B_TRUE : B_FALSE;
2127c478bd9Sstevel@tonic-gate 		/* If stats is needed, initialize the stats structure */
2137c478bd9Sstevel@tonic-gate 		if (dscpmk_data->detailed_stats) {
2147c478bd9Sstevel@tonic-gate 			for (cnt = 0; cnt < DSCPMK_ARRAY_COUNT; cnt++) {
2157c478bd9Sstevel@tonic-gate 				int val = dscpmk_data->dscp_map[cnt];
2167c478bd9Sstevel@tonic-gate 				if (dscpmk_data->dscp_stats[val].present) {
2177c478bd9Sstevel@tonic-gate 					continue;
2187c478bd9Sstevel@tonic-gate 				}
2197c478bd9Sstevel@tonic-gate 				dscpmk_data->dscp_stats[val].present = B_TRUE;
2207c478bd9Sstevel@tonic-gate 				if ((err = dscpmk_det_statinit(aid, dscpmk_data,
2217c478bd9Sstevel@tonic-gate 				    val)) != 0) {
2227c478bd9Sstevel@tonic-gate 					nvlist_free(nvlp);
2237c478bd9Sstevel@tonic-gate 					kmem_free(dscpmk_data, DSCPMK_DATA_SZ);
2247c478bd9Sstevel@tonic-gate 					return (err);
225*39b361b2SRichard Bean 				}
2267c478bd9Sstevel@tonic-gate 			}
2277c478bd9Sstevel@tonic-gate 		}
2287c478bd9Sstevel@tonic-gate 	}
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	/* Free the nvlist */
2317c478bd9Sstevel@tonic-gate 	nvlist_free(nvlp);
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	/* set action chain reference */
2347c478bd9Sstevel@tonic-gate 	if ((err = ipp_action_ref(aid, dscpmk_data->next_action, flags)) != 0) {
2357c478bd9Sstevel@tonic-gate 		dscpmk0dbg(("dscpmk_create_action: ipp_action_ref " \
2367c478bd9Sstevel@tonic-gate 		    "returned with error %d\n", err));
2377c478bd9Sstevel@tonic-gate 		if (dscpmk_data->summary_stats) {
2387c478bd9Sstevel@tonic-gate 			ipp_stat_destroy(dscpmk_data->stats);
2397c478bd9Sstevel@tonic-gate 		}
2407c478bd9Sstevel@tonic-gate 		if (dscpmk_data->detailed_stats) {
2417c478bd9Sstevel@tonic-gate 			for (cnt = 0; cnt < DSCPMK_ARRAY_COUNT; cnt++) {
2427c478bd9Sstevel@tonic-gate 				if (dscpmk_data->dscp_stats[cnt].present) {
2437c478bd9Sstevel@tonic-gate 					ipp_stat_destroy(
2447c478bd9Sstevel@tonic-gate 					    dscpmk_data->dscp_stats[cnt].stats);
2457c478bd9Sstevel@tonic-gate 				}
2467c478bd9Sstevel@tonic-gate 			}
2477c478bd9Sstevel@tonic-gate 		}
2487c478bd9Sstevel@tonic-gate 		kmem_free(dscpmk_data, DSCPMK_DATA_SZ);
2497c478bd9Sstevel@tonic-gate 		return (err);
2507c478bd9Sstevel@tonic-gate 	}
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	ipp_action_set_ptr(aid, (void *)dscpmk_data);
2537c478bd9Sstevel@tonic-gate 	return (0);
2547c478bd9Sstevel@tonic-gate }
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate static int
dscpmk_modify_action(ipp_action_id_t aid,nvlist_t ** nvlpp,ipp_flags_t flags)2577c478bd9Sstevel@tonic-gate dscpmk_modify_action(ipp_action_id_t aid, nvlist_t **nvlpp, ipp_flags_t flags)
2587c478bd9Sstevel@tonic-gate {
2597c478bd9Sstevel@tonic-gate 	nvlist_t *nvlp;
2607c478bd9Sstevel@tonic-gate 	int err = 0, cnt;
2617c478bd9Sstevel@tonic-gate 	uint8_t config_type;
2627c478bd9Sstevel@tonic-gate 	char *next_action_name;
2637c478bd9Sstevel@tonic-gate 	uint32_t bstats;
2647c478bd9Sstevel@tonic-gate 	uint_t nelem = DSCPMK_ARRAY_COUNT;
2657c478bd9Sstevel@tonic-gate 	int32_t *tbl;
2667c478bd9Sstevel@tonic-gate 	ipp_action_id_t next_action;
2677c478bd9Sstevel@tonic-gate 	dscpmk_data_t *dscpmk_data;
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 	ASSERT((nvlpp != NULL) && (*nvlpp != NULL));
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 	nvlp = *nvlpp;
2727c478bd9Sstevel@tonic-gate 	*nvlpp = NULL;		/* nvlist should be NULL when this returns */
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	if ((err = nvlist_lookup_byte(nvlp, IPP_CONFIG_TYPE, &config_type))
2757c478bd9Sstevel@tonic-gate 	    != 0) {
2767c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
2777c478bd9Sstevel@tonic-gate 		dscpmk0dbg(("dscpmk_modify_action: invalid cfg. type\n"));
2787c478bd9Sstevel@tonic-gate 		return (err);
2797c478bd9Sstevel@tonic-gate 	}
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 	if (config_type != IPP_SET) {
2827c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
2837c478bd9Sstevel@tonic-gate 		dscpmk0dbg(("dscpmk_modify_action: invalid cfg. type " \
2847c478bd9Sstevel@tonic-gate 		    "%d\n", config_type));
2857c478bd9Sstevel@tonic-gate 		return (EINVAL);
2867c478bd9Sstevel@tonic-gate 	}
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 	dscpmk_data = (dscpmk_data_t *)ipp_action_get_ptr(aid);
2897c478bd9Sstevel@tonic-gate 	ASSERT(dscpmk_data != NULL);
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	/* parse next action name, if present */
2927c478bd9Sstevel@tonic-gate 	if ((err = nvlist_lookup_string(nvlp, DSCPMK_NEXT_ACTION_NAME,
2937c478bd9Sstevel@tonic-gate 	    &next_action_name)) == 0) {
2947c478bd9Sstevel@tonic-gate 		/* lookup action name to get action id */
2957c478bd9Sstevel@tonic-gate 		if ((next_action = ipp_action_lookup(next_action_name))
2967c478bd9Sstevel@tonic-gate 		    == IPP_ACTION_INVAL) {
2977c478bd9Sstevel@tonic-gate 			nvlist_free(nvlp);
2987c478bd9Sstevel@tonic-gate 			dscpmk0dbg(("dscpmk_modify_action: next_action "\
2997c478bd9Sstevel@tonic-gate 			    "invalid\n"));
3007c478bd9Sstevel@tonic-gate 			return (EINVAL);
3017c478bd9Sstevel@tonic-gate 		}
3027c478bd9Sstevel@tonic-gate 		/* reference new action */
3037c478bd9Sstevel@tonic-gate 		if ((err = ipp_action_ref(aid, next_action, flags)) != 0) {
3047c478bd9Sstevel@tonic-gate 			nvlist_free(nvlp);
3057c478bd9Sstevel@tonic-gate 			dscpmk0dbg(("dscpmk_modify_action: ipp_action_ref " \
3067c478bd9Sstevel@tonic-gate 			    "returned with error %d\n", err));
3077c478bd9Sstevel@tonic-gate 			return (err);
3087c478bd9Sstevel@tonic-gate 		}
3097c478bd9Sstevel@tonic-gate 		/* unref old action */
3107c478bd9Sstevel@tonic-gate 		err = ipp_action_unref(aid, dscpmk_data->next_action, flags);
3117c478bd9Sstevel@tonic-gate 		ASSERT(err == 0);
3127c478bd9Sstevel@tonic-gate 		dscpmk_data->next_action = next_action;
3137c478bd9Sstevel@tonic-gate 	}
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 	/*
3167c478bd9Sstevel@tonic-gate 	 * parse dscp_map, if present. Note that the module gets
3177c478bd9Sstevel@tonic-gate 	 * the entire array with unchanged entries marked with -1.
3187c478bd9Sstevel@tonic-gate 	 * If this array is absent during modification, it means revert to
3197c478bd9Sstevel@tonic-gate 	 * the default table.
3207c478bd9Sstevel@tonic-gate 	 */
3217c478bd9Sstevel@tonic-gate 	if ((err = nvlist_lookup_int32_array(nvlp, DSCPMK_DSCP_MAP,
3227c478bd9Sstevel@tonic-gate 	    &tbl, &nelem)) == 0) {
3237c478bd9Sstevel@tonic-gate 		for (cnt = 0; cnt < DSCPMK_ARRAY_COUNT; cnt++) {
3247c478bd9Sstevel@tonic-gate 			if ((tbl[cnt] != DSCPMK_UNCHANGED_DSCP) && (tbl[cnt] !=
3257c478bd9Sstevel@tonic-gate 			    dscpmk_data->dscp_map[cnt])) {
3267c478bd9Sstevel@tonic-gate 				dscpmk_data->dscp_map[cnt] = tbl[cnt];
3277c478bd9Sstevel@tonic-gate 			}
3287c478bd9Sstevel@tonic-gate 		}
3297c478bd9Sstevel@tonic-gate 	} else {
3307c478bd9Sstevel@tonic-gate 		bcopy(default_dscp_map, dscpmk_data->dscp_map,
3317c478bd9Sstevel@tonic-gate 		    sizeof (default_dscp_map));
3327c478bd9Sstevel@tonic-gate 	}
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	/* parse summary_stats boolean, if present */
3357c478bd9Sstevel@tonic-gate 	if ((err = nvlist_lookup_uint32(nvlp, IPP_ACTION_STATS_ENABLE, &bstats))
3367c478bd9Sstevel@tonic-gate 	    == 0) {
3377c478bd9Sstevel@tonic-gate 		boolean_t val = (bstats != 0) ? B_TRUE : B_FALSE;
3387c478bd9Sstevel@tonic-gate 		/* Turning on stats */
3397c478bd9Sstevel@tonic-gate 		if (!dscpmk_data->summary_stats && val) {
3407c478bd9Sstevel@tonic-gate 			if ((err = dscpmk_summ_statinit(aid, dscpmk_data))
3417c478bd9Sstevel@tonic-gate 			    != 0) {
3427c478bd9Sstevel@tonic-gate 				nvlist_free(nvlp);
3437c478bd9Sstevel@tonic-gate 				return (err);
3447c478bd9Sstevel@tonic-gate 			}
3457c478bd9Sstevel@tonic-gate 		/* Turning off stats */
3467c478bd9Sstevel@tonic-gate 		} else if (!val && dscpmk_data->summary_stats) {
3477c478bd9Sstevel@tonic-gate 			ipp_stat_destroy(dscpmk_data->stats);
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 		}
3507c478bd9Sstevel@tonic-gate 		dscpmk_data->summary_stats = val;
3517c478bd9Sstevel@tonic-gate 	}
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 	/* parse detailed_stats boolean */
3547c478bd9Sstevel@tonic-gate 	if ((err = nvlist_lookup_uint32(nvlp, DSCPMK_DETAILED_STATS, &bstats))
3557c478bd9Sstevel@tonic-gate 	    == 0) {
3567c478bd9Sstevel@tonic-gate 		boolean_t val = (bstats != 0) ? B_TRUE : B_FALSE;
3577c478bd9Sstevel@tonic-gate 		if (dscpmk_data->detailed_stats && !val) {
3587c478bd9Sstevel@tonic-gate 			for (cnt = 0; cnt < DSCPMK_ARRAY_COUNT; cnt++) {
3597c478bd9Sstevel@tonic-gate 				if (dscpmk_data->dscp_stats[cnt].present) {
3607c478bd9Sstevel@tonic-gate 					dscpmk_data->dscp_stats[cnt].present =
3617c478bd9Sstevel@tonic-gate 					    B_FALSE;
3627c478bd9Sstevel@tonic-gate 					ipp_stat_destroy(dscpmk_data->
3637c478bd9Sstevel@tonic-gate 					    dscp_stats[cnt].stats);
3647c478bd9Sstevel@tonic-gate 				}
3657c478bd9Sstevel@tonic-gate 			}
3667c478bd9Sstevel@tonic-gate 		}
3677c478bd9Sstevel@tonic-gate 		dscpmk_data->detailed_stats = val;
3687c478bd9Sstevel@tonic-gate 	}
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 	/* The map might have changed */
3717c478bd9Sstevel@tonic-gate 	if (dscpmk_data->detailed_stats) {
3727c478bd9Sstevel@tonic-gate 		for (cnt = 0; cnt < DSCPMK_ARRAY_COUNT; cnt++) {
3737c478bd9Sstevel@tonic-gate 			int val = dscpmk_data->dscp_map[cnt];
3747c478bd9Sstevel@tonic-gate 			if (!dscpmk_data->dscp_stats[val].present) {
3757c478bd9Sstevel@tonic-gate 				dscpmk_data->dscp_stats[val].present = B_TRUE;
3767c478bd9Sstevel@tonic-gate 				if ((err = dscpmk_det_statinit(aid, dscpmk_data,
3777c478bd9Sstevel@tonic-gate 				    val)) != 0) {
3787c478bd9Sstevel@tonic-gate 					nvlist_free(nvlp);
3797c478bd9Sstevel@tonic-gate 					return (err);
3807c478bd9Sstevel@tonic-gate 				}
3817c478bd9Sstevel@tonic-gate 			}
3827c478bd9Sstevel@tonic-gate 		}
3837c478bd9Sstevel@tonic-gate 	}
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	/* Free the nvlist */
3867c478bd9Sstevel@tonic-gate 	nvlist_free(nvlp);
3877c478bd9Sstevel@tonic-gate 	return (0);
3887c478bd9Sstevel@tonic-gate }
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate static int
dscpmk_destroy_action(ipp_action_id_t aid,ipp_flags_t flags)3917c478bd9Sstevel@tonic-gate dscpmk_destroy_action(ipp_action_id_t aid, ipp_flags_t flags)
3927c478bd9Sstevel@tonic-gate {
3937c478bd9Sstevel@tonic-gate 	dscpmk_data_t *dscpmk_data;
3947c478bd9Sstevel@tonic-gate 	int err, cnt;
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	dscpmk_data = (dscpmk_data_t *)ipp_action_get_ptr(aid);
3977c478bd9Sstevel@tonic-gate 	ASSERT(dscpmk_data != NULL);
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	/* Destroy stats, if gathered */
4007c478bd9Sstevel@tonic-gate 	if (dscpmk_data->summary_stats) {
4017c478bd9Sstevel@tonic-gate 		ipp_stat_destroy(dscpmk_data->stats);
4027c478bd9Sstevel@tonic-gate 	}
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	if (dscpmk_data->detailed_stats) {
4057c478bd9Sstevel@tonic-gate 		for (cnt = 0; cnt < DSCPMK_ARRAY_COUNT; cnt++) {
4067c478bd9Sstevel@tonic-gate 			if (dscpmk_data->dscp_stats[cnt].present) {
4077c478bd9Sstevel@tonic-gate 				ipp_stat_destroy(dscpmk_data->dscp_stats[cnt].
4087c478bd9Sstevel@tonic-gate 				    stats);
4097c478bd9Sstevel@tonic-gate 			}
4107c478bd9Sstevel@tonic-gate 		}
4117c478bd9Sstevel@tonic-gate 	}
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 	/* unreference the action */
4147c478bd9Sstevel@tonic-gate 	err = ipp_action_unref(aid, dscpmk_data->next_action, flags);
4157c478bd9Sstevel@tonic-gate 	ASSERT(err == 0);
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 	kmem_free(dscpmk_data, DSCPMK_DATA_SZ);
4187c478bd9Sstevel@tonic-gate 	return (0);
4197c478bd9Sstevel@tonic-gate }
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate static int
dscpmk_invoke_action(ipp_action_id_t aid,ipp_packet_t * packet)4227c478bd9Sstevel@tonic-gate dscpmk_invoke_action(ipp_action_id_t aid, ipp_packet_t *packet)
4237c478bd9Sstevel@tonic-gate {
4247c478bd9Sstevel@tonic-gate 	dscpmk_data_t *dscpmk_data;
4257c478bd9Sstevel@tonic-gate 	mblk_t *mp = NULL;
4267c478bd9Sstevel@tonic-gate 	ip_priv_t *priv;
4277c478bd9Sstevel@tonic-gate 	int err;
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate 	ASSERT(packet != NULL);
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 	/* get mblk from ipp_packet structure */
4327c478bd9Sstevel@tonic-gate 	mp = ipp_packet_get_data(packet);
4337c478bd9Sstevel@tonic-gate 	priv = (ip_priv_t *)ipp_packet_get_private(packet);
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 	dscpmk_data = (dscpmk_data_t *)ipp_action_get_ptr(aid);
4367c478bd9Sstevel@tonic-gate 	ASSERT(dscpmk_data != NULL);
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate 	/* dscpmk packet as configured */
4397c478bd9Sstevel@tonic-gate 	if ((err = dscpmk_process(&mp, dscpmk_data, priv->proc)) != 0) {
4407c478bd9Sstevel@tonic-gate 		return (err);
4417c478bd9Sstevel@tonic-gate 	} else {
4427c478bd9Sstevel@tonic-gate 		/* return packet with next action set */
4437c478bd9Sstevel@tonic-gate 		return (ipp_packet_next(packet, dscpmk_data->next_action));
4447c478bd9Sstevel@tonic-gate 	}
4457c478bd9Sstevel@tonic-gate }
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate static int
dscpmk_det_statinit(ipp_action_id_t aid,dscpmk_data_t * dscpmk_data,int val)4487c478bd9Sstevel@tonic-gate dscpmk_det_statinit(ipp_action_id_t aid, dscpmk_data_t *dscpmk_data, int val)
4497c478bd9Sstevel@tonic-gate {
4507c478bd9Sstevel@tonic-gate 	int err = 0;
4517c478bd9Sstevel@tonic-gate 	dscpmk_dscp_stats_t *statp;
4527c478bd9Sstevel@tonic-gate 	char stats_string[15];
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 	(void) sprintf(stats_string, "dscpmk_dscp0x%x", val);
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	/* install stats entry */
4577c478bd9Sstevel@tonic-gate 	if ((err = ipp_stat_create(aid, stats_string, DSCPMK_DSCP_STATS_COUNT,
4587c478bd9Sstevel@tonic-gate 	    dscpmk_update_det_stats, dscpmk_data,
4597c478bd9Sstevel@tonic-gate 	    &dscpmk_data->dscp_stats[val].stats)) != 0) {
4607c478bd9Sstevel@tonic-gate 		dscpmk0dbg(("dscpmk_det_statinit: ipp_stat_create returned "\
4617c478bd9Sstevel@tonic-gate 		    "with error %d\n", err));
4627c478bd9Sstevel@tonic-gate 		return (err);
4637c478bd9Sstevel@tonic-gate 	}
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 	statp = (dscpmk_dscp_stats_t *)
4667c478bd9Sstevel@tonic-gate 	    (dscpmk_data->dscp_stats[val].stats)->ipps_data;
4677c478bd9Sstevel@tonic-gate 	ASSERT(statp != NULL);
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 	if ((err = ipp_stat_named_init(dscpmk_data->dscp_stats[val].stats,
4707c478bd9Sstevel@tonic-gate 	    "dscp", IPP_STAT_UINT32, &statp->dscp)) != 0) {
4717c478bd9Sstevel@tonic-gate 		dscpmk0dbg(("dscpmk_det_statinit: ipp_stat_named_init "\
4727c478bd9Sstevel@tonic-gate 		    "returned with error %d\n", err));
4737c478bd9Sstevel@tonic-gate 		return (err);
4747c478bd9Sstevel@tonic-gate 	}
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 	if ((err = ipp_stat_named_init(dscpmk_data->dscp_stats[val].stats,
4777c478bd9Sstevel@tonic-gate 	    "npackets", IPP_STAT_UINT64, &statp->npackets)) != 0) {
4787c478bd9Sstevel@tonic-gate 		dscpmk0dbg(("dscpmk_det_statinit: ipp_stat_named_init "\
4797c478bd9Sstevel@tonic-gate 		    "returned with error %d\n", err));
4807c478bd9Sstevel@tonic-gate 		return (err);
4817c478bd9Sstevel@tonic-gate 	}
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate 	ipp_stat_install(dscpmk_data->dscp_stats[val].stats);
4847c478bd9Sstevel@tonic-gate 	return (0);
4857c478bd9Sstevel@tonic-gate }
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate static int
dscpmk_summ_statinit(ipp_action_id_t aid,dscpmk_data_t * dscpmk_data)4897c478bd9Sstevel@tonic-gate dscpmk_summ_statinit(ipp_action_id_t aid, dscpmk_data_t *dscpmk_data)
4907c478bd9Sstevel@tonic-gate {
4917c478bd9Sstevel@tonic-gate 	int err = 0;
4927c478bd9Sstevel@tonic-gate 	dscpmk_stat_t *statp;
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate 	/* install stats entry */
4957c478bd9Sstevel@tonic-gate 	if ((err = ipp_stat_create(aid, DSCPMK_STATS_STRING, DSCPMK_STATS_COUNT,
4967c478bd9Sstevel@tonic-gate 	    dscpmk_update_stats, dscpmk_data, &dscpmk_data->stats)) != 0) {
4977c478bd9Sstevel@tonic-gate 		dscpmk0dbg(("dscpmk_create_action: ipp_stat_create returned " \
4987c478bd9Sstevel@tonic-gate 		    "with error %d\n", err));
4997c478bd9Sstevel@tonic-gate 		return (err);
5007c478bd9Sstevel@tonic-gate 	}
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	statp = (dscpmk_stat_t *)(dscpmk_data->stats)->ipps_data;
5037c478bd9Sstevel@tonic-gate 	ASSERT(statp != NULL);
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 	if ((err = ipp_stat_named_init(dscpmk_data->stats, "npackets",
5067c478bd9Sstevel@tonic-gate 	    IPP_STAT_UINT64, &statp->npackets)) != 0) {
5077c478bd9Sstevel@tonic-gate 		dscpmk0dbg(("dscpmk_summ_statinit: ipp_stat_named_init " \
5087c478bd9Sstevel@tonic-gate 		    "returned with error %d\n", err));
5097c478bd9Sstevel@tonic-gate 		return (err);
5107c478bd9Sstevel@tonic-gate 	}
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 	if ((err = ipp_stat_named_init(dscpmk_data->stats, "dscp_changed",
5137c478bd9Sstevel@tonic-gate 	    IPP_STAT_UINT64, &statp->dscp_changed)) != 0) {
5147c478bd9Sstevel@tonic-gate 		dscpmk0dbg(("dscpmk_summ_statinit: ipp_stat_named_init " \
5157c478bd9Sstevel@tonic-gate 		    "returned with error %d\n", err));
5167c478bd9Sstevel@tonic-gate 		return (err);
5177c478bd9Sstevel@tonic-gate 	}
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 	if ((err = ipp_stat_named_init(dscpmk_data->stats, "dscp_unchanged",
5207c478bd9Sstevel@tonic-gate 	    IPP_STAT_UINT64, &statp->dscp_unchanged)) != 0) {
5217c478bd9Sstevel@tonic-gate 		dscpmk0dbg(("dscpmk_summ_statinit: ipp_stat_named_init " \
5227c478bd9Sstevel@tonic-gate 		    "returned with error %d\n", err));
5237c478bd9Sstevel@tonic-gate 		return (err);
5247c478bd9Sstevel@tonic-gate 	}
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 	if ((err = ipp_stat_named_init(dscpmk_data->stats, "ipackets",
5277c478bd9Sstevel@tonic-gate 	    IPP_STAT_UINT64, &statp->ipackets)) != 0) {
5287c478bd9Sstevel@tonic-gate 		dscpmk0dbg(("dscpmk_summ_statinit: ipp_stat_named_init " \
5297c478bd9Sstevel@tonic-gate 		    "returned with error %d\n", err));
5307c478bd9Sstevel@tonic-gate 		return (err);
5317c478bd9Sstevel@tonic-gate 	}
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 	if ((err = ipp_stat_named_init(dscpmk_data->stats, "epackets",
5347c478bd9Sstevel@tonic-gate 	    IPP_STAT_UINT64, &statp->epackets)) != 0) {
5357c478bd9Sstevel@tonic-gate 		dscpmk0dbg(("dscpmk_summ_statinit: ipp_stat_named_init " \
5367c478bd9Sstevel@tonic-gate 		    "returned with error %d\n", err));
5377c478bd9Sstevel@tonic-gate 		return (err);
5387c478bd9Sstevel@tonic-gate 	}
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 	ipp_stat_install(dscpmk_data->stats);
5417c478bd9Sstevel@tonic-gate 	return (0);
5427c478bd9Sstevel@tonic-gate }
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate /* ARGSUSED */
5457c478bd9Sstevel@tonic-gate static int
dscpmk_update_det_stats(ipp_stat_t * sp,void * arg,int rw)5467c478bd9Sstevel@tonic-gate dscpmk_update_det_stats(ipp_stat_t *sp, void *arg, int rw)
5477c478bd9Sstevel@tonic-gate {
5487c478bd9Sstevel@tonic-gate 	dscpmk_data_t *dscpmk_data = (dscpmk_data_t *)arg;
5497c478bd9Sstevel@tonic-gate 	dscpmk_dscp_stats_t *statp;
5507c478bd9Sstevel@tonic-gate 	uint32_t count;
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate 	for (count = 0; count < DSCPMK_ARRAY_COUNT; count++) {
5537c478bd9Sstevel@tonic-gate 		if (!dscpmk_data->dscp_stats[count].present)
5547c478bd9Sstevel@tonic-gate 			continue;
5557c478bd9Sstevel@tonic-gate 		statp = (dscpmk_dscp_stats_t *)
5567c478bd9Sstevel@tonic-gate 		    (dscpmk_data->dscp_stats[count].stats)->ipps_data;
5577c478bd9Sstevel@tonic-gate 		ASSERT(statp != NULL);
5587c478bd9Sstevel@tonic-gate 		(void) ipp_stat_named_op(&statp->npackets,
5597c478bd9Sstevel@tonic-gate 		    &dscpmk_data->dscp_stats[count].npackets, rw);
5607c478bd9Sstevel@tonic-gate 		(void) ipp_stat_named_op(&statp->dscp, &count, rw);
5617c478bd9Sstevel@tonic-gate 	}
5627c478bd9Sstevel@tonic-gate 	return (0);
5637c478bd9Sstevel@tonic-gate }
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate static int
dscpmk_update_stats(ipp_stat_t * sp,void * arg,int rw)5667c478bd9Sstevel@tonic-gate dscpmk_update_stats(ipp_stat_t *sp, void *arg, int rw)
5677c478bd9Sstevel@tonic-gate {
5687c478bd9Sstevel@tonic-gate 	dscpmk_data_t *dscpmk_data = (dscpmk_data_t *)arg;
5697c478bd9Sstevel@tonic-gate 	dscpmk_stat_t *snames = (dscpmk_stat_t *)sp->ipps_data;
5707c478bd9Sstevel@tonic-gate 	ASSERT(dscpmk_data != NULL);
5717c478bd9Sstevel@tonic-gate 	ASSERT(snames != NULL);
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate 	(void) ipp_stat_named_op(&snames->npackets, &dscpmk_data->npackets, rw);
5747c478bd9Sstevel@tonic-gate 	(void) ipp_stat_named_op(&snames->dscp_changed, &dscpmk_data->changed,
5757c478bd9Sstevel@tonic-gate 	    rw);
5767c478bd9Sstevel@tonic-gate 	(void) ipp_stat_named_op(&snames->dscp_unchanged,
5777c478bd9Sstevel@tonic-gate 	    &dscpmk_data->unchanged, rw);
5787c478bd9Sstevel@tonic-gate 	(void) ipp_stat_named_op(&snames->ipackets, &dscpmk_data->ipackets, rw);
5797c478bd9Sstevel@tonic-gate 	(void) ipp_stat_named_op(&snames->epackets, &dscpmk_data->epackets, rw);
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate 	return (0);
5827c478bd9Sstevel@tonic-gate }
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate /* ARGSUSED */
5857c478bd9Sstevel@tonic-gate static int
dscpmk_info(ipp_action_id_t aid,int (* fn)(nvlist_t *,void *),void * arg,ipp_flags_t flags)5867c478bd9Sstevel@tonic-gate dscpmk_info(ipp_action_id_t aid, int (*fn)(nvlist_t *, void *), void *arg,
5877c478bd9Sstevel@tonic-gate     ipp_flags_t flags)
5887c478bd9Sstevel@tonic-gate {
5897c478bd9Sstevel@tonic-gate 	nvlist_t *nvlp;
5907c478bd9Sstevel@tonic-gate 	dscpmk_data_t *dscpmk_data;
5917c478bd9Sstevel@tonic-gate 	char *next_action;
5927c478bd9Sstevel@tonic-gate 	int err, cnt;
5937c478bd9Sstevel@tonic-gate 	int32_t dscp_map[DSCPMK_ARRAY_COUNT];
5947c478bd9Sstevel@tonic-gate 
5957c478bd9Sstevel@tonic-gate 	ASSERT(fn != NULL);
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate 	dscpmk_data = (dscpmk_data_t *)ipp_action_get_ptr(aid);
5987c478bd9Sstevel@tonic-gate 	ASSERT(dscpmk_data != NULL);
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate 	/* allocate nvlist to be passed back */
6017c478bd9Sstevel@tonic-gate 	if ((err = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, KM_NOSLEEP)) != 0) {
6027c478bd9Sstevel@tonic-gate 		dscpmk0dbg(("dscpmk_info: error allocating memory\n"));
6037c478bd9Sstevel@tonic-gate 		return (err);
6047c478bd9Sstevel@tonic-gate 	}
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate 	/* look up next action with the next action id */
6077c478bd9Sstevel@tonic-gate 	if ((err = ipp_action_name(dscpmk_data->next_action,
6087c478bd9Sstevel@tonic-gate 	    &next_action)) != 0) {
6097c478bd9Sstevel@tonic-gate 		dscpmk0dbg(("dscpmk_info: next action not available\n"));
6107c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
6117c478bd9Sstevel@tonic-gate 		return (err);
6127c478bd9Sstevel@tonic-gate 	}
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate 	/* add next action name */
6157c478bd9Sstevel@tonic-gate 	if ((err = nvlist_add_string(nvlp, DSCPMK_NEXT_ACTION_NAME,
6167c478bd9Sstevel@tonic-gate 	    next_action)) != 0) {
6177c478bd9Sstevel@tonic-gate 		dscpmk0dbg(("dscpmk_info: error adding next action\n"));
6187c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
6197c478bd9Sstevel@tonic-gate 		kmem_free(next_action, (strlen(next_action) + 1));
6207c478bd9Sstevel@tonic-gate 		return (err);
6217c478bd9Sstevel@tonic-gate 	}
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate 	/* free action name */
6247c478bd9Sstevel@tonic-gate 	kmem_free(next_action, (strlen(next_action) + 1));
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 	/* add config type */
6277c478bd9Sstevel@tonic-gate 	if ((err = nvlist_add_byte(nvlp, IPP_CONFIG_TYPE, IPP_SET)) != 0) {
6287c478bd9Sstevel@tonic-gate 		dscpmk0dbg(("dscpmk_info: error adding config type\n"));
6297c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
6307c478bd9Sstevel@tonic-gate 		return (err);
6317c478bd9Sstevel@tonic-gate 	}
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate 	/* add dscp map */
6347c478bd9Sstevel@tonic-gate 	bcopy(dscpmk_data->dscp_map, dscp_map, sizeof (dscp_map));
6357c478bd9Sstevel@tonic-gate 	for (cnt = 0; cnt < DSCPMK_ARRAY_COUNT; cnt++) {
636*39b361b2SRichard Bean 		dscp_map[cnt] = dscpmk_data->dscp_map[cnt];
6377c478bd9Sstevel@tonic-gate 	}
6387c478bd9Sstevel@tonic-gate 	if ((err = nvlist_add_int32_array(nvlp, DSCPMK_DSCP_MAP,
6397c478bd9Sstevel@tonic-gate 	    dscp_map, DSCPMK_ARRAY_COUNT)) != 0) {
6407c478bd9Sstevel@tonic-gate 		dscpmk0dbg(("dscpmk_info: error adding dscp map\n"));
6417c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
6427c478bd9Sstevel@tonic-gate 		return (err);
6437c478bd9Sstevel@tonic-gate 	}
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 	/* add summary stats boolean */
6467c478bd9Sstevel@tonic-gate 	if ((err = nvlist_add_uint32(nvlp, IPP_ACTION_STATS_ENABLE,
6477c478bd9Sstevel@tonic-gate 	    (dscpmk_data->summary_stats ? 1 : 0))) != 0) {
6487c478bd9Sstevel@tonic-gate 		dscpmk0dbg(("dscpmk_info: error adding stats status\n"));
6497c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
6507c478bd9Sstevel@tonic-gate 		return (err);
6517c478bd9Sstevel@tonic-gate 	}
6527c478bd9Sstevel@tonic-gate 
6537c478bd9Sstevel@tonic-gate 	/* add detailed stats boolean */
6547c478bd9Sstevel@tonic-gate 	if ((err = nvlist_add_uint32(nvlp, DSCPMK_DETAILED_STATS,
6557c478bd9Sstevel@tonic-gate 	    (dscpmk_data->detailed_stats ? 1 : 0))) != 0) {
6567c478bd9Sstevel@tonic-gate 		dscpmk0dbg(("dscpmk_info: error adding det stats status\n"));
6577c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
6587c478bd9Sstevel@tonic-gate 		return (err);
6597c478bd9Sstevel@tonic-gate 	}
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate 	/* call back with nvlist */
6627c478bd9Sstevel@tonic-gate 	err = fn(nvlp, arg);
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 	nvlist_free(nvlp);
6657c478bd9Sstevel@tonic-gate 	return (err);
6667c478bd9Sstevel@tonic-gate }
667