1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <sys/types.h>
28 #include <sys/atomic.h>
29 #include <sys/systm.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <sys/modctl.h>
33 #include <sys/sunddi.h>
34 #include <ipp/ipp.h>
35 #include <ipp/ipp_config.h>
36 #include <inet/common.h>
37 #include <ipp/meters/meter_impl.h>
38
39 #define D_SM_COMMENT "IPP Sliding Window Meter"
40
41 /* DDI file for tswtcl ipp module */
42
43 static int tswtcl_create_action(ipp_action_id_t, nvlist_t **, ipp_flags_t);
44 static int tswtcl_modify_action(ipp_action_id_t, nvlist_t **, ipp_flags_t);
45 static int tswtcl_destroy_action(ipp_action_id_t, ipp_flags_t);
46 static int tswtcl_info(ipp_action_id_t, int (*)(nvlist_t *, void *), void *,
47 ipp_flags_t);
48 static int tswtcl_invoke_action(ipp_action_id_t, ipp_packet_t *);
49
50 /* Stats init function */
51 static int tswtcl_statinit(ipp_action_id_t, tswtcl_data_t *);
52
53 /* Stats callback function */
54 static int tswtcl_update_stats(ipp_stat_t *, void *, int);
55
56 ipp_ops_t tswtcl_ops = {
57 IPPO_REV,
58 tswtcl_create_action, /* ippo_action_create */
59 tswtcl_modify_action, /* ippo_action_modify */
60 tswtcl_destroy_action, /* ippo_action_destroy */
61 tswtcl_info, /* ippo_action_info */
62 tswtcl_invoke_action /* ippo_action_invoke */
63 };
64
65 extern struct mod_ops mod_ippops;
66
67 /*
68 * Module linkage information for the kernel.
69 */
70 static struct modlipp modlipp = {
71 &mod_ippops,
72 D_SM_COMMENT,
73 &tswtcl_ops
74 };
75
76 static struct modlinkage modlinkage = {
77 MODREV_1,
78 (void *)&modlipp,
79 NULL
80 };
81
82
83 int
_init(void)84 _init(void)
85 {
86 return (mod_install(&modlinkage));
87 }
88
89 int
_fini(void)90 _fini(void)
91 {
92 return (mod_remove(&modlinkage));
93 }
94
95 int
_info(struct modinfo * modinfop)96 _info(struct modinfo *modinfop)
97 {
98 return (mod_info(&modlinkage, modinfop));
99 }
100
101 /* ARGSUSED */
102 static int
tswtcl_create_action(ipp_action_id_t aid,nvlist_t ** nvlpp,ipp_flags_t flags)103 tswtcl_create_action(ipp_action_id_t aid, nvlist_t **nvlpp, ipp_flags_t flags)
104 {
105 nvlist_t *nvlp;
106 tswtcl_data_t *tswtcl_data;
107 tswtcl_cfg_t *cfg_parms;
108 char *next_action;
109 uint32_t bstats;
110 int rc, rc2;
111
112 nvlp = *nvlpp;
113 *nvlpp = NULL; /* nvlist should be NULL on return */
114
115
116 if ((cfg_parms = kmem_alloc(TSWTCL_CFG_SZ, KM_NOSLEEP)) == NULL) {
117 nvlist_free(nvlp);
118 return (ENOMEM);
119 }
120
121 /* parse red next action name */
122 if ((rc = nvlist_lookup_string(nvlp, TSWTCL_RED_ACTION_NAME,
123 &next_action)) != 0) {
124 nvlist_free(nvlp);
125 tswtcl0dbg(("tswtcl_create_action:invalid config, red action" \
126 " name missing\n"));
127 kmem_free(cfg_parms, TSWTCL_CFG_SZ);
128 return (rc);
129 }
130 if ((cfg_parms->red_action = ipp_action_lookup(next_action))
131 == IPP_ACTION_INVAL) {
132 nvlist_free(nvlp);
133 tswtcl0dbg(("tswtcl_create_action: red action invalid\n"));
134 kmem_free(cfg_parms, TSWTCL_CFG_SZ);
135 return (EINVAL);
136 }
137
138 /* parse yellow next action name */
139 if ((rc = nvlist_lookup_string(nvlp, TSWTCL_YELLOW_ACTION_NAME,
140 &next_action)) != 0) {
141 nvlist_free(nvlp);
142 tswtcl0dbg(("tswtcl_create_action:invalid config, yellow " \
143 "action name missing\n"));
144 kmem_free(cfg_parms, TSWTCL_CFG_SZ);
145 return (rc);
146 }
147 if ((cfg_parms->yellow_action = ipp_action_lookup(next_action))
148 == IPP_ACTION_INVAL) {
149 nvlist_free(nvlp);
150 tswtcl0dbg(("tswtcl_create_action: yellow action invalid\n"));
151 kmem_free(cfg_parms, TSWTCL_CFG_SZ);
152 return (EINVAL);
153 }
154
155 /* parse green next action name */
156 if ((rc = nvlist_lookup_string(nvlp, TSWTCL_GREEN_ACTION_NAME,
157 &next_action)) != 0) {
158 nvlist_free(nvlp);
159 tswtcl0dbg(("tswtcl_create_action:invalid config, green " \
160 "action name missing\n"));
161 kmem_free(cfg_parms, TSWTCL_CFG_SZ);
162 return (rc);
163 }
164 if ((cfg_parms->green_action = ipp_action_lookup(next_action))
165 == IPP_ACTION_INVAL) {
166 nvlist_free(nvlp);
167 tswtcl0dbg(("tswtcl_create_action: green action invalid\n"));
168 kmem_free(cfg_parms, TSWTCL_CFG_SZ);
169 return (EINVAL);
170 }
171
172 /* parse committed rate - in bits / sec */
173 if ((rc = nvlist_lookup_uint32(nvlp, TSWTCL_COMMITTED_RATE,
174 &cfg_parms->committed_rate)) != 0) {
175 nvlist_free(nvlp);
176 tswtcl0dbg(("tswtcl_create_action: invalid config, "\
177 " committed rate missing\n"));
178 kmem_free(cfg_parms, TSWTCL_CFG_SZ);
179 return (rc);
180 }
181
182 /* parse peak rate - in bits / sec */
183 if ((rc = nvlist_lookup_uint32(nvlp, TSWTCL_PEAK_RATE,
184 &cfg_parms->peak_rate)) != 0) {
185 nvlist_free(nvlp);
186 tswtcl0dbg(("tswtcl_create_action: invalid config, "\
187 " peak rate missing\n"));
188 kmem_free(cfg_parms, TSWTCL_CFG_SZ);
189 return (rc);
190 }
191
192 if (cfg_parms->peak_rate < cfg_parms->committed_rate) {
193 nvlist_free(nvlp);
194 tswtcl0dbg(("tswtcl_create_action: invalid config, "\
195 " peak rate < committed rate\n"));
196 kmem_free(cfg_parms, TSWTCL_CFG_SZ);
197 return (EINVAL);
198 }
199
200 /* parse window - in msec */
201 if ((rc = nvlist_lookup_uint32(nvlp, TSWTCL_WINDOW,
202 &cfg_parms->window)) != 0) {
203 nvlist_free(nvlp);
204 tswtcl0dbg(("tswtcl_create_action: invalid config, "\
205 " window missing\n"));
206 kmem_free(cfg_parms, TSWTCL_CFG_SZ);
207 return (rc);
208 }
209 /* convert to nsec */
210 cfg_parms->nsecwindow = (uint64_t)cfg_parms->window *
211 METER_MSEC_TO_NSEC;
212
213 /* parse stats */
214 if ((rc = nvlist_lookup_uint32(nvlp, IPP_ACTION_STATS_ENABLE, &bstats))
215 != 0) {
216 cfg_parms->stats = B_FALSE;
217 } else {
218 cfg_parms->stats = (boolean_t)bstats;
219 }
220
221 nvlist_free(nvlp);
222
223 /* Initialize other stuff */
224 tswtcl_data = kmem_zalloc(TSWTCL_DATA_SZ, KM_NOSLEEP);
225 if (tswtcl_data == NULL) {
226 kmem_free(cfg_parms, TSWTCL_CFG_SZ);
227 return (ENOMEM);
228 }
229
230 if (cfg_parms->stats) {
231 if ((rc = tswtcl_statinit(aid, tswtcl_data)) != 0) {
232 kmem_free(cfg_parms, TSWTCL_CFG_SZ);
233 kmem_free(tswtcl_data, TSWTCL_DATA_SZ);
234 return (rc);
235 }
236 }
237
238 /* set action chain reference */
239 if ((rc = ipp_action_ref(aid, cfg_parms->red_action, flags)) != 0) {
240 tswtcl0dbg(("tswtcl_create_action: ipp_action_ref " \
241 "returned with error %d", rc));
242 goto cleanup;
243 }
244 if ((rc = ipp_action_ref(aid, cfg_parms->yellow_action, flags)) != 0) {
245 tswtcl0dbg(("tswtcl_create_action: ipp_action_ref " \
246 "returned with error %d", rc));
247 rc2 = ipp_action_unref(aid, cfg_parms->red_action, flags);
248 ASSERT(rc2 == 0);
249 goto cleanup;
250 }
251 if ((rc = ipp_action_ref(aid, cfg_parms->green_action, flags)) != 0) {
252 tswtcl0dbg(("tswtcl_create_action: ipp_action_ref " \
253 "returned with error %d", rc));
254 rc2 = ipp_action_unref(aid, cfg_parms->red_action, flags);
255 ASSERT(rc2 == 0);
256 rc2 = ipp_action_unref(aid, cfg_parms->yellow_action, flags);
257 ASSERT(rc2 == 0);
258 goto cleanup;
259 }
260
261 /* Initializations */
262 cfg_parms->pminusc = cfg_parms->peak_rate - cfg_parms->committed_rate;
263 tswtcl_data->cfg_parms = cfg_parms;
264 tswtcl_data->avg_rate = cfg_parms->committed_rate;
265 mutex_init(&tswtcl_data->tswtcl_lock, NULL, MUTEX_DEFAULT, 0);
266 tswtcl_data->win_front = gethrtime();
267 ipp_action_set_ptr(aid, (void *)tswtcl_data);
268
269 return (0);
270
271 cleanup:
272 if (cfg_parms->stats) {
273 ipp_stat_destroy(tswtcl_data->stats);
274 }
275 kmem_free(cfg_parms, TSWTCL_CFG_SZ);
276 kmem_free(tswtcl_data, TSWTCL_DATA_SZ);
277 return (rc);
278
279 }
280
281 static int
tswtcl_modify_action(ipp_action_id_t aid,nvlist_t ** nvlpp,ipp_flags_t flags)282 tswtcl_modify_action(ipp_action_id_t aid, nvlist_t **nvlpp, ipp_flags_t flags)
283 {
284
285 nvlist_t *nvlp;
286 int err = 0, err2;
287 uint8_t config_type;
288 char *next_action_name;
289 ipp_action_id_t next_action;
290 uint32_t rate;
291 tswtcl_cfg_t *cfg_parms, *old_cfg;
292 tswtcl_data_t *tswtcl_data;
293 uint32_t bstats;
294
295 nvlp = *nvlpp;
296 *nvlpp = NULL; /* nvlist should be NULL when this returns */
297
298 if ((err = nvlist_lookup_byte(nvlp, IPP_CONFIG_TYPE, &config_type))
299 != 0) {
300 nvlist_free(nvlp);
301 tswtcl0dbg(("tswtcl_modify_action:invalid configuration type"));
302 return (err);
303 }
304
305 if (config_type != IPP_SET) {
306 nvlist_free(nvlp);
307 tswtcl0dbg(("tswtcl_modify_action:invalid configuration type " \
308 "%d", config_type));
309 return (EINVAL);
310 }
311
312 tswtcl_data = (tswtcl_data_t *)ipp_action_get_ptr(aid);
313 old_cfg = tswtcl_data->cfg_parms;
314
315 cfg_parms = kmem_alloc(TSWTCL_CFG_SZ, KM_NOSLEEP);
316 if (cfg_parms == NULL) {
317 nvlist_free(nvlp);
318 tswtcl0dbg(("tswtcl_modify_action:mem. allocation failure\n"));
319 return (ENOMEM);
320 }
321
322 /* Just copy all and change as needed */
323 bcopy(old_cfg, cfg_parms, TSWTCL_CFG_SZ);
324
325 /* parse red action name, if present */
326 if ((err = nvlist_lookup_string(nvlp, TSWTCL_RED_ACTION_NAME,
327 &next_action_name)) == 0) {
328 /* Get action id */
329 if ((next_action = ipp_action_lookup(next_action_name))
330 == IPP_ACTION_INVAL) {
331 nvlist_free(nvlp);
332 tswtcl0dbg(("tswtcl_modify_action: red next_action"\
333 " invalid\n"));
334 kmem_free(cfg_parms, TSWTCL_CFG_SZ);
335 return (EINVAL);
336 }
337 cfg_parms->red_action = next_action;
338 }
339
340 /* parse yellow action name, if present */
341 if ((err = nvlist_lookup_string(nvlp, TSWTCL_YELLOW_ACTION_NAME,
342 &next_action_name)) == 0) {
343 /* Get action id */
344 if ((next_action = ipp_action_lookup(next_action_name))
345 == IPP_ACTION_INVAL) {
346 nvlist_free(nvlp);
347 tswtcl0dbg(("tswtcl_modify_action: yellow next_action"\
348 " invalid\n"));
349 kmem_free(cfg_parms, TSWTCL_CFG_SZ);
350 return (EINVAL);
351 }
352 cfg_parms->yellow_action = next_action;
353 }
354
355 /* parse green action name, if present */
356 if ((err = nvlist_lookup_string(nvlp, TSWTCL_GREEN_ACTION_NAME,
357 &next_action_name)) == 0) {
358 /* Get action id */
359 if ((next_action = ipp_action_lookup(next_action_name))
360 == IPP_ACTION_INVAL) {
361 nvlist_free(nvlp);
362 tswtcl0dbg(("tswtcl_modify_action: green next_action"\
363 " invalid\n"));
364 kmem_free(cfg_parms, TSWTCL_CFG_SZ);
365 return (EINVAL);
366 }
367 cfg_parms->green_action = next_action;
368 }
369
370 /* parse committed rate, if present */
371 if ((err = nvlist_lookup_uint32(nvlp, TSWTCL_COMMITTED_RATE, &rate))
372 == 0) {
373 cfg_parms->committed_rate = rate;
374 }
375
376 /* parse peak rate, if present */
377 if ((err = nvlist_lookup_uint32(nvlp, TSWTCL_PEAK_RATE, &rate))
378 == 0) {
379 cfg_parms->peak_rate = rate;
380 }
381
382 if (cfg_parms->peak_rate < cfg_parms->committed_rate) {
383 nvlist_free(nvlp);
384 tswtcl0dbg(("tswtcl_create_action: invalid config, "\
385 " peak rate < committed rate\n"));
386 kmem_free(cfg_parms, TSWTCL_CFG_SZ);
387 return (EINVAL);
388 }
389
390 /* parse window - in msec */
391 if ((err = nvlist_lookup_uint32(nvlp, TSWTCL_WINDOW,
392 &cfg_parms->window)) != 0) {
393 cfg_parms->nsecwindow = (uint64_t)cfg_parms->window *
394 METER_MSEC_TO_NSEC;
395 }
396
397 /* parse stats, if present */
398 if (nvlist_lookup_uint32(nvlp, IPP_ACTION_STATS_ENABLE, &bstats) == 0) {
399 cfg_parms->stats = (boolean_t)bstats;
400 if (cfg_parms->stats && !old_cfg->stats) {
401 if ((err = tswtcl_statinit(aid, tswtcl_data)) != 0) {
402 nvlist_free(nvlp);
403 kmem_free(cfg_parms, TSWTCL_CFG_SZ);
404 return (err);
405 }
406 } else if (!cfg_parms->stats && old_cfg->stats) {
407 ipp_stat_destroy(tswtcl_data->stats);
408 }
409 }
410
411 /* Can we ref all the new actions? */
412 if ((err = ipp_action_ref(aid, cfg_parms->red_action, flags)) != 0) {
413 tswtcl0dbg(("tswtcl_modify_data: can't ref. red action\n"));
414 nvlist_free(nvlp);
415 kmem_free(cfg_parms, TSWTCL_CFG_SZ);
416 return (err);
417 }
418
419 if ((err = ipp_action_ref(aid, cfg_parms->yellow_action, flags)) != 0) {
420 tswtcl0dbg(("tswtcl_modify_data:can't ref. yellow action\n"));
421 nvlist_free(nvlp);
422 err2 = ipp_action_unref(aid, cfg_parms->red_action, flags);
423 ASSERT(err2 == 0);
424 kmem_free(cfg_parms, TSWTCL_CFG_SZ);
425 return (err);
426 }
427
428 if ((err = ipp_action_ref(aid, cfg_parms->green_action, flags)) != 0) {
429 tswtcl0dbg(("tswtcl_modify_data:can't ref. green action\n"));
430 nvlist_free(nvlp);
431 err2 = ipp_action_unref(aid, cfg_parms->red_action, flags);
432 ASSERT(err2 == 0);
433 err2 = ipp_action_unref(aid, cfg_parms->yellow_action, flags);
434 ASSERT(err2 == 0);
435 kmem_free(cfg_parms, TSWTCL_CFG_SZ);
436 return (err);
437 }
438
439 /* Re-compute pminusc */
440 cfg_parms->pminusc = cfg_parms->peak_rate - cfg_parms->committed_rate;
441
442 /* Actually modify the configuration */
443 mutex_enter(&tswtcl_data->tswtcl_lock);
444 tswtcl_data->cfg_parms = cfg_parms;
445 mutex_exit(&tswtcl_data->tswtcl_lock);
446
447 /* Un-ref the old actions */
448 err = ipp_action_unref(aid, old_cfg->red_action, flags);
449 ASSERT(err == 0);
450 err = ipp_action_unref(aid, old_cfg->yellow_action, flags);
451 ASSERT(err == 0);
452 err = ipp_action_unref(aid, old_cfg->green_action, flags);
453 ASSERT(err == 0);
454
455 /* Free the old configuration */
456 kmem_free(old_cfg, TSWTCL_CFG_SZ);
457
458 nvlist_free(nvlp);
459
460 return (0);
461 }
462
463 static int
tswtcl_destroy_action(ipp_action_id_t aid,ipp_flags_t flags)464 tswtcl_destroy_action(ipp_action_id_t aid, ipp_flags_t flags)
465 {
466 tswtcl_data_t *tswtcl_data;
467 tswtcl_cfg_t *cfg_parms;
468 int rc;
469
470 tswtcl_data = (tswtcl_data_t *)ipp_action_get_ptr(aid);
471 ASSERT(tswtcl_data != NULL);
472
473 cfg_parms = tswtcl_data->cfg_parms;
474
475 if (cfg_parms->stats) {
476 ipp_stat_destroy(tswtcl_data->stats);
477 }
478
479 /* unreference the action */
480 rc = ipp_action_unref(aid, cfg_parms->red_action, flags);
481 ASSERT(rc == 0);
482 rc = ipp_action_unref(aid, cfg_parms->yellow_action, flags);
483 ASSERT(rc == 0);
484 rc = ipp_action_unref(aid, cfg_parms->green_action, flags);
485 ASSERT(rc == 0);
486
487 mutex_destroy(&tswtcl_data->tswtcl_lock);
488 kmem_free(cfg_parms, TSWTCL_CFG_SZ);
489 kmem_free(tswtcl_data, TSWTCL_DATA_SZ);
490 return (0);
491 }
492
493 static int
tswtcl_invoke_action(ipp_action_id_t aid,ipp_packet_t * packet)494 tswtcl_invoke_action(ipp_action_id_t aid, ipp_packet_t *packet)
495 {
496 tswtcl_data_t *tswtcl_data;
497 ipp_action_id_t next_action;
498 mblk_t *mp = NULL;
499 int rc;
500
501 /* get mblk from ipp_packet structure */
502 mp = ipp_packet_get_data(packet);
503 tswtcl_data = (tswtcl_data_t *)ipp_action_get_ptr(aid);
504 ASSERT(tswtcl_data != NULL);
505
506 /* tswtcl packet as configured */
507 if ((rc = tswtcl_process(&mp, tswtcl_data, &next_action)) != 0) {
508 return (rc);
509 } else {
510 return (ipp_packet_next(packet, next_action));
511 }
512 }
513
514 static int
tswtcl_statinit(ipp_action_id_t aid,tswtcl_data_t * tswtcl_data)515 tswtcl_statinit(ipp_action_id_t aid, tswtcl_data_t *tswtcl_data)
516 {
517 int rc = 0;
518 meter_stat_t *statsp;
519
520 /* install stats entry */
521 if ((rc = ipp_stat_create(aid, TSWTCL_STATS_STRING, METER_STATS_COUNT,
522 tswtcl_update_stats, tswtcl_data, &tswtcl_data->stats)) != 0) {
523 tswtcl0dbg(("tswtcl_statinit:ipp_stat_create failed "\
524 " with %d\n", rc));
525 return (rc);
526 }
527
528 statsp = (meter_stat_t *)(tswtcl_data->stats)->ipps_data;
529 ASSERT(statsp != NULL);
530
531 if ((rc = ipp_stat_named_init(tswtcl_data->stats, "red_packets",
532 IPP_STAT_UINT64, &statsp->red_packets)) != 0) {
533 tswtcl0dbg(("tswtcl_statinit:ipp_stat_create failed "\
534 " with %d\n", rc));
535 return (rc);
536 }
537 if ((rc = ipp_stat_named_init(tswtcl_data->stats, "red_bits",
538 IPP_STAT_UINT64, &statsp->red_bits)) != 0) {
539 tswtcl0dbg(("tswtcl_statinit:ipp_stat_create failed "\
540 " with %d\n", rc));
541 return (rc);
542 }
543 if ((rc = ipp_stat_named_init(tswtcl_data->stats, "yellow_packets",
544 IPP_STAT_UINT64, &statsp->yellow_packets)) != 0) {
545 tswtcl0dbg(("tswtcl_statinit:ipp_stat_named_init failed "\
546 " with %d\n", rc));
547 return (rc);
548 }
549 if ((rc = ipp_stat_named_init(tswtcl_data->stats, "yellow_bits",
550 IPP_STAT_UINT64, &statsp->yellow_bits)) != 0) {
551 tswtcl0dbg(("tswtcl_statinit:ipp_stat_create failed "\
552 " with %d\n", rc));
553 return (rc);
554 }
555 if ((rc = ipp_stat_named_init(tswtcl_data->stats, "green_packets",
556 IPP_STAT_UINT64, &statsp->green_packets)) != 0) {
557 tswtcl0dbg(("tswtcl_statinit:ipp_stat_named_init failed "\
558 " with %d\n", rc));
559 return (rc);
560 }
561 if ((rc = ipp_stat_named_init(tswtcl_data->stats, "green_bits",
562 IPP_STAT_UINT64, &statsp->green_bits)) != 0) {
563 tswtcl0dbg(("tswtcl_statinit:ipp_stat_create failed "\
564 " with %d\n", rc));
565 return (rc);
566 }
567 if ((rc = ipp_stat_named_init(tswtcl_data->stats, "epackets",
568 IPP_STAT_UINT64, &statsp->epackets)) != 0) {
569 tswtcl0dbg(("tswtcl_statinit:ipp_stat_named_init failed "\
570 " with %d\n", rc));
571 return (rc);
572 }
573 ipp_stat_install(tswtcl_data->stats);
574
575 return (rc);
576
577 }
578
579 static int
tswtcl_update_stats(ipp_stat_t * sp,void * args,int rw)580 tswtcl_update_stats(ipp_stat_t *sp, void *args, int rw)
581 {
582 tswtcl_data_t *tswtcl_data = (tswtcl_data_t *)args;
583 meter_stat_t *stats = (meter_stat_t *)sp->ipps_data;
584
585 ASSERT((tswtcl_data != NULL) && (stats != NULL));
586
587 (void) ipp_stat_named_op(&stats->red_packets, &tswtcl_data->red_packets,
588 rw);
589 (void) ipp_stat_named_op(&stats->yellow_packets,
590 &tswtcl_data->yellow_packets, rw);
591 (void) ipp_stat_named_op(&stats->green_packets,
592 &tswtcl_data->green_packets, rw);
593
594 (void) ipp_stat_named_op(&stats->red_bits, &tswtcl_data->red_bits, rw);
595 (void) ipp_stat_named_op(&stats->yellow_bits,
596 &tswtcl_data->yellow_bits, rw);
597 (void) ipp_stat_named_op(&stats->green_bits,
598 &tswtcl_data->green_bits, rw);
599
600 (void) ipp_stat_named_op(&stats->epackets, &tswtcl_data->epackets,
601 rw);
602
603 return (0);
604 }
605
606 /* ARGSUSED */
607 static int
tswtcl_info(ipp_action_id_t aid,int (* fn)(nvlist_t *,void *),void * arg,ipp_flags_t flags)608 tswtcl_info(ipp_action_id_t aid, int (*fn)(nvlist_t *, void *), void *arg,
609 ipp_flags_t flags)
610 {
611 nvlist_t *nvlp;
612 tswtcl_data_t *tswtcl_data;
613 tswtcl_cfg_t *cfg_parms;
614 char *next_action;
615 int rc;
616
617 tswtcl_data = (tswtcl_data_t *)ipp_action_get_ptr(aid);
618 ASSERT(tswtcl_data != NULL);
619
620 cfg_parms = tswtcl_data->cfg_parms;
621
622 /* allocate nvlist to be passed back */
623 if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, KM_NOSLEEP)) != 0) {
624 tswtcl0dbg(("tswtcl_info: memory allocation failure\n"));
625 return (rc);
626 }
627
628 /* look up red next action with the next action id */
629 if ((rc = ipp_action_name(cfg_parms->red_action, &next_action)) != 0) {
630 tswtcl0dbg(("tswtcl_info: red action not available\n"));
631 nvlist_free(nvlp);
632 return (rc);
633 }
634
635 /* add next action name */
636 if ((rc = nvlist_add_string(nvlp, TSWTCL_RED_ACTION_NAME,
637 next_action)) != 0) {
638 tswtcl0dbg(("tswtcl_info: error adding\n"));
639 nvlist_free(nvlp);
640 kmem_free(next_action, (strlen(next_action) + 1));
641 return (rc);
642 }
643
644 /* free action name */
645 kmem_free(next_action, (strlen(next_action) + 1));
646
647 /* look up yellow next action with the next action id */
648 if ((rc = ipp_action_name(cfg_parms->yellow_action,
649 &next_action)) != 0) {
650 tswtcl0dbg(("tswtcl_info: yellow action not available\n"));
651 nvlist_free(nvlp);
652 return (rc);
653 }
654
655 /* add next action name */
656 if ((rc = nvlist_add_string(nvlp, TSWTCL_YELLOW_ACTION_NAME,
657 next_action)) != 0) {
658 tswtcl0dbg(("tswtcl_info: error adding yellow action\n"));
659 nvlist_free(nvlp);
660 kmem_free(next_action, (strlen(next_action) + 1));
661 return (rc);
662 }
663 /* free action name */
664 kmem_free(next_action, (strlen(next_action) + 1));
665
666 /* look up green next action with the next action id */
667 if ((rc = ipp_action_name(cfg_parms->green_action,
668 &next_action)) != 0) {
669 tswtcl0dbg(("tswtcl_info: green action not available\n"));
670 nvlist_free(nvlp);
671 return (rc);
672 }
673
674 /* add next action name */
675 if ((rc = nvlist_add_string(nvlp, TSWTCL_GREEN_ACTION_NAME,
676 next_action)) != 0) {
677 tswtcl0dbg(("tswtcl_info: error adding green action\n"));
678 nvlist_free(nvlp);
679 kmem_free(next_action, (strlen(next_action) + 1));
680 return (rc);
681 }
682
683 /* free action name */
684 kmem_free(next_action, (strlen(next_action) + 1));
685
686 /* add config type */
687 if ((rc = nvlist_add_byte(nvlp, IPP_CONFIG_TYPE, IPP_SET)) != 0) {
688 tswtcl0dbg(("tswtcl_info: error adding config_type\n"));
689 nvlist_free(nvlp);
690 return (rc);
691 }
692
693 /* add committed_rate */
694 if ((rc = nvlist_add_uint32(nvlp, TSWTCL_COMMITTED_RATE,
695 cfg_parms->committed_rate)) != 0) {
696 tswtcl0dbg(("tswtcl_info: error adding committed_rate\n"));
697 nvlist_free(nvlp);
698 return (rc);
699 }
700
701 /* add peak_rate */
702 if ((rc = nvlist_add_uint32(nvlp, TSWTCL_PEAK_RATE,
703 cfg_parms->peak_rate)) != 0) {
704 tswtcl0dbg(("tswtcl_info: error adding peak_rate\n"));
705 nvlist_free(nvlp);
706 return (rc);
707 }
708
709 /* add window */
710 if ((rc = nvlist_add_uint32(nvlp, TSWTCL_WINDOW,
711 cfg_parms->window)) != 0) {
712 tswtcl0dbg(("tswtcl_info: error adding window\n"));
713 nvlist_free(nvlp);
714 return (rc);
715 }
716
717 if ((rc = nvlist_add_uint32(nvlp, IPP_ACTION_STATS_ENABLE,
718 (uint32_t)(uintptr_t)tswtcl_data->stats)) != 0) {
719 tswtcl0dbg(("tswtcl_info: error adding stats status\n"));
720 nvlist_free(nvlp);
721 return (rc);
722 }
723
724 /* call back with nvlist */
725 rc = fn(nvlp, arg);
726
727 nvlist_free(nvlp);
728 return (rc);
729 }
730