blob: 217a4c963898ff53c07bf2dd01b6a980f4b26045 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
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:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
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.
14 */
Damjan Marione936bbe2016-02-25 23:17:38 +010015#include <stdint.h>
Brian Russell48e26362021-02-10 13:53:42 +000016#include <stdbool.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070017#include <vnet/policer/policer.h>
Brian Russell97de8a22021-01-19 16:50:56 +000018#include <vnet/policer/police_inlines.h>
Matus Fabian70e6a8d2016-06-20 08:10:42 -070019#include <vnet/classify/vnet_classify.h>
Brian Russelle3845d72021-02-08 15:33:18 +000020#include <vnet/ip/ip_packet.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070021
Dave Wallace71612d62017-10-24 01:32:41 -040022vnet_policer_main_t vnet_policer_main;
23
Brian Russell97de8a22021-01-19 16:50:56 +000024u8 *
25format_policer_handoff_trace (u8 *s, va_list *args)
26{
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 *);
30
31 s = format (s, "policer %d, handoff thread %d to %d", t->policer_index,
32 t->current_worker_index, t->next_worker_index);
33
34 return s;
35}
36
Brian Russella71ed782021-01-27 11:34:33 +000037vlib_combined_counter_main_t policer_counters[] = {
38 {
39 .name = "Policer-Conform",
40 .stat_segment_name = "/net/policer/conform",
41 },
42 {
43 .name = "Policer-Exceed",
44 .stat_segment_name = "/net/policer/exceed",
45 },
46 {
47 .name = "Policer-Violate",
48 .stat_segment_name = "/net/policer/violate",
49 },
50};
51
Maxime Peim2d1a62b2023-01-06 11:57:38 +000052int
53policer_add (vlib_main_t *vm, const u8 *name, const qos_pol_cfg_params_st *cfg,
54 u32 *policer_index)
Matus Fabian65fcd4d2016-05-13 05:44:48 -070055{
56 vnet_policer_main_t *pm = &vnet_policer_main;
Brian Russell54be0cc2021-02-15 11:49:42 +000057 policer_t test_policer;
58 policer_t *policer;
Maxime Peim2d1a62b2023-01-06 11:57:38 +000059 policer_t *pp;
60 qos_pol_cfg_params_st *cp;
Damjan Marion3891cd82016-10-27 10:27:00 +020061 uword *p;
Matus Fabian70e6a8d2016-06-20 08:10:42 -070062 u32 pi;
Matus Fabian65fcd4d2016-05-13 05:44:48 -070063 int rv;
Maxime Peim2d1a62b2023-01-06 11:57:38 +000064 int i;
Matus Fabian65fcd4d2016-05-13 05:44:48 -070065
Matus Fabian70e6a8d2016-06-20 08:10:42 -070066 p = hash_get_mem (pm->policer_config_by_name, name);
67
Maxime Peim2d1a62b2023-01-06 11:57:38 +000068 if (p != NULL)
69 return VNET_API_ERROR_VALUE_EXIST;
Matus Fabian70e6a8d2016-06-20 08:10:42 -070070
Matus Fabian65fcd4d2016-05-13 05:44:48 -070071 /* Vet the configuration before adding it to the table */
Brian Russellc5299ff2021-02-09 10:16:58 +000072 rv = pol_logical_2_physical (cfg, &test_policer);
Matus Fabian65fcd4d2016-05-13 05:44:48 -070073
Maxime Peim2d1a62b2023-01-06 11:57:38 +000074 if (rv != 0)
75 return VNET_API_ERROR_INVALID_VALUE;
76
77 pool_get (pm->configs, cp);
78 pool_get_aligned (pm->policers, policer, CLIB_CACHE_LINE_BYTES);
79
80 clib_memcpy (cp, cfg, sizeof (*cp));
81 clib_memcpy (policer, &test_policer, sizeof (*pp));
82
83 policer->name = format (0, "%s%c", name, 0);
84 pi = policer - pm->policers;
85
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);
88 *policer_index = pi;
89 policer->thread_index = ~0;
90
91 for (i = 0; i < NUM_POLICE_RESULTS; i++)
Matus Fabian65fcd4d2016-05-13 05:44:48 -070092 {
Maxime Peim2d1a62b2023-01-06 11:57:38 +000093 vlib_validate_combined_counter (&policer_counters[i], pi);
94 vlib_zero_combined_counter (&policer_counters[i], pi);
Matus Fabian65fcd4d2016-05-13 05:44:48 -070095 }
96
97 return 0;
98}
99
Brian Russell48e26362021-02-10 13:53:42 +0000100int
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000101policer_del (vlib_main_t *vm, u32 policer_index)
Brian Russell48e26362021-02-10 13:53:42 +0000102{
103 vnet_policer_main_t *pm = &vnet_policer_main;
Brian Russell54be0cc2021-02-15 11:49:42 +0000104 policer_t *policer;
Brian Russell48e26362021-02-10 13:53:42 +0000105 uword *p;
106
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000107 if (pool_is_free_index (pm->policers, policer_index))
108 return VNET_API_ERROR_NO_SUCH_ENTRY;
109
110 policer = &pm->policers[policer_index];
111
112 p = hash_get_mem (pm->policer_config_by_name, policer->name);
113
114 /* free policer config */
115 if (p != NULL)
Brian Russell48e26362021-02-10 13:53:42 +0000116 {
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000117 pool_put_index (pm->configs, p[0]);
118 hash_unset_mem (pm->policer_config_by_name, policer->name);
Brian Russell48e26362021-02-10 13:53:42 +0000119 }
120
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000121 /* free policer */
122 hash_unset_mem (pm->policer_index_by_name, policer->name);
123 vec_free (policer->name);
124 pool_put_index (pm->policers, policer_index);
125
126 return 0;
127}
128
129int
130policer_update (vlib_main_t *vm, u32 policer_index,
131 const qos_pol_cfg_params_st *cfg)
132{
133 vnet_policer_main_t *pm = &vnet_policer_main;
134 policer_t test_policer;
135 policer_t *policer;
136 qos_pol_cfg_params_st *cp;
137 uword *p;
138 u8 *name;
139 int rv;
140 int i;
141
142 if (pool_is_free_index (pm->policers, policer_index))
143 return VNET_API_ERROR_NO_SUCH_ENTRY;
144
145 policer = &pm->policers[policer_index];
146
147 /* Vet the configuration before adding it to the table */
148 rv = pol_logical_2_physical (cfg, &test_policer);
149 if (rv != 0)
150 return VNET_API_ERROR_INVALID_VALUE;
151
152 p = hash_get_mem (pm->policer_config_by_name, policer->name);
153
154 if (PREDICT_TRUE (p != NULL))
155 {
156 cp = &pm->configs[p[0]];
157 }
158 else
159 {
160 /* recover from a missing configuration */
161 pool_get (pm->configs, cp);
162 hash_set_mem (pm->policer_config_by_name, policer->name,
163 cp - pm->configs);
164 }
165
166 name = policer->name;
167
168 clib_memcpy (cp, cfg, sizeof (*cp));
169 clib_memcpy (policer, &test_policer, sizeof (*policer));
170
171 policer->name = name;
172 policer->thread_index = ~0;
173
174 for (i = 0; i < NUM_POLICE_RESULTS; i++)
175 vlib_zero_combined_counter (&policer_counters[i], policer_index);
176
177 return 0;
178}
179
180int
181policer_reset (vlib_main_t *vm, u32 policer_index)
182{
183 vnet_policer_main_t *pm = &vnet_policer_main;
184 policer_t *policer;
185
186 if (pool_is_free_index (pm->policers, policer_index))
187 return VNET_API_ERROR_NO_SUCH_ENTRY;
188
189 policer = &pm->policers[policer_index];
190
191 policer->current_bucket = policer->current_limit;
192 policer->extended_bucket = policer->extended_limit;
193
194 return 0;
195}
196
197int
198policer_bind_worker (u32 policer_index, u32 worker, bool bind)
199{
200 vnet_policer_main_t *pm = &vnet_policer_main;
201 policer_t *policer;
202
203 if (pool_is_free_index (pm->policers, policer_index))
204 return VNET_API_ERROR_NO_SUCH_ENTRY;
205
206 policer = &pm->policers[policer_index];
Brian Russell48e26362021-02-10 13:53:42 +0000207
208 if (bind)
209 {
210 if (worker >= vlib_num_workers ())
211 {
212 return VNET_API_ERROR_INVALID_WORKER;
213 }
214
215 policer->thread_index = vlib_get_worker_thread_index (worker);
216 }
217 else
218 {
219 policer->thread_index = ~0;
220 }
221 return 0;
222}
223
Brian Russellb0468302021-02-17 15:51:45 +0000224int
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000225policer_input (u32 policer_index, u32 sw_if_index, vlib_dir_t dir, bool apply)
Brian Russellb0468302021-02-17 15:51:45 +0000226{
227 vnet_policer_main_t *pm = &vnet_policer_main;
Brian Russellb0468302021-02-17 15:51:45 +0000228
229 if (apply)
230 {
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200231 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;
Brian Russellb0468302021-02-17 15:51:45 +0000233 }
234 else
235 {
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200236 pm->policer_index_by_sw_if_index[dir][sw_if_index] = ~0;
Brian Russellb0468302021-02-17 15:51:45 +0000237 }
238
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200239 if (dir == VLIB_RX)
240 {
241 vnet_feature_enable_disable ("device-input", "policer-input",
242 sw_if_index, apply, 0, 0);
243 }
244 else
245 {
246 vnet_feature_enable_disable ("ip4-output", "policer-output", sw_if_index,
247 apply, 0, 0);
248 vnet_feature_enable_disable ("ip6-output", "policer-output", sw_if_index,
249 apply, 0, 0);
250 }
Brian Russellb0468302021-02-17 15:51:45 +0000251 return 0;
252}
253
Damjan Marion3891cd82016-10-27 10:27:00 +0200254u8 *
255format_policer_instance (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700256{
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000257 vnet_policer_main_t *pm = &vnet_policer_main;
Brian Russell54be0cc2021-02-15 11:49:42 +0000258 policer_t *i = va_arg (*va, policer_t *);
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000259 u32 policer_index = i - pm->policers;
Brian Russella71ed782021-01-27 11:34:33 +0000260 int result;
261 vlib_counter_t counts[NUM_POLICE_RESULTS];
262
263 for (result = 0; result < NUM_POLICE_RESULTS; result++)
264 {
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000265 vlib_get_combined_counter (&policer_counters[result], policer_index,
Brian Russella71ed782021-01-27 11:34:33 +0000266 &counts[result]);
267 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700268
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000269 s =
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");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700272 s = format (s, "cir %u tok/period, pir %u tok/period, scale %u\n",
Damjan Marion3891cd82016-10-27 10:27:00 +0200273 i->cir_tokens_per_period, i->pir_tokens_per_period, i->scale);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700274 s = format (s, "cur lim %u, cur bkt %u, ext lim %u, ext bkt %u\n",
Damjan Marion3891cd82016-10-27 10:27:00 +0200275 i->current_limit,
276 i->current_bucket, i->extended_limit, i->extended_bucket);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700277 s = format (s, "last update %llu\n", i->last_update_time);
Brian Russella71ed782021-01-27 11:34:33 +0000278 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);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700284 return s;
Damjan Marion3891cd82016-10-27 10:27:00 +0200285}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700286
Damjan Marion3891cd82016-10-27 10:27:00 +0200287static u8 *
288format_policer_round_type (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700289{
Brian Russellc5299ff2021-02-09 10:16:58 +0000290 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700291
Brian Russellc5299ff2021-02-09 10:16:58 +0000292 if (c->rnd_type == QOS_ROUND_TO_CLOSEST)
Damjan Marion3891cd82016-10-27 10:27:00 +0200293 s = format (s, "closest");
Brian Russellc5299ff2021-02-09 10:16:58 +0000294 else if (c->rnd_type == QOS_ROUND_TO_UP)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700295 s = format (s, "up");
Brian Russellc5299ff2021-02-09 10:16:58 +0000296 else if (c->rnd_type == QOS_ROUND_TO_DOWN)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700297 s = format (s, "down");
298 else
299 s = format (s, "ILLEGAL");
300 return s;
301}
302
303
Damjan Marion3891cd82016-10-27 10:27:00 +0200304static u8 *
305format_policer_rate_type (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700306{
Brian Russellc5299ff2021-02-09 10:16:58 +0000307 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700308
Brian Russellc5299ff2021-02-09 10:16:58 +0000309 if (c->rate_type == QOS_RATE_KBPS)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700310 s = format (s, "kbps");
Brian Russellc5299ff2021-02-09 10:16:58 +0000311 else if (c->rate_type == QOS_RATE_PPS)
Damjan Marion3891cd82016-10-27 10:27:00 +0200312 s = format (s, "pps");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700313 else
314 s = format (s, "ILLEGAL");
315 return s;
316}
317
Damjan Marion3891cd82016-10-27 10:27:00 +0200318static u8 *
319format_policer_type (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700320{
Brian Russellc5299ff2021-02-09 10:16:58 +0000321 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Damjan Marion3891cd82016-10-27 10:27:00 +0200322
Brian Russellc5299ff2021-02-09 10:16:58 +0000323 if (c->rfc == QOS_POLICER_TYPE_1R2C)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700324 s = format (s, "1r2c");
Damjan Marion3891cd82016-10-27 10:27:00 +0200325
Brian Russellc5299ff2021-02-09 10:16:58 +0000326 else if (c->rfc == QOS_POLICER_TYPE_1R3C_RFC_2697)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700327 s = format (s, "1r3c");
328
Brian Russellc5299ff2021-02-09 10:16:58 +0000329 else if (c->rfc == QOS_POLICER_TYPE_2R3C_RFC_2698)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700330 s = format (s, "2r3c-2698");
331
Brian Russellc5299ff2021-02-09 10:16:58 +0000332 else if (c->rfc == QOS_POLICER_TYPE_2R3C_RFC_4115)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700333 s = format (s, "2r3c-4115");
334
Brian Russellc5299ff2021-02-09 10:16:58 +0000335 else if (c->rfc == QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700336 s = format (s, "2r3c-mef5cf1");
337 else
338 s = format (s, "ILLEGAL");
339 return s;
340}
341
Damjan Marion3891cd82016-10-27 10:27:00 +0200342static u8 *
Damjan Marion3891cd82016-10-27 10:27:00 +0200343format_policer_action_type (u8 * s, va_list * va)
Matus Fabian4ac74c92016-05-31 07:33:29 -0700344{
Brian Russellc5299ff2021-02-09 10:16:58 +0000345 qos_pol_action_params_st *a = va_arg (*va, qos_pol_action_params_st *);
Matus Fabian4ac74c92016-05-31 07:33:29 -0700346
Brian Russellc5299ff2021-02-09 10:16:58 +0000347 if (a->action_type == QOS_ACTION_DROP)
Matus Fabian4ac74c92016-05-31 07:33:29 -0700348 s = format (s, "drop");
Brian Russellc5299ff2021-02-09 10:16:58 +0000349 else if (a->action_type == QOS_ACTION_TRANSMIT)
Matus Fabian4ac74c92016-05-31 07:33:29 -0700350 s = format (s, "transmit");
Brian Russellc5299ff2021-02-09 10:16:58 +0000351 else if (a->action_type == QOS_ACTION_MARK_AND_TRANSMIT)
Brian Russelle3845d72021-02-08 15:33:18 +0000352 s = format (s, "mark-and-transmit %U", format_ip_dscp, a->dscp);
Matus Fabian4ac74c92016-05-31 07:33:29 -0700353 else
354 s = format (s, "ILLEGAL");
355 return s;
356}
357
Damjan Marion3891cd82016-10-27 10:27:00 +0200358u8 *
359format_policer_config (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700360{
Brian Russellc5299ff2021-02-09 10:16:58 +0000361 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700362
363 s = format (s, "type %U cir %u eir %u cb %u eb %u\n",
Damjan Marion3891cd82016-10-27 10:27:00 +0200364 format_policer_type, c,
365 c->rb.kbps.cir_kbps,
366 c->rb.kbps.eir_kbps, c->rb.kbps.cb_bytes, c->rb.kbps.eb_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700367 s = format (s, "rate type %U, round type %U\n",
Damjan Marion3891cd82016-10-27 10:27:00 +0200368 format_policer_rate_type, c, format_policer_round_type, c);
Matus Fabian4ac74c92016-05-31 07:33:29 -0700369 s = format (s, "conform action %U, exceed action %U, violate action %U\n",
Damjan Marion3891cd82016-10-27 10:27:00 +0200370 format_policer_action_type, &c->conform_action,
371 format_policer_action_type, &c->exceed_action,
372 format_policer_action_type, &c->violate_action);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700373 return s;
374}
375
376static uword
377unformat_policer_type (unformat_input_t * input, va_list * va)
378{
Brian Russellc5299ff2021-02-09 10:16:58 +0000379 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700380
381 if (!unformat (input, "type"))
382 return 0;
383
384 if (unformat (input, "1r2c"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000385 c->rfc = QOS_POLICER_TYPE_1R2C;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700386 else if (unformat (input, "1r3c"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000387 c->rfc = QOS_POLICER_TYPE_1R3C_RFC_2697;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700388 else if (unformat (input, "2r3c-2698"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000389 c->rfc = QOS_POLICER_TYPE_2R3C_RFC_2698;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700390 else if (unformat (input, "2r3c-4115"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000391 c->rfc = QOS_POLICER_TYPE_2R3C_RFC_4115;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700392 else if (unformat (input, "2r3c-mef5cf1"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000393 c->rfc = QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700394 else
395 return 0;
396 return 1;
397}
398
399static uword
400unformat_policer_round_type (unformat_input_t * input, va_list * va)
401{
Brian Russellc5299ff2021-02-09 10:16:58 +0000402 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700403
Damjan Marion3891cd82016-10-27 10:27:00 +0200404 if (!unformat (input, "round"))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700405 return 0;
406
Damjan Marion3891cd82016-10-27 10:27:00 +0200407 if (unformat (input, "closest"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000408 c->rnd_type = QOS_ROUND_TO_CLOSEST;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700409 else if (unformat (input, "up"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000410 c->rnd_type = QOS_ROUND_TO_UP;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700411 else if (unformat (input, "down"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000412 c->rnd_type = QOS_ROUND_TO_DOWN;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700413 else
414 return 0;
415 return 1;
416}
417
418static uword
419unformat_policer_rate_type (unformat_input_t * input, va_list * va)
420{
Brian Russellc5299ff2021-02-09 10:16:58 +0000421 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700422
Damjan Marion3891cd82016-10-27 10:27:00 +0200423 if (!unformat (input, "rate"))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700424 return 0;
425
426 if (unformat (input, "kbps"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000427 c->rate_type = QOS_RATE_KBPS;
Damjan Marion3891cd82016-10-27 10:27:00 +0200428 else if (unformat (input, "pps"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000429 c->rate_type = QOS_RATE_PPS;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700430 else
431 return 0;
432 return 1;
433}
434
435static uword
436unformat_policer_cir (unformat_input_t * input, va_list * va)
437{
Brian Russellc5299ff2021-02-09 10:16:58 +0000438 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700439
440 if (unformat (input, "cir %u", &c->rb.kbps.cir_kbps))
441 return 1;
442 return 0;
443}
444
445static uword
446unformat_policer_eir (unformat_input_t * input, va_list * va)
447{
Brian Russellc5299ff2021-02-09 10:16:58 +0000448 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700449
450 if (unformat (input, "eir %u", &c->rb.kbps.eir_kbps))
451 return 1;
452 return 0;
453}
454
455static uword
456unformat_policer_cb (unformat_input_t * input, va_list * va)
457{
Brian Russellc5299ff2021-02-09 10:16:58 +0000458 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700459
460 if (unformat (input, "cb %u", &c->rb.kbps.cb_bytes))
461 return 1;
462 return 0;
463}
464
465static uword
466unformat_policer_eb (unformat_input_t * input, va_list * va)
467{
Brian Russellc5299ff2021-02-09 10:16:58 +0000468 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700469
470 if (unformat (input, "eb %u", &c->rb.kbps.eb_bytes))
471 return 1;
472 return 0;
473}
474
Matus Fabian4ac74c92016-05-31 07:33:29 -0700475static uword
Matus Fabian4ac74c92016-05-31 07:33:29 -0700476unformat_policer_action_type (unformat_input_t * input, va_list * va)
477{
Brian Russellc5299ff2021-02-09 10:16:58 +0000478 qos_pol_action_params_st *a = va_arg (*va, qos_pol_action_params_st *);
Matus Fabian4ac74c92016-05-31 07:33:29 -0700479
480 if (unformat (input, "drop"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000481 a->action_type = QOS_ACTION_DROP;
Matus Fabian4ac74c92016-05-31 07:33:29 -0700482 else if (unformat (input, "transmit"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000483 a->action_type = QOS_ACTION_TRANSMIT;
Brian Russelle3845d72021-02-08 15:33:18 +0000484 else if (unformat (input, "mark-and-transmit %U", unformat_ip_dscp,
485 &a->dscp))
Brian Russellc5299ff2021-02-09 10:16:58 +0000486 a->action_type = QOS_ACTION_MARK_AND_TRANSMIT;
Matus Fabian4ac74c92016-05-31 07:33:29 -0700487 else
488 return 0;
489 return 1;
490}
491
492static uword
493unformat_policer_action (unformat_input_t * input, va_list * va)
494{
Brian Russellc5299ff2021-02-09 10:16:58 +0000495 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Matus Fabian4ac74c92016-05-31 07:33:29 -0700496
497 if (unformat (input, "conform-action %U", unformat_policer_action_type,
Damjan Marion3891cd82016-10-27 10:27:00 +0200498 &c->conform_action))
Matus Fabian4ac74c92016-05-31 07:33:29 -0700499 return 1;
500 else if (unformat (input, "exceed-action %U", unformat_policer_action_type,
Damjan Marion3891cd82016-10-27 10:27:00 +0200501 &c->exceed_action))
Matus Fabian4ac74c92016-05-31 07:33:29 -0700502 return 1;
503 else if (unformat (input, "violate-action %U", unformat_policer_action_type,
Damjan Marion3891cd82016-10-27 10:27:00 +0200504 &c->violate_action))
Matus Fabian4ac74c92016-05-31 07:33:29 -0700505 return 1;
506 return 0;
507}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700508
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700509static uword
510unformat_policer_classify_next_index (unformat_input_t * input, va_list * va)
511{
Damjan Marion3891cd82016-10-27 10:27:00 +0200512 u32 *r = va_arg (*va, u32 *);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700513 vnet_policer_main_t *pm = &vnet_policer_main;
Damjan Marion3891cd82016-10-27 10:27:00 +0200514 uword *p;
515 u8 *match_name = 0;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700516
517 if (unformat (input, "%s", &match_name))
518 ;
519 else
520 return 0;
521
522 p = hash_get_mem (pm->policer_index_by_name, match_name);
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000523 vec_free (match_name);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700524
525 if (p == 0)
526 return 0;
527
528 *r = p[0];
529
530 return 1;
531}
532
533static uword
534unformat_policer_classify_precolor (unformat_input_t * input, va_list * va)
535{
Damjan Marion3891cd82016-10-27 10:27:00 +0200536 u32 *r = va_arg (*va, u32 *);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700537
538 if (unformat (input, "conform-color"))
539 *r = POLICE_CONFORM;
540 else if (unformat (input, "exceed-color"))
541 *r = POLICE_EXCEED;
542 else
543 return 0;
544
545 return 1;
546}
547
Ed Warnickecb9cada2015-12-08 15:45:58 -0700548#define foreach_config_param \
549_(eb) \
550_(cb) \
551_(eir) \
552_(cir) \
553_(rate_type) \
554_(round_type) \
Matus Fabian4ac74c92016-05-31 07:33:29 -0700555_(type) \
556_(action)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700557
558static clib_error_t *
Neale Ranns415cd672021-03-19 08:54:38 +0000559policer_add_command_fn (vlib_main_t *vm, unformat_input_t *input,
560 vlib_cli_command_t *cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700561{
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000562 vnet_policer_main_t *pm = &vnet_policer_main;
Brian Russellc5299ff2021-02-09 10:16:58 +0000563 qos_pol_cfg_params_st c;
Damjan Marion3891cd82016-10-27 10:27:00 +0200564 unformat_input_t _line_input, *line_input = &_line_input;
Damjan Marion3891cd82016-10-27 10:27:00 +0200565 u8 *name = 0;
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000566 uword *p;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700567 u32 pi;
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000568 u32 policer_index = ~0;
569 int rv = 0;
Billy McFalla9a20e72017-02-15 11:39:12 -0500570 clib_error_t *error = NULL;
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000571 u8 is_update = cmd->function_arg;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700572
573 /* Get a line of input. */
Damjan Marion3891cd82016-10-27 10:27:00 +0200574 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700575 return 0;
576
Dave Barachb7b92992018-10-17 10:38:51 -0400577 clib_memset (&c, 0, sizeof (c));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700578
Damjan Marion3891cd82016-10-27 10:27:00 +0200579 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700580 {
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000581 if (unformat (line_input, "name %s", &name))
582 ;
583 else if (is_update && unformat (line_input, "index %u", &policer_index))
Damjan Marion3891cd82016-10-27 10:27:00 +0200584 ;
585 else if (unformat (line_input, "color-aware"))
586 c.color_aware = 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700587
588#define _(a) else if (unformat (line_input, "%U", unformat_policer_##a, &c)) ;
589 foreach_config_param
590#undef _
Damjan Marion3891cd82016-10-27 10:27:00 +0200591 else
Billy McFalla9a20e72017-02-15 11:39:12 -0500592 {
593 error = clib_error_return (0, "unknown input `%U'",
594 format_unformat_error, line_input);
595 goto done;
596 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700597 }
598
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000599 if (is_update)
600 {
601 if (~0 == policer_index && 0 != name)
602 {
603 p = hash_get_mem (pm->policer_index_by_name, name);
604 if (p != NULL)
605 policer_index = p[0];
606 }
607
608 if (~0 != policer_index)
609 {
610 rv = policer_update (vm, policer_index, &c);
611 }
612 }
613 else
614 {
615 rv = policer_add (vm, name, &c, &pi);
616 }
617
618 switch (rv)
619 {
620 case VNET_API_ERROR_NO_SUCH_ENTRY:
621 error = clib_error_return (0, "No such policer");
622 break;
623 case VNET_API_ERROR_VALUE_EXIST:
624 error = clib_error_return (0, "Policer already exists");
625 break;
626 case VNET_API_ERROR_INVALID_VALUE:
627 error = clib_error_return (0, "Config failed sanity check");
628 break;
629 }
Billy McFalla9a20e72017-02-15 11:39:12 -0500630
631done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700632 unformat_free (line_input);
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000633 vec_free (name);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700634
Billy McFalla9a20e72017-02-15 11:39:12 -0500635 return error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700636}
637
Neale Ranns415cd672021-03-19 08:54:38 +0000638static clib_error_t *
639policer_del_command_fn (vlib_main_t *vm, unformat_input_t *input,
640 vlib_cli_command_t *cmd)
641{
642 unformat_input_t _line_input, *line_input = &_line_input;
643 clib_error_t *error = NULL;
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000644 vnet_policer_main_t *pm = &vnet_policer_main;
645 int rv;
646 u32 policer_index = ~0;
647 uword *p;
Neale Ranns415cd672021-03-19 08:54:38 +0000648 u8 *name = 0;
649
650 /* Get a line of input. */
651 if (!unformat_user (input, unformat_line_input, line_input))
652 return 0;
653
654 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
655 {
656 if (unformat (line_input, "name %s", &name))
657 ;
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000658 else if (unformat (line_input, "index %u", &policer_index))
659 ;
Neale Ranns415cd672021-03-19 08:54:38 +0000660 else
661 {
662 error = clib_error_return (0, "unknown input `%U'",
663 format_unformat_error, line_input);
664 goto done;
665 }
666 }
667
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000668 if (~0 == policer_index && 0 != name)
669 {
670 p = hash_get_mem (pm->policer_index_by_name, name);
671 if (p != NULL)
672 policer_index = p[0];
673 }
674
675 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
676 if (~0 != policer_index)
677 rv = policer_del (vm, policer_index);
678
679 switch (rv)
680 {
681 case VNET_API_ERROR_INVALID_VALUE:
682 error = clib_error_return (0, "No such policer configuration");
683 break;
684 case VNET_API_ERROR_NO_SUCH_ENTRY:
685 error = clib_error_return (0, "No such policer");
686 break;
687 }
Neale Ranns415cd672021-03-19 08:54:38 +0000688
689done:
690 unformat_free (line_input);
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000691 vec_free (name);
Neale Ranns415cd672021-03-19 08:54:38 +0000692
693 return error;
694}
695
696static clib_error_t *
697policer_bind_command_fn (vlib_main_t *vm, unformat_input_t *input,
698 vlib_cli_command_t *cmd)
699{
700 unformat_input_t _line_input, *line_input = &_line_input;
701 clib_error_t *error = NULL;
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000702 vnet_policer_main_t *pm = &vnet_policer_main;
703 u8 bind = 1;
704 u8 *name = 0;
705 u32 worker = ~0;
706 u32 policer_index = ~0;
707 uword *p;
Neale Ranns415cd672021-03-19 08:54:38 +0000708 int rv;
709
Neale Ranns415cd672021-03-19 08:54:38 +0000710 /* Get a line of input. */
711 if (!unformat_user (input, unformat_line_input, line_input))
712 return 0;
713
714 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
715 {
716 if (unformat (line_input, "name %s", &name))
717 ;
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000718 else if (unformat (line_input, "index %u", &policer_index))
719 ;
jinshaohuidcd7e242021-05-30 05:40:56 +0100720 else if (unformat (line_input, "unbind"))
Neale Ranns415cd672021-03-19 08:54:38 +0000721 bind = 0;
jinshaohuidcd7e242021-05-30 05:40:56 +0100722 else if (unformat (line_input, "%d", &worker))
Neale Ranns415cd672021-03-19 08:54:38 +0000723 ;
724 else
725 {
726 error = clib_error_return (0, "unknown input `%U'",
727 format_unformat_error, line_input);
728 goto done;
729 }
730 }
731
732 if (bind && ~0 == worker)
733 {
734 error = clib_error_return (0, "specify worker to bind to: `%U'",
735 format_unformat_error, line_input);
736 }
737 else
738 {
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000739 if (~0 == policer_index && 0 != name)
740 {
741 p = hash_get_mem (pm->policer_index_by_name, name);
742 if (p != NULL)
743 policer_index = p[0];
744 }
745
746 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
747 if (~0 != policer_index)
748 rv = policer_bind_worker (policer_index, worker, bind);
Neale Ranns415cd672021-03-19 08:54:38 +0000749
750 if (rv)
751 error = clib_error_return (0, "failed: `%d'", rv);
752 }
753
754done:
755 unformat_free (line_input);
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000756 vec_free (name);
Neale Ranns415cd672021-03-19 08:54:38 +0000757
758 return error;
759}
760
761static clib_error_t *
762policer_input_command_fn (vlib_main_t *vm, unformat_input_t *input,
763 vlib_cli_command_t *cmd)
764{
765 unformat_input_t _line_input, *line_input = &_line_input;
766 clib_error_t *error = NULL;
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000767 vnet_policer_main_t *pm = &vnet_policer_main;
768 u8 apply = 1;
769 u8 *name = 0;
770 u32 sw_if_index = ~0;
771 u32 policer_index = ~0;
772 uword *p;
Neale Ranns415cd672021-03-19 08:54:38 +0000773 int rv;
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200774 vlib_dir_t dir = cmd->function_arg;
Neale Ranns415cd672021-03-19 08:54:38 +0000775
Neale Ranns415cd672021-03-19 08:54:38 +0000776 /* Get a line of input. */
777 if (!unformat_user (input, unformat_line_input, line_input))
778 return 0;
779
780 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
781 {
782 if (unformat (line_input, "name %s", &name))
783 ;
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000784 else if (unformat (line_input, "index %u", &policer_index))
785 ;
Neale Ranns415cd672021-03-19 08:54:38 +0000786 else if (unformat (line_input, "unapply"))
787 apply = 0;
788 else if (unformat (line_input, "%U", unformat_vnet_sw_interface,
789 vnet_get_main (), &sw_if_index))
790 ;
791 else
792 {
793 error = clib_error_return (0, "unknown input `%U'",
794 format_unformat_error, line_input);
795 goto done;
796 }
797 }
798
799 if (~0 == sw_if_index)
800 {
801 error = clib_error_return (0, "specify interface to apply to: `%U'",
802 format_unformat_error, line_input);
803 }
804 else
805 {
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000806 if (~0 == policer_index && 0 != name)
807 {
808 p = hash_get_mem (pm->policer_index_by_name, name);
809 if (p != NULL)
810 policer_index = p[0];
811 }
812
813 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
814 if (~0 != policer_index)
815 rv = policer_input (policer_index, sw_if_index, dir, apply);
Neale Ranns415cd672021-03-19 08:54:38 +0000816
817 if (rv)
818 error = clib_error_return (0, "failed: `%d'", rv);
819 }
820
821done:
822 unformat_free (line_input);
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000823 vec_free (name);
824
825 return error;
826}
827
828static clib_error_t *
829policer_reset_command_fn (vlib_main_t *vm, unformat_input_t *input,
830 vlib_cli_command_t *cmd)
831{
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;
835 int rv;
836 u32 policer_index = ~0;
837 uword *p;
838 u8 *name = 0;
839
840 /* Get a line of input. */
841 if (!unformat_user (input, unformat_line_input, line_input))
842 return 0;
843
844 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
845 {
846 if (unformat (line_input, "name %s", &name))
847 ;
848 else if (unformat (line_input, "index %u", &policer_index))
849 ;
850 else
851 {
852 error = clib_error_return (0, "unknown input `%U'",
853 format_unformat_error, line_input);
854 goto done;
855 }
856 }
857
858 if (~0 == policer_index && 0 != name)
859 {
860 p = hash_get_mem (pm->policer_index_by_name, name);
861 if (p != NULL)
862 policer_index = p[0];
863 }
864
865 rv = VNET_API_ERROR_NO_SUCH_ENTRY;
866 if (~0 != policer_index)
867 rv = policer_reset (vm, policer_index);
868
869 switch (rv)
870 {
871 case VNET_API_ERROR_NO_SUCH_ENTRY:
872 error = clib_error_return (0, "No such policer");
873 break;
874 }
875
876done:
877 unformat_free (line_input);
878 vec_free (name);
Neale Ranns415cd672021-03-19 08:54:38 +0000879
880 return error;
881}
882
Ed Warnickecb9cada2015-12-08 15:45:58 -0700883VLIB_CLI_COMMAND (configure_policer_command, static) = {
Neale Ranns415cd672021-03-19 08:54:38 +0000884 .path = "configure policer",
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000885 .short_help = "configure policer [name <name> | index <index>] [type 1r2c | "
886 "1r3c | 2r3c-2698 "
Maxime Peimed5f2912022-11-17 15:29:10 +0000887 "| 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>]",
Neale Ranns415cd672021-03-19 08:54:38 +0000892 .function = policer_add_command_fn,
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000893 .function_arg = 1
Neale Ranns415cd672021-03-19 08:54:38 +0000894};
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200895
Neale Ranns415cd672021-03-19 08:54:38 +0000896VLIB_CLI_COMMAND (policer_add_command, static) = {
897 .path = "policer add",
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000898 .short_help = "policer add name <name> [type 1r2c | 1r3c | 2r3c-2698 | "
Maxime Peimed5f2912022-11-17 15:29:10 +0000899 "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>]",
Neale Ranns415cd672021-03-19 08:54:38 +0000904 .function = policer_add_command_fn,
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000905 .function_arg = 0
Neale Ranns415cd672021-03-19 08:54:38 +0000906};
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200907
Neale Ranns415cd672021-03-19 08:54:38 +0000908VLIB_CLI_COMMAND (policer_del_command, static) = {
909 .path = "policer del",
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000910 .short_help = "policer del [name <name> | index <index>]",
Neale Ranns415cd672021-03-19 08:54:38 +0000911 .function = policer_del_command_fn,
912};
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200913
Neale Ranns415cd672021-03-19 08:54:38 +0000914VLIB_CLI_COMMAND (policer_bind_command, static) = {
915 .path = "policer bind",
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000916 .short_help = "policer bind [unbind] [name <name> | index <index>] <worker>",
Neale Ranns415cd672021-03-19 08:54:38 +0000917 .function = policer_bind_command_fn,
918};
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200919
Neale Ranns415cd672021-03-19 08:54:38 +0000920VLIB_CLI_COMMAND (policer_input_command, static) = {
921 .path = "policer input",
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000922 .short_help =
923 "policer input [unapply] [name <name> | index <index>] <interface>",
Neale Ranns415cd672021-03-19 08:54:38 +0000924 .function = policer_input_command_fn,
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200925 .function_arg = VLIB_RX,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700926};
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200927
928VLIB_CLI_COMMAND (policer_output_command, static) = {
929 .path = "policer output",
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000930 .short_help =
931 "policer output [unapply] [name <name> | index <index>] <interface>",
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200932 .function = policer_input_command_fn,
933 .function_arg = VLIB_TX,
934};
Ed Warnickecb9cada2015-12-08 15:45:58 -0700935
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000936VLIB_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
940};
941
Ed Warnickecb9cada2015-12-08 15:45:58 -0700942static clib_error_t *
943show_policer_command_fn (vlib_main_t * vm,
Damjan Marion3891cd82016-10-27 10:27:00 +0200944 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700945{
946 vnet_policer_main_t *pm = &vnet_policer_main;
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000947 unformat_input_t _line_input, *line_input = &_line_input;
948 policer_t *policer;
949 u32 policer_index = ~0;
950 u8 *name = 0;
951 uword *ci, *pi;
Brian Russellc5299ff2021-02-09 10:16:58 +0000952 qos_pol_cfg_params_st *config;
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000953 clib_error_t *error = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700954
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000955 /* Get a line of input. */
956 if (!unformat_user (input, unformat_line_input, line_input))
957 {
958 pool_foreach (policer, pm->policers)
959 {
960 ci = hash_get_mem (pm->policer_config_by_name, policer->name);
961 config = pool_elt_at_index (pm->configs, ci[0]);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700962
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000963 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, "-----------");
967 }
968 return 0;
969 }
Brian Russella71ed782021-01-27 11:34:33 +0000970
Maxime Peim2d1a62b2023-01-06 11:57:38 +0000971 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
972 {
973 if (unformat (line_input, "name %s", &name))
974 ;
975 else if (unformat (line_input, "index %u", &policer_index))
976 ;
977 else
978 {
979 error = clib_error_return (0, "unknown input `%U'",
980 format_unformat_error, line_input);
981 goto done;
982 }
983 }
984
985 if (~0 == policer_index && 0 != name)
986 {
987 pi = hash_get_mem (pm->policer_index_by_name, name);
988 if (pi != NULL)
989 policer_index = pi[0];
990 }
991
992 if (~0 == policer_index || pool_is_free_index (pm->policers, policer_index))
993 goto done;
994
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,
999 config);
1000 vlib_cli_output (vm, "%U", format_policer_instance, policer);
1001 vlib_cli_output (vm, "-----------");
1002
1003done:
1004 unformat_free (line_input);
1005 vec_free (name);
1006
1007 return error;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001008}
1009
1010
Damjan Marion3891cd82016-10-27 10:27:00 +02001011/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001012VLIB_CLI_COMMAND (show_policer_command, static) = {
Huawei LI1f4b6512022-11-05 02:50:53 +08001013 .path = "show policer",
Maxime Peim2d1a62b2023-01-06 11:57:38 +00001014 .short_help = "show policer [name <name> | index <index>]",
Huawei LI1f4b6512022-11-05 02:50:53 +08001015 .function = show_policer_command_fn,
Ed Warnickecb9cada2015-12-08 15:45:58 -07001016};
Damjan Marion3891cd82016-10-27 10:27:00 +02001017/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001018
Chaoyu Jin913b8732017-08-08 13:36:23 -07001019static clib_error_t *
1020show_policer_pools_command_fn (vlib_main_t * vm,
1021 unformat_input_t * input,
1022 vlib_cli_command_t * cmd)
1023{
1024 vnet_policer_main_t *pm = &vnet_policer_main;
1025
Maxime Peim2d1a62b2023-01-06 11:57:38 +00001026 vlib_cli_output (vm, "pool sizes: configs=%d policers=%d",
1027 pool_elts (pm->configs), pool_elts (pm->policers));
Chaoyu Jin913b8732017-08-08 13:36:23 -07001028 return 0;
1029}
1030/* *INDENT-OFF* */
1031VLIB_CLI_COMMAND (show_policer_pools_command, static) = {
1032 .path = "show policer pools",
1033 .short_help = "show policer pools",
1034 .function = show_policer_pools_command_fn,
1035};
1036/* *INDENT-ON* */
1037
Damjan Marion3891cd82016-10-27 10:27:00 +02001038clib_error_t *
1039policer_init (vlib_main_t * vm)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001040{
Damjan Marion3891cd82016-10-27 10:27:00 +02001041 vnet_policer_main_t *pm = &vnet_policer_main;
Damjan Marion3891cd82016-10-27 10:27:00 +02001042
Ed Warnickecb9cada2015-12-08 15:45:58 -07001043 pm->vlib_main = vm;
Damjan Marion3891cd82016-10-27 10:27:00 +02001044 pm->vnet_main = vnet_get_main ();
Brian Russellbbccdc52021-02-10 18:34:48 +00001045 pm->log_class = vlib_log_register_class ("policer", 0);
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +02001046 pm->fq_index[VLIB_RX] =
1047 vlib_frame_queue_main_init (policer_input_node.index, 0);
1048 pm->fq_index[VLIB_TX] =
1049 vlib_frame_queue_main_init (policer_output_node.index, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001050
1051 pm->policer_config_by_name = hash_create_string (0, sizeof (uword));
Matus Fabian70e6a8d2016-06-20 08:10:42 -07001052 pm->policer_index_by_name = hash_create_string (0, sizeof (uword));
1053
1054 vnet_classify_register_unformat_policer_next_index_fn
1055 (unformat_policer_classify_next_index);
1056 vnet_classify_register_unformat_opaque_index_fn
1057 (unformat_policer_classify_precolor);
1058
Ed Warnickecb9cada2015-12-08 15:45:58 -07001059 return 0;
1060}
1061
Damjan Marion3891cd82016-10-27 10:27:00 +02001062VLIB_INIT_FUNCTION (policer_init);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001063
1064
Damjan Marion3891cd82016-10-27 10:27:00 +02001065
1066/*
1067 * fd.io coding-style-patch-verification: ON
1068 *
1069 * Local Variables:
1070 * eval: (c-set-style "gnu")
1071 * End:
1072 */