xref: /illumos-gate/usr/src/uts/common/ipp/dlcosmk/dlcosmkddi.c (revision 39b361b2ebefcef5612a54ae5cbd2179e19be296)
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/atomic.h>
287c478bd9Sstevel@tonic-gate #include <sys/systm.h>
297c478bd9Sstevel@tonic-gate #include <sys/socket.h>
307c478bd9Sstevel@tonic-gate #include <netinet/in.h>
317c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
327c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
337c478bd9Sstevel@tonic-gate #include <ipp/ipp.h>
347c478bd9Sstevel@tonic-gate #include <ipp/ipp_config.h>
357c478bd9Sstevel@tonic-gate #include <inet/common.h>
367c478bd9Sstevel@tonic-gate #include <ipp/dlcosmk/dlcosmk_impl.h>
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate #define	D_SM_COMMENT	"IPP dlcosmk marker module"
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate /* DDI file for dlcosmk ipp module */
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate static int dlcosmk_create_action(ipp_action_id_t, nvlist_t **, ipp_flags_t);
437c478bd9Sstevel@tonic-gate static int dlcosmk_modify_action(ipp_action_id_t, nvlist_t **, ipp_flags_t);
447c478bd9Sstevel@tonic-gate static int dlcosmk_destroy_action(ipp_action_id_t, ipp_flags_t);
457c478bd9Sstevel@tonic-gate static int dlcosmk_info(ipp_action_id_t, int (*)(nvlist_t *, void *), void *,
467c478bd9Sstevel@tonic-gate     ipp_flags_t);
477c478bd9Sstevel@tonic-gate static int dlcosmk_invoke_action(ipp_action_id_t, ipp_packet_t *);
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate static int dlcosmk_statinit(ipp_action_id_t, dlcosmk_data_t *);
507c478bd9Sstevel@tonic-gate static int dlcosmk_update_stats(ipp_stat_t *, void *, int);
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate /* Entry points for this IPP module */
537c478bd9Sstevel@tonic-gate ipp_ops_t dlcosmk_ops = {
547c478bd9Sstevel@tonic-gate 	IPPO_REV,
557c478bd9Sstevel@tonic-gate 	dlcosmk_create_action,	/* ippo_action_create */
567c478bd9Sstevel@tonic-gate 	dlcosmk_modify_action,	/* ippo_action_modify */
577c478bd9Sstevel@tonic-gate 	dlcosmk_destroy_action,	/* ippo_action_destroy */
587c478bd9Sstevel@tonic-gate 	dlcosmk_info,		/* ippo_action_info */
597c478bd9Sstevel@tonic-gate 	dlcosmk_invoke_action	/* ippo_action_invoke */
607c478bd9Sstevel@tonic-gate };
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate extern struct mod_ops mod_ippops;
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate /*
657c478bd9Sstevel@tonic-gate  * Module linkage information for the kernel.
667c478bd9Sstevel@tonic-gate  */
677c478bd9Sstevel@tonic-gate static struct modlipp modlipp = {
687c478bd9Sstevel@tonic-gate 	&mod_ippops,
69*39b361b2SRichard Bean 	D_SM_COMMENT,
707c478bd9Sstevel@tonic-gate 	&dlcosmk_ops
717c478bd9Sstevel@tonic-gate };
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
747c478bd9Sstevel@tonic-gate 	MODREV_1,
757c478bd9Sstevel@tonic-gate 	(void *)&modlipp,
767c478bd9Sstevel@tonic-gate 	NULL
777c478bd9Sstevel@tonic-gate };
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate int
_init(void)817c478bd9Sstevel@tonic-gate _init(void)
827c478bd9Sstevel@tonic-gate {
837c478bd9Sstevel@tonic-gate 	return (mod_install(&modlinkage));
847c478bd9Sstevel@tonic-gate }
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate int
_fini(void)877c478bd9Sstevel@tonic-gate _fini(void)
887c478bd9Sstevel@tonic-gate {
897c478bd9Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
907c478bd9Sstevel@tonic-gate }
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)937c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
947c478bd9Sstevel@tonic-gate {
957c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
967c478bd9Sstevel@tonic-gate }
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate static int
dlcosmk_create_action(ipp_action_id_t aid,nvlist_t ** nvlpp,ipp_flags_t flags)997c478bd9Sstevel@tonic-gate dlcosmk_create_action(ipp_action_id_t aid, nvlist_t **nvlpp,
1007c478bd9Sstevel@tonic-gate     ipp_flags_t flags)
1017c478bd9Sstevel@tonic-gate {
1027c478bd9Sstevel@tonic-gate 	nvlist_t *nvlp;
1037c478bd9Sstevel@tonic-gate 	dlcosmk_data_t *dlcosmk_data;
1047c478bd9Sstevel@tonic-gate 	char *next_action;
1057c478bd9Sstevel@tonic-gate 	int err;
1067c478bd9Sstevel@tonic-gate 	uint32_t bstats, param;
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	ASSERT((nvlpp != NULL) && (*nvlpp != NULL));
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 	nvlp = *nvlpp;
1117c478bd9Sstevel@tonic-gate 	*nvlpp = NULL;		/* nvlist should be NULL on return */
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	if ((dlcosmk_data = kmem_zalloc(DLCOSMK_DATA_SZ, KM_NOSLEEP)) == NULL) {
1147c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
1157c478bd9Sstevel@tonic-gate 		return (ENOMEM);
1167c478bd9Sstevel@tonic-gate 	}
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 	/* parse next action name */
1197c478bd9Sstevel@tonic-gate 	if ((err = nvlist_lookup_string(nvlp, DLCOSMK_NEXT_ACTION_NAME,
1207c478bd9Sstevel@tonic-gate 	    &next_action)) != 0) {
1217c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
1227c478bd9Sstevel@tonic-gate 		dlcosmk0dbg(("dlcosmk_create_action: invalid config, "\
1237c478bd9Sstevel@tonic-gate 		    "next_action name missing\n"));
1247c478bd9Sstevel@tonic-gate 		kmem_free(dlcosmk_data, DLCOSMK_DATA_SZ);
1257c478bd9Sstevel@tonic-gate 		return (err);
1267c478bd9Sstevel@tonic-gate 	}
1277c478bd9Sstevel@tonic-gate 	if ((dlcosmk_data->next_action =
1287c478bd9Sstevel@tonic-gate 	    ipp_action_lookup(next_action)) == IPP_ACTION_INVAL) {
1297c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
1307c478bd9Sstevel@tonic-gate 		dlcosmk0dbg(("dlcosmk_create_action: next_action invalid\n"));
1317c478bd9Sstevel@tonic-gate 		kmem_free(dlcosmk_data, DLCOSMK_DATA_SZ);
1327c478bd9Sstevel@tonic-gate 		return (EINVAL);
1337c478bd9Sstevel@tonic-gate 	}
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	/* parse cos - from the config file */
1367c478bd9Sstevel@tonic-gate 	if ((err = nvlist_lookup_byte(nvlp, DLCOSMK_COS,
1377c478bd9Sstevel@tonic-gate 	    &dlcosmk_data->usr_pri)) != 0) {
1387c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
1397c478bd9Sstevel@tonic-gate 		dlcosmk0dbg(("dlcosmk_create_action: invalid config, "\
1407c478bd9Sstevel@tonic-gate 		    "cos missing\n"));
1417c478bd9Sstevel@tonic-gate 		kmem_free(dlcosmk_data, DLCOSMK_DATA_SZ);
1427c478bd9Sstevel@tonic-gate 		return (err);
1437c478bd9Sstevel@tonic-gate 	}
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	/* parse b_band - mapped from cos */
1467c478bd9Sstevel@tonic-gate 	if ((err = nvlist_lookup_uint32(nvlp, DLCOSMK_BAND, &param)) != 0) {
1477c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
1487c478bd9Sstevel@tonic-gate 		dlcosmk0dbg(("dlcosmk_create_action: invalid config, "\
1497c478bd9Sstevel@tonic-gate 		    "b_band missing\n"));
1507c478bd9Sstevel@tonic-gate 		kmem_free(dlcosmk_data, DLCOSMK_DATA_SZ);
1517c478bd9Sstevel@tonic-gate 		return (err);
1527c478bd9Sstevel@tonic-gate 	}
1537c478bd9Sstevel@tonic-gate 	dlcosmk_data->b_band = param;
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	/* parse dl_priority.dl_max  - mapped from cos */
1567c478bd9Sstevel@tonic-gate 	if ((err = nvlist_lookup_uint32(nvlp, DLCOSMK_PRI, &param)) != 0) {
1577c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
1587c478bd9Sstevel@tonic-gate 		dlcosmk0dbg(("dlcosmk_create_action: invalid config, "\
1597c478bd9Sstevel@tonic-gate 		    "dl_priority missing\n"));
1607c478bd9Sstevel@tonic-gate 		kmem_free(dlcosmk_data, DLCOSMK_DATA_SZ);
1617c478bd9Sstevel@tonic-gate 		return (err);
1627c478bd9Sstevel@tonic-gate 	}
1637c478bd9Sstevel@tonic-gate 	dlcosmk_data->dl_max = param;
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	/* parse gather_stats boolean */
1667c478bd9Sstevel@tonic-gate 	if ((err = nvlist_lookup_uint32(nvlp, IPP_ACTION_STATS_ENABLE, &bstats))
1677c478bd9Sstevel@tonic-gate 	    != 0) {
1687c478bd9Sstevel@tonic-gate 		dlcosmk_data->gather_stats = B_FALSE;
1697c478bd9Sstevel@tonic-gate 	} else {
1707c478bd9Sstevel@tonic-gate 		/* If stats is needed, initialize the stats structure */
1717c478bd9Sstevel@tonic-gate 		dlcosmk_data->gather_stats = (bstats != 0) ? B_TRUE : B_FALSE;
1727c478bd9Sstevel@tonic-gate 		if (dlcosmk_data->gather_stats) {
1737c478bd9Sstevel@tonic-gate 			if ((err = dlcosmk_statinit(aid, dlcosmk_data)) != 0) {
1747c478bd9Sstevel@tonic-gate 				nvlist_free(nvlp);
1757c478bd9Sstevel@tonic-gate 				kmem_free(dlcosmk_data, DLCOSMK_DATA_SZ);
1767c478bd9Sstevel@tonic-gate 				return (err);
1777c478bd9Sstevel@tonic-gate 			}
1787c478bd9Sstevel@tonic-gate 		}
1797c478bd9Sstevel@tonic-gate 	}
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 	/* Free the nvlist */
1827c478bd9Sstevel@tonic-gate 	nvlist_free(nvlp);
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	/* set action chain reference */
1857c478bd9Sstevel@tonic-gate 	if ((err = ipp_action_ref(aid, dlcosmk_data->next_action,
1867c478bd9Sstevel@tonic-gate 	    flags)) != 0) {
1877c478bd9Sstevel@tonic-gate 		dlcosmk0dbg(("dlcosmk_create_action: ipp_action_ref " \
1887c478bd9Sstevel@tonic-gate 		    "returned with error %d\n", err));
1897c478bd9Sstevel@tonic-gate 		ipp_stat_destroy(dlcosmk_data->stats);
1907c478bd9Sstevel@tonic-gate 		kmem_free(dlcosmk_data, DLCOSMK_DATA_SZ);
1917c478bd9Sstevel@tonic-gate 		return (err);
1927c478bd9Sstevel@tonic-gate 	}
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	ipp_action_set_ptr(aid, (void *)dlcosmk_data);
1957c478bd9Sstevel@tonic-gate 	return (0);
1967c478bd9Sstevel@tonic-gate }
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate static int
dlcosmk_modify_action(ipp_action_id_t aid,nvlist_t ** nvlpp,ipp_flags_t flags)1997c478bd9Sstevel@tonic-gate dlcosmk_modify_action(ipp_action_id_t aid, nvlist_t **nvlpp, ipp_flags_t flags)
2007c478bd9Sstevel@tonic-gate {
2017c478bd9Sstevel@tonic-gate 	nvlist_t *nvlp;
2027c478bd9Sstevel@tonic-gate 	int err = 0;
2037c478bd9Sstevel@tonic-gate 	uint32_t band, dlpri;
2047c478bd9Sstevel@tonic-gate 	uint8_t config_type;
2057c478bd9Sstevel@tonic-gate 	uint8_t cos;
2067c478bd9Sstevel@tonic-gate 	char *next_action_name;
2077c478bd9Sstevel@tonic-gate 	ipp_action_id_t next_action;
2087c478bd9Sstevel@tonic-gate 	dlcosmk_data_t *dlcosmk_data;
2097c478bd9Sstevel@tonic-gate 	uint32_t bstats;
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	ASSERT((nvlpp != NULL) && (*nvlpp != NULL));
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 	nvlp = *nvlpp;
2147c478bd9Sstevel@tonic-gate 	*nvlpp = NULL;		/* nvlist should be NULL when this returns */
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 	if ((err = nvlist_lookup_byte(nvlp, IPP_CONFIG_TYPE, &config_type))
2177c478bd9Sstevel@tonic-gate 	    != 0) {
2187c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
2197c478bd9Sstevel@tonic-gate 		dlcosmk0dbg(("dlcosmk_modify_action: invalid configuration "\
2207c478bd9Sstevel@tonic-gate 		    "type\n"));
2217c478bd9Sstevel@tonic-gate 		return (err);
2227c478bd9Sstevel@tonic-gate 	}
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	if (config_type != IPP_SET) {
2257c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
2267c478bd9Sstevel@tonic-gate 		dlcosmk0dbg(("dlcosmk_modify_action: invalid configuration "\
2277c478bd9Sstevel@tonic-gate 		    "type %d\n", config_type));
2287c478bd9Sstevel@tonic-gate 		return (EINVAL);
2297c478bd9Sstevel@tonic-gate 	}
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 	dlcosmk_data = (dlcosmk_data_t *)ipp_action_get_ptr(aid);
2327c478bd9Sstevel@tonic-gate 	ASSERT(dlcosmk_data != NULL);
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	/* parse next action name, if present */
2357c478bd9Sstevel@tonic-gate 	if ((err = nvlist_lookup_string(nvlp, DLCOSMK_NEXT_ACTION_NAME,
2367c478bd9Sstevel@tonic-gate 	    &next_action_name)) == 0) {
2377c478bd9Sstevel@tonic-gate 		/* lookup action name to get action id */
2387c478bd9Sstevel@tonic-gate 		if ((next_action = ipp_action_lookup(next_action_name))
2397c478bd9Sstevel@tonic-gate 		    == IPP_ACTION_INVAL) {
2407c478bd9Sstevel@tonic-gate 			nvlist_free(nvlp);
2417c478bd9Sstevel@tonic-gate 			dlcosmk0dbg(("dlcosmk_modify_action: next_action "\
2427c478bd9Sstevel@tonic-gate 			    "invalid\n"));
2437c478bd9Sstevel@tonic-gate 			return (EINVAL);
2447c478bd9Sstevel@tonic-gate 		}
2457c478bd9Sstevel@tonic-gate 		/* reference new action */
2467c478bd9Sstevel@tonic-gate 		if ((err = ipp_action_ref(aid, next_action, flags)) != 0) {
2477c478bd9Sstevel@tonic-gate 			nvlist_free(nvlp);
2487c478bd9Sstevel@tonic-gate 			dlcosmk0dbg(("dlcosmk_modify_action: ipp_action_ref "\
2497c478bd9Sstevel@tonic-gate 			    "returned with error %d\n", err));
2507c478bd9Sstevel@tonic-gate 			return (err);
2517c478bd9Sstevel@tonic-gate 		}
2527c478bd9Sstevel@tonic-gate 		/* unref old action */
2537c478bd9Sstevel@tonic-gate 		err = ipp_action_unref(aid, dlcosmk_data->next_action, flags);
2547c478bd9Sstevel@tonic-gate 		ASSERT(err == 0);
2557c478bd9Sstevel@tonic-gate 		dlcosmk_data->next_action = next_action;
2567c478bd9Sstevel@tonic-gate 	}
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 	/* parse cos, if present */
2597c478bd9Sstevel@tonic-gate 	if ((err = nvlist_lookup_byte(nvlp, DLCOSMK_COS, &cos)) == 0) {
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 		/* parse b_band, mapped from cos */
2627c478bd9Sstevel@tonic-gate 		if ((err = nvlist_lookup_uint32(nvlp, DLCOSMK_BAND,
2637c478bd9Sstevel@tonic-gate 		    &band)) != 0) {
2647c478bd9Sstevel@tonic-gate 			nvlist_free(nvlp);
2657c478bd9Sstevel@tonic-gate 			dlcosmk0dbg(("dlcosmk_modify_action: b_band not "\
2667c478bd9Sstevel@tonic-gate 			    "provided\n"));
2677c478bd9Sstevel@tonic-gate 			return (err);
2687c478bd9Sstevel@tonic-gate 		}
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 		/* parse dl_priority, mapped from cos */
2717c478bd9Sstevel@tonic-gate 		if ((err = nvlist_lookup_uint32(nvlp, DLCOSMK_PRI,
2727c478bd9Sstevel@tonic-gate 		    &dlpri)) != 0) {
2737c478bd9Sstevel@tonic-gate 			nvlist_free(nvlp);
2747c478bd9Sstevel@tonic-gate 			dlcosmk0dbg(("dlcosmk_modify_action: dl_priority not "\
2757c478bd9Sstevel@tonic-gate 			    "provided\n"));
2767c478bd9Sstevel@tonic-gate 			return (err);
2777c478bd9Sstevel@tonic-gate 		}
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 		/* Have all the three values, change them */
2807c478bd9Sstevel@tonic-gate 		dlcosmk_data->usr_pri = cos;
2817c478bd9Sstevel@tonic-gate 		dlcosmk_data->b_band = band;
2827c478bd9Sstevel@tonic-gate 		dlcosmk_data->dl_max = dlpri;
2837c478bd9Sstevel@tonic-gate 	}
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 	/* parse gather_stats boolean, if present */
2877c478bd9Sstevel@tonic-gate 	if ((err = nvlist_lookup_uint32(nvlp, IPP_ACTION_STATS_ENABLE, &bstats))
2887c478bd9Sstevel@tonic-gate 	    == 0) {
2897c478bd9Sstevel@tonic-gate 		boolean_t val = (bstats != 0) ? B_TRUE : B_FALSE;
2907c478bd9Sstevel@tonic-gate 		/* Turning on stats */
2917c478bd9Sstevel@tonic-gate 		if (!dlcosmk_data->gather_stats && val) {
2927c478bd9Sstevel@tonic-gate 			if ((err = dlcosmk_statinit(aid, dlcosmk_data)) != 0) {
2937c478bd9Sstevel@tonic-gate 				nvlist_free(nvlp);
2947c478bd9Sstevel@tonic-gate 				return (err);
2957c478bd9Sstevel@tonic-gate 			}
2967c478bd9Sstevel@tonic-gate 		/* Turning off stats */
2977c478bd9Sstevel@tonic-gate 		} else if (!val && dlcosmk_data->gather_stats) {
2987c478bd9Sstevel@tonic-gate 			ipp_stat_destroy(dlcosmk_data->stats);
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 		}
3017c478bd9Sstevel@tonic-gate 		dlcosmk_data->gather_stats = val;
3027c478bd9Sstevel@tonic-gate 	}
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 	/* Free thenvlist */
3057c478bd9Sstevel@tonic-gate 	nvlist_free(nvlp);
3067c478bd9Sstevel@tonic-gate 	return (0);
3077c478bd9Sstevel@tonic-gate }
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate static int
dlcosmk_destroy_action(ipp_action_id_t aid,ipp_flags_t flags)3107c478bd9Sstevel@tonic-gate dlcosmk_destroy_action(ipp_action_id_t aid, ipp_flags_t flags)
3117c478bd9Sstevel@tonic-gate {
3127c478bd9Sstevel@tonic-gate 	dlcosmk_data_t *dlcosmk_data;
3137c478bd9Sstevel@tonic-gate 	int err;
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 	dlcosmk_data = (dlcosmk_data_t *)ipp_action_get_ptr(aid);
3167c478bd9Sstevel@tonic-gate 	ASSERT(dlcosmk_data != NULL);
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 	/* Destroy stats, if gathered */
3197c478bd9Sstevel@tonic-gate 	if (dlcosmk_data->gather_stats) {
3207c478bd9Sstevel@tonic-gate 		ipp_stat_destroy(dlcosmk_data->stats);
3217c478bd9Sstevel@tonic-gate 	}
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 	/* unreference the action */
3247c478bd9Sstevel@tonic-gate 	err = ipp_action_unref(aid, dlcosmk_data->next_action, flags);
3257c478bd9Sstevel@tonic-gate 	ASSERT(err == 0);
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 	kmem_free(dlcosmk_data, DLCOSMK_DATA_SZ);
3287c478bd9Sstevel@tonic-gate 	return (0);
3297c478bd9Sstevel@tonic-gate }
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate static int
dlcosmk_invoke_action(ipp_action_id_t aid,ipp_packet_t * packet)3327c478bd9Sstevel@tonic-gate dlcosmk_invoke_action(ipp_action_id_t aid, ipp_packet_t *packet)
3337c478bd9Sstevel@tonic-gate {
3347c478bd9Sstevel@tonic-gate 	dlcosmk_data_t *dlcosmk_data;
3357c478bd9Sstevel@tonic-gate 	mblk_t *mp = NULL;
3367c478bd9Sstevel@tonic-gate 	int err;
3377c478bd9Sstevel@tonic-gate 	ip_priv_t *priv;
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 	ASSERT(packet != NULL);
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 	/* get mblk from ipp_packet structure */
3427c478bd9Sstevel@tonic-gate 	mp = ipp_packet_get_data(packet);
3437c478bd9Sstevel@tonic-gate 	priv = (ip_priv_t *)ipp_packet_get_private(packet);
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 	dlcosmk_data = (dlcosmk_data_t *)ipp_action_get_ptr(aid);
3467c478bd9Sstevel@tonic-gate 	ASSERT(dlcosmk_data != NULL);
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	/* dlcosmk packet as configured */
3497c478bd9Sstevel@tonic-gate 	if ((err = dlcosmk_process(&mp, dlcosmk_data, priv->ill_index,
3507c478bd9Sstevel@tonic-gate 	    priv->proc)) != 0) {
3517c478bd9Sstevel@tonic-gate 		return (err);
3527c478bd9Sstevel@tonic-gate 	} else {
3537c478bd9Sstevel@tonic-gate 		/* return packet with next action set */
3547c478bd9Sstevel@tonic-gate 		return (ipp_packet_next(packet, dlcosmk_data->next_action));
3557c478bd9Sstevel@tonic-gate 	}
3567c478bd9Sstevel@tonic-gate }
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate static int
dlcosmk_statinit(ipp_action_id_t aid,dlcosmk_data_t * dlcosmk_data)3597c478bd9Sstevel@tonic-gate dlcosmk_statinit(ipp_action_id_t aid, dlcosmk_data_t *dlcosmk_data)
3607c478bd9Sstevel@tonic-gate {
3617c478bd9Sstevel@tonic-gate 	int err;
3627c478bd9Sstevel@tonic-gate 	dlcosmk_stat_t *statp;
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 	/* install stats entry */
3657c478bd9Sstevel@tonic-gate 	if ((err = ipp_stat_create(aid, DLCOSMK_STATS_STRING,
3667c478bd9Sstevel@tonic-gate 	    DLCOSMK_STATS_COUNT, dlcosmk_update_stats, dlcosmk_data,
3677c478bd9Sstevel@tonic-gate 	    &dlcosmk_data->stats)) != 0) {
3687c478bd9Sstevel@tonic-gate 		dlcosmk0dbg(("dlcosmk_create_action: ipp_stat_create " \
3697c478bd9Sstevel@tonic-gate 		    "returned with error %d\n", err));
3707c478bd9Sstevel@tonic-gate 		return (err);
3717c478bd9Sstevel@tonic-gate 	}
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 	statp = (dlcosmk_stat_t *)(dlcosmk_data->stats)->ipps_data;
3747c478bd9Sstevel@tonic-gate 	ASSERT(statp != NULL);
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 	if ((err = ipp_stat_named_init(dlcosmk_data->stats, "npackets",
3777c478bd9Sstevel@tonic-gate 	    IPP_STAT_UINT64, &statp->npackets)) != 0) {
3787c478bd9Sstevel@tonic-gate 		dlcosmk0dbg(("dlcosmk_create_action: ipp_stat_named_init " \
3797c478bd9Sstevel@tonic-gate 		    "returned with error %d\n", err));
3807c478bd9Sstevel@tonic-gate 		return (err);
3817c478bd9Sstevel@tonic-gate 	}
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 	if ((err = ipp_stat_named_init(dlcosmk_data->stats, "ipackets",
3847c478bd9Sstevel@tonic-gate 	    IPP_STAT_UINT64, &statp->ipackets)) != 0) {
3857c478bd9Sstevel@tonic-gate 		dlcosmk0dbg(("dlcosmk_create_action: ipp_stat_named_init " \
3867c478bd9Sstevel@tonic-gate 		    "returned with error %d\n", err));
3877c478bd9Sstevel@tonic-gate 		return (err);
3887c478bd9Sstevel@tonic-gate 	}
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 	if ((err = ipp_stat_named_init(dlcosmk_data->stats, "epackets",
3917c478bd9Sstevel@tonic-gate 	    IPP_STAT_UINT64, &statp->epackets)) != 0) {
3927c478bd9Sstevel@tonic-gate 		dlcosmk0dbg(("dlcosmk_create_action: ipp_stat_named_init " \
3937c478bd9Sstevel@tonic-gate 		    "returned with error %d\n", err));
3947c478bd9Sstevel@tonic-gate 		return (err);
3957c478bd9Sstevel@tonic-gate 	}
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	if ((err = ipp_stat_named_init(dlcosmk_data->stats, "usr_pri",
3987c478bd9Sstevel@tonic-gate 	    IPP_STAT_INT32, &statp->usr_pri)) != 0) {
3997c478bd9Sstevel@tonic-gate 		dlcosmk0dbg(("dlcosmk_create_action: ipp_stat_named_init " \
4007c478bd9Sstevel@tonic-gate 		    "returned with error %d", err));
4017c478bd9Sstevel@tonic-gate 		return (err);
4027c478bd9Sstevel@tonic-gate 	}
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	if ((err = ipp_stat_named_init(dlcosmk_data->stats, "b_band",
4057c478bd9Sstevel@tonic-gate 	    IPP_STAT_INT32, &statp->b_band)) != 0) {
4067c478bd9Sstevel@tonic-gate 		dlcosmk0dbg(("dlcosmk_create_action: ipp_stat_named_init " \
4077c478bd9Sstevel@tonic-gate 		    "returned with error %d\n", err));
4087c478bd9Sstevel@tonic-gate 		return (err);
4097c478bd9Sstevel@tonic-gate 	}
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 	if ((err = ipp_stat_named_init(dlcosmk_data->stats, "dl_max",
4127c478bd9Sstevel@tonic-gate 	    IPP_STAT_INT32, &statp->dl_max)) != 0) {
4137c478bd9Sstevel@tonic-gate 		dlcosmk0dbg(("dlcosmk_create_action: ipp_stat_named_init " \
4147c478bd9Sstevel@tonic-gate 		    "returned with error %d\n", err));
4157c478bd9Sstevel@tonic-gate 		return (err);
4167c478bd9Sstevel@tonic-gate 	}
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	ipp_stat_install(dlcosmk_data->stats);
4197c478bd9Sstevel@tonic-gate 	return (0);
4207c478bd9Sstevel@tonic-gate }
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate static int
dlcosmk_update_stats(ipp_stat_t * sp,void * arg,int rw)4237c478bd9Sstevel@tonic-gate dlcosmk_update_stats(ipp_stat_t *sp, void *arg, int rw)
4247c478bd9Sstevel@tonic-gate {
4257c478bd9Sstevel@tonic-gate 	dlcosmk_data_t *dlcosmk_data = (dlcosmk_data_t *)arg;
4267c478bd9Sstevel@tonic-gate 	dlcosmk_stat_t *snames = (dlcosmk_stat_t *)sp->ipps_data;
4277c478bd9Sstevel@tonic-gate 	uint32_t upri, bband;
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate 	ASSERT(dlcosmk_data != NULL);
4307c478bd9Sstevel@tonic-gate 	ASSERT(snames != NULL);
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	upri = dlcosmk_data->usr_pri;
4337c478bd9Sstevel@tonic-gate 	bband = dlcosmk_data->b_band;
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 	(void) ipp_stat_named_op(&snames->npackets, &dlcosmk_data->npackets,
4367c478bd9Sstevel@tonic-gate 	    rw);
4377c478bd9Sstevel@tonic-gate 	(void) ipp_stat_named_op(&snames->ipackets, &dlcosmk_data->ipackets,
4387c478bd9Sstevel@tonic-gate 	    rw);
4397c478bd9Sstevel@tonic-gate 	(void) ipp_stat_named_op(&snames->epackets, &dlcosmk_data->epackets,
4407c478bd9Sstevel@tonic-gate 	    rw);
4417c478bd9Sstevel@tonic-gate 	(void) ipp_stat_named_op(&snames->usr_pri, &upri, rw);
4427c478bd9Sstevel@tonic-gate 	(void) ipp_stat_named_op(&snames->b_band, &bband, rw);
4437c478bd9Sstevel@tonic-gate 	(void) ipp_stat_named_op(&snames->dl_max, &dlcosmk_data->dl_max, rw);
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 	return (0);
4467c478bd9Sstevel@tonic-gate }
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate /* ARGSUSED */
4497c478bd9Sstevel@tonic-gate static int
dlcosmk_info(ipp_action_id_t aid,int (* fn)(nvlist_t *,void *),void * arg,ipp_flags_t flags)4507c478bd9Sstevel@tonic-gate dlcosmk_info(ipp_action_id_t aid, int (*fn)(nvlist_t *, void *), void *arg,
4517c478bd9Sstevel@tonic-gate     ipp_flags_t flags)
4527c478bd9Sstevel@tonic-gate {
4537c478bd9Sstevel@tonic-gate 	nvlist_t *nvlp;
4547c478bd9Sstevel@tonic-gate 	dlcosmk_data_t *dlcosmk_data;
4557c478bd9Sstevel@tonic-gate 	char *next_action;
4567c478bd9Sstevel@tonic-gate 	int err;
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	ASSERT(fn != NULL);
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	dlcosmk_data = (dlcosmk_data_t *)ipp_action_get_ptr(aid);
4617c478bd9Sstevel@tonic-gate 	ASSERT(dlcosmk_data != NULL);
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 	/* allocate nvlist to be passed back */
4647c478bd9Sstevel@tonic-gate 	if ((err = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, KM_NOSLEEP)) != 0) {
4657c478bd9Sstevel@tonic-gate 		dlcosmk0dbg(("dlcosmk_info: error allocating memory\n"));
4667c478bd9Sstevel@tonic-gate 		return (err);
4677c478bd9Sstevel@tonic-gate 	}
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 	/* look up next action with the next action id */
4707c478bd9Sstevel@tonic-gate 	if ((err = ipp_action_name(dlcosmk_data->next_action,
4717c478bd9Sstevel@tonic-gate 	    &next_action)) != 0) {
4727c478bd9Sstevel@tonic-gate 		dlcosmk0dbg(("dlcosmk_info: next action not available\n"));
4737c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
4747c478bd9Sstevel@tonic-gate 		return (err);
4757c478bd9Sstevel@tonic-gate 	}
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 	/* add next action name */
4787c478bd9Sstevel@tonic-gate 	if ((err = nvlist_add_string(nvlp, DLCOSMK_NEXT_ACTION_NAME,
4797c478bd9Sstevel@tonic-gate 	    next_action)) != 0) {
4807c478bd9Sstevel@tonic-gate 		dlcosmk0dbg(("dlcosmk_info: error adding next action\n"));
4817c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
4827c478bd9Sstevel@tonic-gate 		kmem_free(next_action, (strlen(next_action) + 1));
4837c478bd9Sstevel@tonic-gate 		return (err);
4847c478bd9Sstevel@tonic-gate 	}
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 	/* free action name */
4877c478bd9Sstevel@tonic-gate 	kmem_free(next_action, (strlen(next_action) + 1));
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 	/* add config type */
4907c478bd9Sstevel@tonic-gate 	if ((err = nvlist_add_byte(nvlp, IPP_CONFIG_TYPE, IPP_SET)) != 0) {
4917c478bd9Sstevel@tonic-gate 		dlcosmk0dbg(("dlcosmk_info: error adding config. type\n"));
4927c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
4937c478bd9Sstevel@tonic-gate 		return (err);
4947c478bd9Sstevel@tonic-gate 	}
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 	/* just give the cos, since that is what is provided in the config */
4977c478bd9Sstevel@tonic-gate 	if ((err = nvlist_add_byte(nvlp, DLCOSMK_COS, dlcosmk_data->usr_pri))
4987c478bd9Sstevel@tonic-gate 	    != 0) {
4997c478bd9Sstevel@tonic-gate 		dlcosmk0dbg(("dlcosmk_info: error adding cos\n"));
5007c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
5017c478bd9Sstevel@tonic-gate 		return (err);
5027c478bd9Sstevel@tonic-gate 	}
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	/* add gather stats boolean */
5057c478bd9Sstevel@tonic-gate 	if ((err = nvlist_add_uint32(nvlp, IPP_ACTION_STATS_ENABLE,
5067c478bd9Sstevel@tonic-gate 	    (dlcosmk_data->gather_stats ? 1 : 0))) != 0) {
5077c478bd9Sstevel@tonic-gate 		dlcosmk0dbg(("dlcosmk_info: error adding stats status\n"));
5087c478bd9Sstevel@tonic-gate 		nvlist_free(nvlp);
5097c478bd9Sstevel@tonic-gate 		return (err);
5107c478bd9Sstevel@tonic-gate 	}
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 	/* call back with nvlist */
5137c478bd9Sstevel@tonic-gate 	err = fn(nvlp, arg);
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate 	nvlist_free(nvlp);
5167c478bd9Sstevel@tonic-gate 	return (err);
5177c478bd9Sstevel@tonic-gate }
518