4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/types.h>
27 #include <sys/atomic.h>
28 #include <sys/systm.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <sys/modctl.h>
32 #include <sys/sunddi.h>
34 #include <ipp/ipp_config.h>
35 #include <inet/common.h>
36 #include <ipp/meters/meter_impl.h>
38 #define D_SM_COMMENT "IPP Single-Two Rate Token Meter"
40 /* DDI file for tokenmt ipp module */
42 /* Default DSCP to colour mapping for colour-aware meter */
43 enum meter_colour default_dscp_to_colour
[64] = {
44 TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
,
45 TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
,
46 TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
,
47 TOKENMT_YELLOW
, TOKENMT_GREEN
, TOKENMT_RED
, TOKENMT_GREEN
,
48 TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
,
49 TOKENMT_YELLOW
, TOKENMT_GREEN
, TOKENMT_RED
, TOKENMT_GREEN
,
50 TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
,
51 TOKENMT_YELLOW
, TOKENMT_GREEN
, TOKENMT_RED
, TOKENMT_GREEN
,
52 TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
,
53 TOKENMT_YELLOW
, TOKENMT_GREEN
, TOKENMT_RED
, TOKENMT_GREEN
,
54 TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
,
55 TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
,
56 TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
,
57 TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
,
58 TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
,
59 TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
, TOKENMT_GREEN
62 static int tokenmt_create_action(ipp_action_id_t
, nvlist_t
**, ipp_flags_t
);
63 static int tokenmt_modify_action(ipp_action_id_t
, nvlist_t
**, ipp_flags_t
);
64 static int tokenmt_destroy_action(ipp_action_id_t
, ipp_flags_t
);
65 static int tokenmt_info(ipp_action_id_t
, int (*)(nvlist_t
*, void *), void *,
67 static int tokenmt_invoke_action(ipp_action_id_t
, ipp_packet_t
*);
69 /* Initialize stats */
70 static int tokenmt_statinit(ipp_action_id_t
, tokenmt_data_t
*);
72 /* Stats callback function */
73 static int tokenmt_update_stats(ipp_stat_t
*, void *, int);
75 ipp_ops_t tokenmt_ops
= {
77 tokenmt_create_action
, /* ippo_action_create */
78 tokenmt_modify_action
, /* ippo_action_modify */
79 tokenmt_destroy_action
, /* ippo_action_destroy */
80 tokenmt_info
, /* ippo_action_info */
81 tokenmt_invoke_action
/* ippo_action_invoke */
84 extern struct mod_ops mod_ippops
;
87 * Module linkage information for the kernel.
89 static struct modlipp modlipp
= {
95 static struct modlinkage modlinkage
= {
105 return (mod_install(&modlinkage
));
111 return (mod_remove(&modlinkage
));
115 _info(struct modinfo
*modinfop
)
117 return (mod_info(&modlinkage
, modinfop
));
122 tokenmt_create_action(ipp_action_id_t aid
, nvlist_t
**nvlpp
, ipp_flags_t flags
)
125 tokenmt_data_t
*tokenmt_data
;
127 tokenmt_cfg_t
*cfg_parms
;
135 *nvlpp
= NULL
; /* nvlist should be NULL on return */
137 if ((cfg_parms
= kmem_zalloc(TOKENMT_CFG_SZ
, KM_NOSLEEP
)) == NULL
) {
142 /* parse red next action name */
143 if ((rc
= nvlist_lookup_string(nvlp
, TOKENMT_RED_ACTION_NAME
,
144 &next_action
)) != 0) {
146 tokenmt0dbg(("tokenmt_create_action:invalid config, red "\
147 "action name missing\n"));
148 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
151 if ((cfg_parms
->red_action
= ipp_action_lookup(next_action
))
152 == IPP_ACTION_INVAL
) {
154 tokenmt0dbg(("tokenmt_create_action: red action invalid\n"));
155 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
159 /* parse yellow next action name, if present this is Two Rate meter */
160 if ((rc
= nvlist_lookup_string(nvlp
, TOKENMT_YELLOW_ACTION_NAME
,
161 &next_action
)) == 0) {
162 if ((cfg_parms
->yellow_action
= ipp_action_lookup(next_action
))
163 == IPP_ACTION_INVAL
) {
165 tokenmt0dbg(("tokenmt_create_action: yellow action "\
167 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
171 cfg_parms
->yellow_action
= TOKENMT_NO_ACTION
;
174 /* parse green next action name */
175 if ((rc
= nvlist_lookup_string(nvlp
, TOKENMT_GREEN_ACTION_NAME
,
176 &next_action
)) != 0) {
178 tokenmt0dbg(("tokenmt_create_action:invalid config, green " \
179 "action name missing\n"));
180 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
183 if ((cfg_parms
->green_action
= ipp_action_lookup(next_action
))
184 == IPP_ACTION_INVAL
) {
186 tokenmt0dbg(("tokenmt_create_action: green action invalid\n"));
187 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
191 /* parse committed rate - in kilo bits / sec */
192 if ((rc
= nvlist_lookup_uint32(nvlp
, TOKENMT_COMMITTED_RATE
,
193 &cfg_parms
->committed_rate
)) != 0) {
195 tokenmt0dbg(("tokenmt_create_action: invalid config, "\
196 " committed rate missing\n"));
197 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
200 if (cfg_parms
->committed_rate
== 0) {
202 tokenmt0dbg(("tokenmt_create_action: invalid committed rate, "\
203 "%u\n", cfg_parms
->committed_rate
));
204 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
208 /* parse committed burst in bits */
209 if ((rc
= nvlist_lookup_uint32(nvlp
, TOKENMT_COMMITTED_BURST
,
210 &cfg_parms
->committed_burst
)) != 0) {
212 tokenmt0dbg(("tokenmt_create_action: invalid config, "\
213 " committed burst missing\n"));
214 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
220 * If the peak burst size is specified, make sure we have the
223 if ((rc
= nvlist_lookup_uint32(nvlp
, TOKENMT_PEAK_BURST
,
224 &cfg_parms
->peak_burst
)) == 0) {
225 if (cfg_parms
->yellow_action
== TOKENMT_NO_ACTION
) {
227 tokenmt0dbg(("tokenmt_create_action: peak burst "\
228 "specified without yellow action\n"));
229 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
232 } else if (cfg_parms
->yellow_action
!= TOKENMT_NO_ACTION
) {
234 tokenmt0dbg(("tokenmt_create_action: peak burst must be "\
235 "provided with yellow action\n"));
236 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
240 /* Check if we have a peak_rate */
241 if ((rc
= nvlist_lookup_uint32(nvlp
, TOKENMT_PEAK_RATE
,
242 &cfg_parms
->peak_rate
)) == 0) {
243 if (cfg_parms
->yellow_action
== TOKENMT_NO_ACTION
) {
245 tokenmt0dbg(("tokenmt_create_action: peak rate "\
246 "specified without yellow action\n"));
247 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
249 } else if ((cfg_parms
->peak_rate
== 0) ||
250 (cfg_parms
->peak_rate
< cfg_parms
->committed_rate
)) {
252 tokenmt0dbg(("tokenmt_create_action: invalid "\
253 "peak rate, %u\n", cfg_parms
->peak_rate
));
254 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
257 cfg_parms
->tokenmt_type
= TRTCL_TOKENMT
;
259 cfg_parms
->tokenmt_type
= SRTCL_TOKENMT
;
262 /* Validate the committed and peak burst size */
263 if (cfg_parms
->tokenmt_type
== SRTCL_TOKENMT
) {
264 if ((cfg_parms
->committed_burst
== 0) &&
265 (cfg_parms
->peak_burst
== 0)) {
267 tokenmt0dbg(("tokenmt_create_action: at least one "\
268 "burst size must be non-zero\n"));
269 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
272 } else { /* TRTCL_TOKENMT */
273 if ((cfg_parms
->committed_burst
== 0) ||
274 (cfg_parms
->peak_burst
== 0)) {
276 tokenmt0dbg(("tokenmt_create_action: both the "\
277 "burst sizes must be non-zero\n"));
278 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
283 /* just copy default colour mapping */
284 bcopy(default_dscp_to_colour
, cfg_parms
->dscp_to_colour
,
285 sizeof (default_dscp_to_colour
));
287 /* parse mode, if present */
288 if ((rc
= nvlist_lookup_uint32(nvlp
, TOKENMT_COLOUR_AWARE
,
290 cfg_parms
->colour_aware
= B_FALSE
;
292 cfg_parms
->colour_aware
= (mode
== 0) ? B_FALSE
: B_TRUE
;
295 /* Get the dscp to colour mapping array */
296 if (cfg_parms
->colour_aware
) {
297 if ((rc
= nvlist_lookup_int32_array(nvlp
,
298 TOKENMT_COLOUR_MAP
, &colour_tbl
, &nelem
)) == 0) {
300 for (count
= 0; count
< 64; count
++) {
301 if (colour_tbl
[count
] == -1)
303 cfg_parms
->dscp_to_colour
[count
] =
310 if ((rc
= nvlist_lookup_uint32(nvlp
, IPP_ACTION_STATS_ENABLE
, &bstats
))
312 cfg_parms
->stats
= B_FALSE
;
314 cfg_parms
->stats
= (bstats
== 0) ? B_FALSE
: B_TRUE
;
319 /* Initialize other stuff */
320 tokenmt_data
= kmem_zalloc(TOKENMT_DATA_SZ
, KM_NOSLEEP
);
321 if (tokenmt_data
== NULL
) {
322 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
326 /* Initialize stats, if required */
327 if (cfg_parms
->stats
) {
328 if ((rc
= tokenmt_statinit(aid
, tokenmt_data
)) != 0) {
329 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
330 kmem_free(tokenmt_data
, TOKENMT_DATA_SZ
);
335 /* set action chain reference */
336 if ((rc
= ipp_action_ref(aid
, cfg_parms
->red_action
, flags
)) != 0) {
337 tokenmt0dbg(("tokenmt_create_action: ipp_action_ref " \
338 "returned with error %d", rc
));
341 if ((rc
= ipp_action_ref(aid
, cfg_parms
->green_action
, flags
)) != 0) {
342 tokenmt0dbg(("tokenmt_create_action: ipp_action_ref " \
343 "returned with error %d", rc
));
344 rc2
= ipp_action_unref(aid
, cfg_parms
->red_action
, flags
);
349 if (cfg_parms
->yellow_action
!= TOKENMT_NO_ACTION
) {
350 if ((rc
= ipp_action_ref(aid
, cfg_parms
->yellow_action
,
352 tokenmt0dbg(("tokenmt_create_action: ipp_action_ref "\
353 "returned with error %d", rc
));
354 rc2
= ipp_action_unref(aid
, cfg_parms
->red_action
,
357 rc2
= ipp_action_unref(aid
, cfg_parms
->green_action
,
365 tokenmt_data
->cfg_parms
= cfg_parms
;
367 tokenmt_data
->committed_tokens
= cfg_parms
->committed_burst
;
368 tokenmt_data
->peak_tokens
= cfg_parms
->peak_burst
;
369 tokenmt_data
->last_seen
= gethrtime();
371 mutex_init(&tokenmt_data
->tokenmt_lock
, NULL
, MUTEX_DEFAULT
, 0);
372 ipp_action_set_ptr(aid
, (void *)tokenmt_data
);
376 if (cfg_parms
->stats
) {
377 ipp_stat_destroy(tokenmt_data
->stats
);
379 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
380 kmem_free(tokenmt_data
, TOKENMT_DATA_SZ
);
385 tokenmt_modify_action(ipp_action_id_t aid
, nvlist_t
**nvlpp
, ipp_flags_t flags
)
390 char *next_action_name
;
391 ipp_action_id_t next_action
;
392 uint32_t rate
, cbs
, pbs
;
393 tokenmt_cfg_t
*cfg_parms
, *old_cfg
;
394 tokenmt_data_t
*tokenmt_data
;
395 uint32_t bstats
, mode
;
400 *nvlpp
= NULL
; /* nvlist should be NULL when this returns */
402 if ((err
= nvlist_lookup_byte(nvlp
, IPP_CONFIG_TYPE
, &config_type
))
405 tokenmt0dbg(("tokenmt_modify_action: invalid configuration "\
410 if (config_type
!= IPP_SET
) {
412 tokenmt0dbg(("tokenmt_modify_action: invalid configuration "\
413 "type %d", config_type
));
417 tokenmt_data
= (tokenmt_data_t
*)ipp_action_get_ptr(aid
);
418 old_cfg
= tokenmt_data
->cfg_parms
;
420 cfg_parms
= kmem_zalloc(TOKENMT_CFG_SZ
, KM_NOSLEEP
);
421 if (cfg_parms
== NULL
) {
423 tokenmt0dbg(("tokenmt_modify_action: memory allocation "\
428 /* Just copy all and change as needed */
429 bcopy(old_cfg
, cfg_parms
, TOKENMT_CFG_SZ
);
431 /* parse red action name, if present */
432 if ((err
= nvlist_lookup_string(nvlp
, TOKENMT_RED_ACTION_NAME
,
433 &next_action_name
)) == 0) {
435 if ((next_action
= ipp_action_lookup(next_action_name
))
436 == IPP_ACTION_INVAL
) {
438 tokenmt0dbg(("tokenmt_modify_action: next_action "\
440 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
443 cfg_parms
->red_action
= next_action
;
446 /* parse yellow action name, if present */
447 if ((err
= nvlist_lookup_string(nvlp
, TOKENMT_YELLOW_ACTION_NAME
,
448 &next_action_name
)) == 0) {
450 if ((next_action
= ipp_action_lookup(next_action_name
))
451 == IPP_ACTION_INVAL
) {
453 tokenmt0dbg(("tokenmt_modify_action: next_action "\
455 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
458 cfg_parms
->yellow_action
= next_action
;
460 cfg_parms
->yellow_action
= TOKENMT_NO_ACTION
;
463 /* parse green action name, if present */
464 if ((err
= nvlist_lookup_string(nvlp
, TOKENMT_GREEN_ACTION_NAME
,
465 &next_action_name
)) == 0) {
467 if ((next_action
= ipp_action_lookup(next_action_name
))
468 == IPP_ACTION_INVAL
) {
470 tokenmt0dbg(("tokenmt_modify_action: next_action "\
472 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
475 cfg_parms
->green_action
= next_action
;
478 /* parse committed rate, if present */
479 if ((err
= nvlist_lookup_uint32(nvlp
, TOKENMT_COMMITTED_RATE
, &rate
))
483 tokenmt0dbg(("tokenmt_modify_action: invalid "\
484 "committed rate %u\n", cfg_parms
->committed_rate
));
485 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
488 cfg_parms
->committed_rate
= rate
;
491 /* parse committed burst, if present */
492 if (nvlist_lookup_uint32(nvlp
, TOKENMT_COMMITTED_BURST
, &cbs
) == 0) {
493 cfg_parms
->committed_burst
= cbs
;
497 if (nvlist_lookup_uint32(nvlp
, TOKENMT_PEAK_BURST
, &pbs
) == 0) {
498 cfg_parms
->peak_burst
= pbs
;
500 cfg_parms
->peak_burst
= 0;
503 /* If the peak rate is not specified, then it means single rate meter */
504 if (nvlist_lookup_uint32(nvlp
, TOKENMT_PEAK_RATE
, &rate
) == 0) {
505 cfg_parms
->peak_rate
= rate
;
506 if ((rate
== 0) || (rate
< cfg_parms
->committed_rate
)) {
508 tokenmt0dbg(("tokenmt_modify_action: invalid "\
509 "committed rate %u\n", cfg_parms
->committed_rate
));
510 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
513 cfg_parms
->tokenmt_type
= TRTCL_TOKENMT
;
515 cfg_parms
->peak_rate
= 0;
516 cfg_parms
->tokenmt_type
= SRTCL_TOKENMT
;
519 if (cfg_parms
->yellow_action
== TOKENMT_NO_ACTION
) {
520 if ((cfg_parms
->peak_burst
!= 0) ||
521 (cfg_parms
->tokenmt_type
== TRTCL_TOKENMT
)) {
523 tokenmt0dbg(("tokenmt_modify_action: yellow action "\
525 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
529 if ((cfg_parms
->tokenmt_type
!= TRTCL_TOKENMT
) &&
530 (cfg_parms
->peak_burst
== 0)) {
532 tokenmt0dbg(("tokenmt_modify_action: peak "\
533 "burst/rate missing\n"));
534 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
539 /* Validate the committed and peak burst size */
540 if (cfg_parms
->tokenmt_type
== SRTCL_TOKENMT
) {
541 if ((cfg_parms
->committed_burst
== 0) &&
542 (cfg_parms
->peak_burst
== 0)) {
544 tokenmt0dbg(("tokenmt_modify_action: at least one "\
545 "burst size must be non-zero\n"));
546 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
549 } else { /* TRTCL_TOKENMT */
550 if ((cfg_parms
->committed_burst
== 0) ||
551 (cfg_parms
->peak_burst
== 0)) {
553 tokenmt0dbg(("tokenmt_modify_action: both the "\
554 "burst sizes must be non-zero\n"));
555 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
561 if (nvlist_lookup_uint32(nvlp
, TOKENMT_COLOUR_AWARE
, &mode
) == 0) {
562 cfg_parms
->colour_aware
= (mode
== 0) ? B_FALSE
: B_TRUE
;
564 cfg_parms
->colour_aware
= B_FALSE
;
567 if (cfg_parms
->colour_aware
) {
568 if (nvlist_lookup_int32_array(nvlp
, TOKENMT_COLOUR_MAP
,
569 &colour_tbl
, &nelem
) == 0) {
571 for (count
= 0; count
< 64; count
++) {
572 if (colour_tbl
[count
] == -1)
574 cfg_parms
->dscp_to_colour
[count
] =
578 bcopy(default_dscp_to_colour
, cfg_parms
->dscp_to_colour
,
579 sizeof (default_dscp_to_colour
));
583 /* parse stats, if present */
584 if (nvlist_lookup_uint32(nvlp
, IPP_ACTION_STATS_ENABLE
, &bstats
) == 0) {
585 cfg_parms
->stats
= (bstats
== 0) ? B_FALSE
: B_TRUE
;
586 if (cfg_parms
->stats
&& !old_cfg
->stats
) {
587 if ((err
= tokenmt_statinit(aid
, tokenmt_data
)) != 0) {
589 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
592 } else if (!cfg_parms
->stats
&& old_cfg
->stats
) {
593 ipp_stat_destroy(tokenmt_data
->stats
);
597 /* Can we ref all the new actions? */
598 if ((err
= ipp_action_ref(aid
, cfg_parms
->red_action
, flags
)) != 0) {
599 tokenmt0dbg(("tokenmt_modify_data: can't ref. red action\n"));
600 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
603 if ((err
= ipp_action_ref(aid
, cfg_parms
->green_action
, flags
)) != 0) {
604 tokenmt0dbg(("tokenmt_modify_data:can't ref. green action\n"));
605 err2
= ipp_action_unref(aid
, cfg_parms
->red_action
, flags
);
607 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
611 if (cfg_parms
->yellow_action
!= TOKENMT_NO_ACTION
) {
612 if ((err
= ipp_action_ref(aid
, cfg_parms
->yellow_action
,
614 tokenmt0dbg(("tokenmt_modify_data:can't ref. yellow "\
616 err2
= ipp_action_unref(aid
, cfg_parms
->red_action
,
619 err2
= ipp_action_unref(aid
, cfg_parms
->green_action
,
622 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
628 /* Actually modify the configuration */
629 mutex_enter(&tokenmt_data
->tokenmt_lock
);
630 tokenmt_data
->cfg_parms
= cfg_parms
;
631 mutex_exit(&tokenmt_data
->tokenmt_lock
);
633 /* Un-ref the old actions */
634 err
= ipp_action_unref(aid
, old_cfg
->red_action
, flags
);
636 if (old_cfg
->yellow_action
!= TOKENMT_NO_ACTION
) {
637 err
= ipp_action_unref(aid
, old_cfg
->yellow_action
, flags
);
640 err
= ipp_action_unref(aid
, old_cfg
->green_action
, flags
);
643 /* Free the old configuration */
644 kmem_free(old_cfg
, TOKENMT_CFG_SZ
);
649 tokenmt_destroy_action(ipp_action_id_t aid
, ipp_flags_t flags
)
651 tokenmt_data_t
*tokenmt_data
;
652 tokenmt_cfg_t
*cfg_parms
;
655 tokenmt_data
= (tokenmt_data_t
*)ipp_action_get_ptr(aid
);
656 ASSERT(tokenmt_data
!= NULL
);
658 cfg_parms
= tokenmt_data
->cfg_parms
;
660 if (cfg_parms
->stats
) {
661 ipp_stat_destroy(tokenmt_data
->stats
);
664 /* unreference the action */
665 rc
= ipp_action_unref(aid
, cfg_parms
->red_action
, flags
);
667 if (cfg_parms
->yellow_action
!= TOKENMT_NO_ACTION
) {
668 rc
= ipp_action_unref(aid
, cfg_parms
->yellow_action
, flags
);
671 rc
= ipp_action_unref(aid
, cfg_parms
->green_action
, flags
);
674 mutex_destroy(&tokenmt_data
->tokenmt_lock
);
675 kmem_free(cfg_parms
, TOKENMT_CFG_SZ
);
676 kmem_free(tokenmt_data
, TOKENMT_DATA_SZ
);
681 tokenmt_invoke_action(ipp_action_id_t aid
, ipp_packet_t
*packet
)
683 tokenmt_data_t
*tokenmt_data
;
684 ipp_action_id_t next_action
;
688 /* get mblk from ipp_packet structure */
689 mp
= ipp_packet_get_data(packet
);
690 tokenmt_data
= (tokenmt_data_t
*)ipp_action_get_ptr(aid
);
691 ASSERT(tokenmt_data
!= NULL
);
693 /* meter packet as configured */
694 if ((rc
= tokenmt_process(&mp
, tokenmt_data
, &next_action
)) != 0) {
697 return (ipp_packet_next(packet
, next_action
));
702 tokenmt_statinit(ipp_action_id_t aid
, tokenmt_data_t
*tokenmt_data
) {
705 meter_stat_t
*statsp
;
707 /* install stats entry */
708 if ((rc
= ipp_stat_create(aid
, TOKENMT_STATS_STRING
, METER_STATS_COUNT
,
709 tokenmt_update_stats
, tokenmt_data
, &tokenmt_data
->stats
)) != 0) {
710 tokenmt0dbg(("tokenmt_statinit: ipp_stat_create failed "\
715 statsp
= (meter_stat_t
*)(tokenmt_data
->stats
)->ipps_data
;
716 ASSERT(statsp
!= NULL
);
718 if ((rc
= ipp_stat_named_init(tokenmt_data
->stats
, "red_packets",
719 IPP_STAT_UINT64
, &statsp
->red_packets
)) != 0) {
720 tokenmt0dbg(("tokenmt_statinit:ipp_stat_named_init failed "\
724 if ((rc
= ipp_stat_named_init(tokenmt_data
->stats
, "yellow_packets",
725 IPP_STAT_UINT64
, &statsp
->yellow_packets
)) != 0) {
726 tokenmt0dbg(("tokenmt_statinit:ipp_stat_named_init failed "\
730 if ((rc
= ipp_stat_named_init(tokenmt_data
->stats
, "green_packets",
731 IPP_STAT_UINT64
, &statsp
->green_packets
)) != 0) {
732 tokenmt0dbg(("tokenmt_statinit:ipp_stat_named_init failed "\
736 if ((rc
= ipp_stat_named_init(tokenmt_data
->stats
, "red_bits",
737 IPP_STAT_UINT64
, &statsp
->red_bits
)) != 0) {
738 tokenmt0dbg(("tokenmt_statinit:ipp_stat_named_init failed "\
742 if ((rc
= ipp_stat_named_init(tokenmt_data
->stats
, "yellow_bits",
743 IPP_STAT_UINT64
, &statsp
->yellow_bits
)) != 0) {
744 tokenmt0dbg(("tokenmt_statinit:ipp_stat_named_init failed "\
748 if ((rc
= ipp_stat_named_init(tokenmt_data
->stats
, "green_bits",
749 IPP_STAT_UINT64
, &statsp
->green_bits
)) != 0) {
750 tokenmt0dbg(("tokenmt_statinit:ipp_stat_named_init failed "\
754 if ((rc
= ipp_stat_named_init(tokenmt_data
->stats
, "epackets",
755 IPP_STAT_UINT64
, &statsp
->epackets
)) != 0) {
756 tokenmt0dbg(("tokenmt_statinit:ipp_stat_named_init failed "\
761 ipp_stat_install(tokenmt_data
->stats
);
767 tokenmt_update_stats(ipp_stat_t
*sp
, void *args
, int rw
)
769 tokenmt_data_t
*tokenmt_data
= (tokenmt_data_t
*)args
;
770 meter_stat_t
*stats
= (meter_stat_t
*)sp
->ipps_data
;
772 ASSERT((tokenmt_data
!= NULL
) && (stats
!= NULL
));
774 (void) ipp_stat_named_op(&stats
->red_packets
,
775 &tokenmt_data
->red_packets
, rw
);
776 (void) ipp_stat_named_op(&stats
->yellow_packets
,
777 &tokenmt_data
->yellow_packets
, rw
);
778 (void) ipp_stat_named_op(&stats
->green_packets
,
779 &tokenmt_data
->green_packets
, rw
);
780 (void) ipp_stat_named_op(&stats
->red_bits
,
781 &tokenmt_data
->red_bits
, rw
);
782 (void) ipp_stat_named_op(&stats
->yellow_bits
,
783 &tokenmt_data
->yellow_bits
, rw
);
784 (void) ipp_stat_named_op(&stats
->green_bits
,
785 &tokenmt_data
->green_bits
, rw
);
786 (void) ipp_stat_named_op(&stats
->epackets
, &tokenmt_data
->epackets
,
794 tokenmt_info(ipp_action_id_t aid
, int (*fn
)(nvlist_t
*, void *), void *arg
,
798 tokenmt_data_t
*tokenmt_data
;
799 tokenmt_cfg_t
*cfg_parms
;
801 int32_t dscp_to_colour
[64];
804 tokenmt_data
= (tokenmt_data_t
*)ipp_action_get_ptr(aid
);
805 ASSERT(tokenmt_data
!= NULL
);
807 cfg_parms
= tokenmt_data
->cfg_parms
;
809 /* allocate nvlist to be passed back */
810 if ((rc
= nvlist_alloc(&nvlp
, NV_UNIQUE_NAME
, KM_NOSLEEP
)) != 0) {
811 tokenmt0dbg(("tokenmt_info: memory allocation failure\n"));
815 /* look up red next action with the next action id */
816 if ((rc
= ipp_action_name(cfg_parms
->red_action
, &next_action
)) != 0) {
817 tokenmt0dbg(("tokenmt_info: red_action not available\n"));
822 /* add next action name */
823 if ((rc
= nvlist_add_string(nvlp
, TOKENMT_RED_ACTION_NAME
,
824 next_action
)) != 0) {
826 tokenmt0dbg(("tokenmt_info: error adding red_action\n"));
827 kmem_free(next_action
, (strlen(next_action
) + 1));
831 /* free action name */
832 kmem_free(next_action
, (strlen(next_action
) + 1));
835 /* look up yellow next action with the next action id */
836 if (cfg_parms
->yellow_action
!= TOKENMT_NO_ACTION
) {
837 if ((rc
= ipp_action_name(cfg_parms
->yellow_action
,
838 &next_action
)) != 0) {
839 tokenmt0dbg(("tokenmt_info: yellow_action not "\
844 /* add next action name */
845 if ((rc
= nvlist_add_string(nvlp
, TOKENMT_YELLOW_ACTION_NAME
,
846 next_action
)) != 0) {
848 tokenmt0dbg(("tokenmt_info: error adding "\
850 kmem_free(next_action
, (strlen(next_action
) + 1));
853 /* free action name */
854 kmem_free(next_action
, (strlen(next_action
) + 1));
857 /* look up green next action with the next action id */
858 if ((rc
= ipp_action_name(cfg_parms
->green_action
,
859 &next_action
)) != 0) {
860 tokenmt0dbg(("tokenmt_info: green_action not available\n"));
865 /* add next action name */
866 if ((rc
= nvlist_add_string(nvlp
, TOKENMT_GREEN_ACTION_NAME
,
867 next_action
)) != 0) {
869 tokenmt0dbg(("tokenmt_info: error adding green_action\n"));
870 kmem_free(next_action
, (strlen(next_action
) + 1));
874 /* free action name */
875 kmem_free(next_action
, (strlen(next_action
) + 1));
877 /* add config type */
878 if ((rc
= nvlist_add_byte(nvlp
, IPP_CONFIG_TYPE
, IPP_SET
)) != 0) {
879 tokenmt0dbg(("tokenmt_info: error adding config_type\n"));
884 /* add committed_rate */
885 if ((rc
= nvlist_add_uint32(nvlp
, TOKENMT_COMMITTED_RATE
,
886 cfg_parms
->committed_rate
)) != 0) {
887 tokenmt0dbg(("tokenmt_info: error adding committed_rate\n"));
892 if (cfg_parms
->tokenmt_type
== TRTCL_TOKENMT
) {
894 if ((rc
= nvlist_add_uint32(nvlp
, TOKENMT_PEAK_RATE
,
895 cfg_parms
->peak_rate
)) != 0) {
896 tokenmt0dbg(("tokenmt_info: error adding peak_rate\n"));
902 /* add committed_burst */
903 if ((rc
= nvlist_add_uint32(nvlp
, TOKENMT_COMMITTED_BURST
,
904 cfg_parms
->committed_burst
)) != 0) {
905 tokenmt0dbg(("tokenmt_info: error adding committed_burst\n"));
911 if (cfg_parms
->peak_burst
!= 0) {
912 if ((rc
= nvlist_add_uint32(nvlp
, TOKENMT_PEAK_BURST
,
913 cfg_parms
->peak_burst
)) != 0) {
914 tokenmt0dbg(("tokenmt_info: error adding peak "\
921 /* add colour aware */
922 if ((rc
= nvlist_add_uint32(nvlp
, TOKENMT_COLOUR_AWARE
,
923 cfg_parms
->colour_aware
)) != 0) {
924 tokenmt0dbg(("tokenmt_info: error adding mode\n"));
929 if (cfg_parms
->colour_aware
) {
930 bcopy(cfg_parms
->dscp_to_colour
, dscp_to_colour
,
931 sizeof (cfg_parms
->dscp_to_colour
));
932 if ((rc
= nvlist_add_int32_array(nvlp
, TOKENMT_COLOUR_MAP
,
933 dscp_to_colour
, 64)) != 0) {
934 tokenmt0dbg(("tokenmt_info: error adding colour "\
941 if ((rc
= nvlist_add_uint32(nvlp
, IPP_ACTION_STATS_ENABLE
,
942 (uint32_t)cfg_parms
->stats
)) != 0) {
943 tokenmt0dbg(("tokenmt_info: error adding stats status\n"));
948 /* call back with nvlist */