2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
17 #include <vnet/policer/policer.h>
18 #include <vnet/policer/police_inlines.h>
19 #include <vnet/classify/vnet_classify.h>
20 #include <vnet/ip/ip_packet.h>
22 vnet_policer_main_t vnet_policer_main;
25 format_policer_handoff_trace (u8 *s, va_list *args)
27 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
28 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
29 policer_handoff_trace_t *t = va_arg (*args, policer_handoff_trace_t *);
31 s = format (s, "policer %d, handoff thread %d to %d", t->policer_index,
32 t->current_worker_index, t->next_worker_index);
37 vlib_combined_counter_main_t policer_counters[] = {
39 .name = "Policer-Conform",
40 .stat_segment_name = "/net/policer/conform",
43 .name = "Policer-Exceed",
44 .stat_segment_name = "/net/policer/exceed",
47 .name = "Policer-Violate",
48 .stat_segment_name = "/net/policer/violate",
53 policer_add (vlib_main_t *vm, const u8 *name, const qos_pol_cfg_params_st *cfg,
56 vnet_policer_main_t *pm = &vnet_policer_main;
57 policer_t test_policer;
60 qos_pol_cfg_params_st *cp;
66 p = hash_get_mem (pm->policer_config_by_name, name);
69 return VNET_API_ERROR_VALUE_EXIST;
71 /* Vet the configuration before adding it to the table */
72 rv = pol_logical_2_physical (cfg, &test_policer);
75 return VNET_API_ERROR_INVALID_VALUE;
77 pool_get (pm->configs, cp);
78 pool_get_aligned (pm->policers, policer, CLIB_CACHE_LINE_BYTES);
80 clib_memcpy (cp, cfg, sizeof (*cp));
81 clib_memcpy (policer, &test_policer, sizeof (*pp));
83 policer->name = format (0, "%s%c", name, 0);
84 pi = policer - pm->policers;
86 hash_set_mem (pm->policer_config_by_name, policer->name, cp - pm->configs);
87 hash_set_mem (pm->policer_index_by_name, policer->name, pi);
89 policer->thread_index = ~0;
91 for (i = 0; i < NUM_POLICE_RESULTS; i++)
93 vlib_validate_combined_counter (&policer_counters[i], pi);
94 vlib_zero_combined_counter (&policer_counters[i], pi);
101 policer_del (vlib_main_t *vm, u32 policer_index)
103 vnet_policer_main_t *pm = &vnet_policer_main;
107 if (pool_is_free_index (pm->policers, policer_index))
108 return VNET_API_ERROR_NO_SUCH_ENTRY;
110 policer = &pm->policers[policer_index];
112 p = hash_get_mem (pm->policer_config_by_name, policer->name);
114 /* free policer config */
117 pool_put_index (pm->configs, p[0]);
118 hash_unset_mem (pm->policer_config_by_name, policer->name);
122 hash_unset_mem (pm->policer_index_by_name, policer->name);
123 vec_free (policer->name);
124 pool_put_index (pm->policers, policer_index);
130 policer_update (vlib_main_t *vm, u32 policer_index,
131 const qos_pol_cfg_params_st *cfg)
133 vnet_policer_main_t *pm = &vnet_policer_main;
134 policer_t test_policer;
136 qos_pol_cfg_params_st *cp;
142 if (pool_is_free_index (pm->policers, policer_index))
143 return VNET_API_ERROR_NO_SUCH_ENTRY;
145 policer = &pm->policers[policer_index];
147 /* Vet the configuration before adding it to the table */
148 rv = pol_logical_2_physical (cfg, &test_policer);
150 return VNET_API_ERROR_INVALID_VALUE;
152 p = hash_get_mem (pm->policer_config_by_name, policer->name);
154 if (PREDICT_TRUE (p != NULL))
156 cp = &pm->configs[p[0]];
160 /* recover from a missing configuration */
161 pool_get (pm->configs, cp);
162 hash_set_mem (pm->policer_config_by_name, policer->name,
166 name = policer->name;
168 clib_memcpy (cp, cfg, sizeof (*cp));
169 clib_memcpy (policer, &test_policer, sizeof (*policer));
171 policer->name = name;
172 policer->thread_index = ~0;
174 for (i = 0; i < NUM_POLICE_RESULTS; i++)
175 vlib_zero_combined_counter (&policer_counters[i], policer_index);
181 policer_reset (vlib_main_t *vm, u32 policer_index)
183 vnet_policer_main_t *pm = &vnet_policer_main;
186 if (pool_is_free_index (pm->policers, policer_index))
187 return VNET_API_ERROR_NO_SUCH_ENTRY;
189 policer = &pm->policers[policer_index];
191 policer->current_bucket = policer->current_limit;
192 policer->extended_bucket = policer->extended_limit;
198 policer_bind_worker (u32 policer_index, u32 worker, bool bind)
200 vnet_policer_main_t *pm = &vnet_policer_main;
203 if (pool_is_free_index (pm->policers, policer_index))
204 return VNET_API_ERROR_NO_SUCH_ENTRY;
206 policer = &pm->policers[policer_index];
210 if (worker >= vlib_num_workers ())
212 return VNET_API_ERROR_INVALID_WORKER;
215 policer->thread_index = vlib_get_worker_thread_index (worker);
219 policer->thread_index = ~0;
225 policer_input (u32 policer_index, u32 sw_if_index, vlib_dir_t dir, bool apply)
227 vnet_policer_main_t *pm = &vnet_policer_main;
231 vec_validate (pm->policer_index_by_sw_if_index[dir], sw_if_index);
232 pm->policer_index_by_sw_if_index[dir][sw_if_index] = policer_index;
236 pm->policer_index_by_sw_if_index[dir][sw_if_index] = ~0;
241 vnet_feature_enable_disable ("device-input", "policer-input",
242 sw_if_index, apply, 0, 0);
246 vnet_feature_enable_disable ("ip4-output", "policer-output", sw_if_index,
248 vnet_feature_enable_disable ("ip6-output", "policer-output", sw_if_index,
255 format_policer_instance (u8 * s, va_list * va)
257 vnet_policer_main_t *pm = &vnet_policer_main;
258 policer_t *i = va_arg (*va, policer_t *);
259 u32 policer_index = i - pm->policers;
261 vlib_counter_t counts[NUM_POLICE_RESULTS];
263 for (result = 0; result < NUM_POLICE_RESULTS; result++)
265 vlib_get_combined_counter (&policer_counters[result], policer_index,
270 format (s, "Policer at index %d: %s rate, %s color-aware\n", policer_index,
271 i->single_rate ? "single" : "dual", i->color_aware ? "is" : "not");
272 s = format (s, "cir %u tok/period, pir %u tok/period, scale %u\n",
273 i->cir_tokens_per_period, i->pir_tokens_per_period, i->scale);
274 s = format (s, "cur lim %u, cur bkt %u, ext lim %u, ext bkt %u\n",
276 i->current_bucket, i->extended_limit, i->extended_bucket);
277 s = format (s, "last update %llu\n", i->last_update_time);
278 s = format (s, "conform %llu packets, %llu bytes\n",
279 counts[POLICE_CONFORM].packets, counts[POLICE_CONFORM].bytes);
280 s = format (s, "exceed %llu packets, %llu bytes\n",
281 counts[POLICE_EXCEED].packets, counts[POLICE_EXCEED].bytes);
282 s = format (s, "violate %llu packets, %llu bytes\n",
283 counts[POLICE_VIOLATE].packets, counts[POLICE_VIOLATE].bytes);
288 format_policer_round_type (u8 * s, va_list * va)
290 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
292 if (c->rnd_type == QOS_ROUND_TO_CLOSEST)
293 s = format (s, "closest");
294 else if (c->rnd_type == QOS_ROUND_TO_UP)
295 s = format (s, "up");
296 else if (c->rnd_type == QOS_ROUND_TO_DOWN)
297 s = format (s, "down");
299 s = format (s, "ILLEGAL");
305 format_policer_rate_type (u8 * s, va_list * va)
307 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
309 if (c->rate_type == QOS_RATE_KBPS)
310 s = format (s, "kbps");
311 else if (c->rate_type == QOS_RATE_PPS)
312 s = format (s, "pps");
314 s = format (s, "ILLEGAL");
319 format_policer_type (u8 * s, va_list * va)
321 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
323 if (c->rfc == QOS_POLICER_TYPE_1R2C)
324 s = format (s, "1r2c");
326 else if (c->rfc == QOS_POLICER_TYPE_1R3C_RFC_2697)
327 s = format (s, "1r3c");
329 else if (c->rfc == QOS_POLICER_TYPE_2R3C_RFC_2698)
330 s = format (s, "2r3c-2698");
332 else if (c->rfc == QOS_POLICER_TYPE_2R3C_RFC_4115)
333 s = format (s, "2r3c-4115");
335 else if (c->rfc == QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1)
336 s = format (s, "2r3c-mef5cf1");
338 s = format (s, "ILLEGAL");
343 format_policer_action_type (u8 * s, va_list * va)
345 qos_pol_action_params_st *a = va_arg (*va, qos_pol_action_params_st *);
347 if (a->action_type == QOS_ACTION_DROP)
348 s = format (s, "drop");
349 else if (a->action_type == QOS_ACTION_TRANSMIT)
350 s = format (s, "transmit");
351 else if (a->action_type == QOS_ACTION_MARK_AND_TRANSMIT)
352 s = format (s, "mark-and-transmit %U", format_ip_dscp, a->dscp);
354 s = format (s, "ILLEGAL");
359 format_policer_config (u8 * s, va_list * va)
361 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
363 s = format (s, "type %U cir %u eir %u cb %u eb %u\n",
364 format_policer_type, c,
366 c->rb.kbps.eir_kbps, c->rb.kbps.cb_bytes, c->rb.kbps.eb_bytes);
367 s = format (s, "rate type %U, round type %U\n",
368 format_policer_rate_type, c, format_policer_round_type, c);
369 s = format (s, "conform action %U, exceed action %U, violate action %U\n",
370 format_policer_action_type, &c->conform_action,
371 format_policer_action_type, &c->exceed_action,
372 format_policer_action_type, &c->violate_action);
377 unformat_policer_type (unformat_input_t * input, va_list * va)
379 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
381 if (!unformat (input, "type"))
384 if (unformat (input, "1r2c"))
385 c->rfc = QOS_POLICER_TYPE_1R2C;
386 else if (unformat (input, "1r3c"))
387 c->rfc = QOS_POLICER_TYPE_1R3C_RFC_2697;
388 else if (unformat (input, "2r3c-2698"))
389 c->rfc = QOS_POLICER_TYPE_2R3C_RFC_2698;
390 else if (unformat (input, "2r3c-4115"))
391 c->rfc = QOS_POLICER_TYPE_2R3C_RFC_4115;
392 else if (unformat (input, "2r3c-mef5cf1"))
393 c->rfc = QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1;
400 unformat_policer_round_type (unformat_input_t * input, va_list * va)
402 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
404 if (!unformat (input, "round"))
407 if (unformat (input, "closest"))
408 c->rnd_type = QOS_ROUND_TO_CLOSEST;
409 else if (unformat (input, "up"))
410 c->rnd_type = QOS_ROUND_TO_UP;
411 else if (unformat (input, "down"))
412 c->rnd_type = QOS_ROUND_TO_DOWN;
419 unformat_policer_rate_type (unformat_input_t * input, va_list * va)
421 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
423 if (!unformat (input, "rate"))
426 if (unformat (input, "kbps"))
427 c->rate_type = QOS_RATE_KBPS;
428 else if (unformat (input, "pps"))
429 c->rate_type = QOS_RATE_PPS;
436 unformat_policer_cir (unformat_input_t * input, va_list * va)
438 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
440 if (unformat (input, "cir %u", &c->rb.kbps.cir_kbps))
446 unformat_policer_eir (unformat_input_t * input, va_list * va)
448 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
450 if (unformat (input, "eir %u", &c->rb.kbps.eir_kbps))
456 unformat_policer_cb (unformat_input_t * input, va_list * va)
458 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
460 if (unformat (input, "cb %u", &c->rb.kbps.cb_bytes))
466 unformat_policer_eb (unformat_input_t * input, va_list * va)
468 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
470 if (unformat (input, "eb %u", &c->rb.kbps.eb_bytes))
476 unformat_policer_action_type (unformat_input_t * input, va_list * va)
478 qos_pol_action_params_st *a = va_arg (*va, qos_pol_action_params_st *);
480 if (unformat (input, "drop"))
481 a->action_type = QOS_ACTION_DROP;
482 else if (unformat (input, "transmit"))
483 a->action_type = QOS_ACTION_TRANSMIT;
484 else if (unformat (input, "mark-and-transmit %U", unformat_ip_dscp,
486 a->action_type = QOS_ACTION_MARK_AND_TRANSMIT;
493 unformat_policer_action (unformat_input_t * input, va_list * va)
495 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
497 if (unformat (input, "conform-action %U", unformat_policer_action_type,
500 else if (unformat (input, "exceed-action %U", unformat_policer_action_type,
503 else if (unformat (input, "violate-action %U", unformat_policer_action_type,
510 unformat_policer_classify_next_index (unformat_input_t * input, va_list * va)
512 u32 *r = va_arg (*va, u32 *);
513 vnet_policer_main_t *pm = &vnet_policer_main;
517 if (unformat (input, "%s", &match_name))
522 p = hash_get_mem (pm->policer_index_by_name, match_name);
523 vec_free (match_name);
534 unformat_policer_classify_precolor (unformat_input_t * input, va_list * va)
536 u32 *r = va_arg (*va, u32 *);
538 if (unformat (input, "conform-color"))
540 else if (unformat (input, "exceed-color"))
548 #define foreach_config_param \
558 static clib_error_t *
559 policer_add_command_fn (vlib_main_t *vm, unformat_input_t *input,
560 vlib_cli_command_t *cmd)
562 vnet_policer_main_t *pm = &vnet_policer_main;
563 qos_pol_cfg_params_st c;
564 unformat_input_t _line_input, *line_input = &_line_input;
568 u32 policer_index = ~0;
570 clib_error_t *error = NULL;
571 u8 is_update = cmd->function_arg;
573 /* Get a line of input. */
574 if (!unformat_user (input, unformat_line_input, line_input))
577 clib_memset (&c, 0, sizeof (c));
579 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
581 if (unformat (line_input, "name %s", &name))
583 else if (is_update && unformat (line_input, "index %u", &policer_index))
585 else if (unformat (line_input, "color-aware"))
588 #define _(a) else if (unformat (line_input, "%U", unformat_policer_##a, &c)) ;
593 error = clib_error_return (0, "unknown input `%U'",
594 format_unformat_error, line_input);
601 if (~0 == policer_index && 0 != name)
603 p = hash_get_mem (pm->policer_index_by_name, name);
605 policer_index = p[0];
608 if (~0 != policer_index)
610 rv = policer_update (vm, policer_index, &c);
615 rv = policer_add (vm, name, &c, &pi);
620 case VNET_API_ERROR_NO_SUCH_ENTRY:
621 error = clib_error_return (0, "No such policer");
623 case VNET_API_ERROR_VALUE_EXIST:
624 error = clib_error_return (0, "Policer already exists");
626 case VNET_API_ERROR_INVALID_VALUE:
627 error = clib_error_return (0, "Config failed sanity check");
632 unformat_free (line_input);
638 static clib_error_t *
639 policer_del_command_fn (vlib_main_t *vm, unformat_input_t *input,
640 vlib_cli_command_t *cmd)
642 unformat_input_t _line_input, *line_input = &_line_input;
643 clib_error_t *error = NULL;
644 vnet_policer_main_t *pm = &vnet_policer_main;
646 u32 policer_index = ~0;
650 /* Get a line of input. */
651 if (!unformat_user (input, unformat_line_input, line_input))
654 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
656 if (unformat (line_input, "name %s", &name))
658 else if (unformat (line_input, "index %u", &policer_index))
662 error = clib_error_return (0, "unknown input `%U'",
663 format_unformat_error, line_input);
668 if (~0 == policer_index && 0 != name)
670 p = hash_get_mem (pm->policer_index_by_name, name);
672 policer_index = p[0];
675 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
676 if (~0 != policer_index)
677 rv = policer_del (vm, policer_index);
681 case VNET_API_ERROR_INVALID_VALUE:
682 error = clib_error_return (0, "No such policer configuration");
684 case VNET_API_ERROR_NO_SUCH_ENTRY:
685 error = clib_error_return (0, "No such policer");
690 unformat_free (line_input);
696 static clib_error_t *
697 policer_bind_command_fn (vlib_main_t *vm, unformat_input_t *input,
698 vlib_cli_command_t *cmd)
700 unformat_input_t _line_input, *line_input = &_line_input;
701 clib_error_t *error = NULL;
702 vnet_policer_main_t *pm = &vnet_policer_main;
706 u32 policer_index = ~0;
710 /* Get a line of input. */
711 if (!unformat_user (input, unformat_line_input, line_input))
714 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
716 if (unformat (line_input, "name %s", &name))
718 else if (unformat (line_input, "index %u", &policer_index))
720 else if (unformat (line_input, "unbind"))
722 else if (unformat (line_input, "%d", &worker))
726 error = clib_error_return (0, "unknown input `%U'",
727 format_unformat_error, line_input);
732 if (bind && ~0 == worker)
734 error = clib_error_return (0, "specify worker to bind to: `%U'",
735 format_unformat_error, line_input);
739 if (~0 == policer_index && 0 != name)
741 p = hash_get_mem (pm->policer_index_by_name, name);
743 policer_index = p[0];
746 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
747 if (~0 != policer_index)
748 rv = policer_bind_worker (policer_index, worker, bind);
751 error = clib_error_return (0, "failed: `%d'", rv);
755 unformat_free (line_input);
761 static clib_error_t *
762 policer_input_command_fn (vlib_main_t *vm, unformat_input_t *input,
763 vlib_cli_command_t *cmd)
765 unformat_input_t _line_input, *line_input = &_line_input;
766 clib_error_t *error = NULL;
767 vnet_policer_main_t *pm = &vnet_policer_main;
770 u32 sw_if_index = ~0;
771 u32 policer_index = ~0;
774 vlib_dir_t dir = cmd->function_arg;
776 /* Get a line of input. */
777 if (!unformat_user (input, unformat_line_input, line_input))
780 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
782 if (unformat (line_input, "name %s", &name))
784 else if (unformat (line_input, "index %u", &policer_index))
786 else if (unformat (line_input, "unapply"))
788 else if (unformat (line_input, "%U", unformat_vnet_sw_interface,
789 vnet_get_main (), &sw_if_index))
793 error = clib_error_return (0, "unknown input `%U'",
794 format_unformat_error, line_input);
799 if (~0 == sw_if_index)
801 error = clib_error_return (0, "specify interface to apply to: `%U'",
802 format_unformat_error, line_input);
806 if (~0 == policer_index && 0 != name)
808 p = hash_get_mem (pm->policer_index_by_name, name);
810 policer_index = p[0];
813 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
814 if (~0 != policer_index)
815 rv = policer_input (policer_index, sw_if_index, dir, apply);
818 error = clib_error_return (0, "failed: `%d'", rv);
822 unformat_free (line_input);
828 static clib_error_t *
829 policer_reset_command_fn (vlib_main_t *vm, unformat_input_t *input,
830 vlib_cli_command_t *cmd)
832 unformat_input_t _line_input, *line_input = &_line_input;
833 clib_error_t *error = NULL;
834 vnet_policer_main_t *pm = &vnet_policer_main;
836 u32 policer_index = ~0;
840 /* Get a line of input. */
841 if (!unformat_user (input, unformat_line_input, line_input))
844 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
846 if (unformat (line_input, "name %s", &name))
848 else if (unformat (line_input, "index %u", &policer_index))
852 error = clib_error_return (0, "unknown input `%U'",
853 format_unformat_error, line_input);
858 if (~0 == policer_index && 0 != name)
860 p = hash_get_mem (pm->policer_index_by_name, name);
862 policer_index = p[0];
865 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
866 if (~0 != policer_index)
867 rv = policer_reset (vm, policer_index);
871 case VNET_API_ERROR_NO_SUCH_ENTRY:
872 error = clib_error_return (0, "No such policer");
877 unformat_free (line_input);
883 VLIB_CLI_COMMAND (configure_policer_command, static) = {
884 .path = "configure policer",
885 .short_help = "configure policer [name <name> | index <index>] [type 1r2c | "
887 "| 2r3c-4115] [color-aware] [cir <cir>] [cb <cb>] [eir <eir>] "
888 "[eb <eb>] [rate kbps | pps] [round closest | up | down] "
889 "[conform-action drop | transmit | mark-and-transmit <dscp>] "
890 "[exceed-action drop | transmit | mark-and-transmit <dscp>] "
891 "[violate-action drop | transmit | mark-and-transmit <dscp>]",
892 .function = policer_add_command_fn,
896 VLIB_CLI_COMMAND (policer_add_command, static) = {
897 .path = "policer add",
898 .short_help = "policer add name <name> [type 1r2c | 1r3c | 2r3c-2698 | "
899 "2r3c-4115] [color-aware] [cir <cir>] [cb <cb>] [eir <eir>] "
900 "[eb <eb>] [rate kbps | pps] [round closest | up | down] "
901 "[conform-action drop | transmit | mark-and-transmit <dscp>] "
902 "[exceed-action drop | transmit | mark-and-transmit <dscp>] "
903 "[violate-action drop | transmit | mark-and-transmit <dscp>]",
904 .function = policer_add_command_fn,
908 VLIB_CLI_COMMAND (policer_del_command, static) = {
909 .path = "policer del",
910 .short_help = "policer del [name <name> | index <index>]",
911 .function = policer_del_command_fn,
914 VLIB_CLI_COMMAND (policer_bind_command, static) = {
915 .path = "policer bind",
916 .short_help = "policer bind [unbind] [name <name> | index <index>] <worker>",
917 .function = policer_bind_command_fn,
920 VLIB_CLI_COMMAND (policer_input_command, static) = {
921 .path = "policer input",
923 "policer input [unapply] [name <name> | index <index>] <interface>",
924 .function = policer_input_command_fn,
925 .function_arg = VLIB_RX,
928 VLIB_CLI_COMMAND (policer_output_command, static) = {
929 .path = "policer output",
931 "policer output [unapply] [name <name> | index <index>] <interface>",
932 .function = policer_input_command_fn,
933 .function_arg = VLIB_TX,
936 VLIB_CLI_COMMAND (policer_reset_command, static) = {
937 .path = "policer reset",
938 .short_help = "policer reset [name <name> | index <index>]",
939 .function = policer_reset_command_fn
942 static clib_error_t *
943 show_policer_command_fn (vlib_main_t * vm,
944 unformat_input_t * input, vlib_cli_command_t * cmd)
946 vnet_policer_main_t *pm = &vnet_policer_main;
947 unformat_input_t _line_input, *line_input = &_line_input;
949 u32 policer_index = ~0;
952 qos_pol_cfg_params_st *config;
953 clib_error_t *error = 0;
955 /* Get a line of input. */
956 if (!unformat_user (input, unformat_line_input, line_input))
958 pool_foreach (policer, pm->policers)
960 ci = hash_get_mem (pm->policer_config_by_name, policer->name);
961 config = pool_elt_at_index (pm->configs, ci[0]);
963 vlib_cli_output (vm, "Name \"%s\" %U ", policer->name,
964 format_policer_config, config);
965 vlib_cli_output (vm, "%U", format_policer_instance, policer);
966 vlib_cli_output (vm, "-----------");
971 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
973 if (unformat (line_input, "name %s", &name))
975 else if (unformat (line_input, "index %u", &policer_index))
979 error = clib_error_return (0, "unknown input `%U'",
980 format_unformat_error, line_input);
985 if (~0 == policer_index && 0 != name)
987 pi = hash_get_mem (pm->policer_index_by_name, name);
989 policer_index = pi[0];
992 if (~0 == policer_index || pool_is_free_index (pm->policers, policer_index))
995 policer = &pm->policers[policer_index];
996 ci = hash_get_mem (pm->policer_config_by_name, policer->name);
997 config = pool_elt_at_index (pm->configs, ci[0]);
998 vlib_cli_output (vm, "Name \"%s\" %U ", policer->name, format_policer_config,
1000 vlib_cli_output (vm, "%U", format_policer_instance, policer);
1001 vlib_cli_output (vm, "-----------");
1004 unformat_free (line_input);
1011 VLIB_CLI_COMMAND (show_policer_command, static) = {
1012 .path = "show policer",
1013 .short_help = "show policer [name <name> | index <index>]",
1014 .function = show_policer_command_fn,
1017 static clib_error_t *
1018 show_policer_pools_command_fn (vlib_main_t * vm,
1019 unformat_input_t * input,
1020 vlib_cli_command_t * cmd)
1022 vnet_policer_main_t *pm = &vnet_policer_main;
1024 vlib_cli_output (vm, "pool sizes: configs=%d policers=%d",
1025 pool_elts (pm->configs), pool_elts (pm->policers));
1028 VLIB_CLI_COMMAND (show_policer_pools_command, static) = {
1029 .path = "show policer pools",
1030 .short_help = "show policer pools",
1031 .function = show_policer_pools_command_fn,
1035 policer_init (vlib_main_t * vm)
1037 vnet_policer_main_t *pm = &vnet_policer_main;
1040 pm->vnet_main = vnet_get_main ();
1041 pm->log_class = vlib_log_register_class ("policer", 0);
1042 pm->fq_index[VLIB_RX] =
1043 vlib_frame_queue_main_init (policer_input_node.index, 0);
1044 pm->fq_index[VLIB_TX] =
1045 vlib_frame_queue_main_init (policer_output_node.index, 0);
1047 pm->policer_config_by_name = hash_create_string (0, sizeof (uword));
1048 pm->policer_index_by_name = hash_create_string (0, sizeof (uword));
1050 vnet_classify_register_unformat_policer_next_index_fn
1051 (unformat_policer_classify_next_index);
1052 vnet_classify_register_unformat_opaque_index_fn
1053 (unformat_policer_classify_precolor);
1058 VLIB_INIT_FUNCTION (policer_init);
1063 * fd.io coding-style-patch-verification: ON
1066 * eval: (c-set-style "gnu")