blob: 8389a5ead485d6346274aeb29ab3fd4d20b79fce [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
Matus Fabian65fcd4d2016-05-13 05:44:48 -070052clib_error_t *
Brian Russellc5299ff2021-02-09 10:16:58 +000053policer_add_del (vlib_main_t *vm, u8 *name, qos_pol_cfg_params_st *cfg,
54 u32 *policer_index, u8 is_add)
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;
Damjan Marion3891cd82016-10-27 10:27:00 +020059 uword *p;
Matus Fabian70e6a8d2016-06-20 08:10:42 -070060 u32 pi;
Matus Fabian65fcd4d2016-05-13 05:44:48 -070061 int rv;
62
Matus Fabian70e6a8d2016-06-20 08:10:42 -070063 p = hash_get_mem (pm->policer_config_by_name, name);
64
Matus Fabian65fcd4d2016-05-13 05:44:48 -070065 if (is_add == 0)
66 {
Chaoyu Jin913b8732017-08-08 13:36:23 -070067 /* free policer config and template */
Matus Fabian65fcd4d2016-05-13 05:44:48 -070068 if (p == 0)
Damjan Marion3891cd82016-10-27 10:27:00 +020069 {
70 vec_free (name);
71 return clib_error_return (0, "No such policer configuration");
72 }
Chaoyu Jin913b8732017-08-08 13:36:23 -070073 pool_put_index (pm->configs, p[0]);
74 pool_put_index (pm->policer_templates, p[0]);
Matus Fabian65fcd4d2016-05-13 05:44:48 -070075 hash_unset_mem (pm->policer_config_by_name, name);
Chaoyu Jin913b8732017-08-08 13:36:23 -070076
77 /* free policer */
78 p = hash_get_mem (pm->policer_index_by_name, name);
79 if (p == 0)
80 {
81 vec_free (name);
82 return clib_error_return (0, "No such policer");
83 }
84 pool_put_index (pm->policers, p[0]);
Matus Fabian70e6a8d2016-06-20 08:10:42 -070085 hash_unset_mem (pm->policer_index_by_name, name);
Chaoyu Jin913b8732017-08-08 13:36:23 -070086
Damjan Marion3891cd82016-10-27 10:27:00 +020087 vec_free (name);
Matus Fabian65fcd4d2016-05-13 05:44:48 -070088 return 0;
89 }
90
Matus Fabian70e6a8d2016-06-20 08:10:42 -070091 if (p != 0)
92 {
Damjan Marion3891cd82016-10-27 10:27:00 +020093 vec_free (name);
Matus Fabian70e6a8d2016-06-20 08:10:42 -070094 return clib_error_return (0, "Policer already exists");
95 }
96
Matus Fabian65fcd4d2016-05-13 05:44:48 -070097 /* Vet the configuration before adding it to the table */
Brian Russellc5299ff2021-02-09 10:16:58 +000098 rv = pol_logical_2_physical (cfg, &test_policer);
Matus Fabian65fcd4d2016-05-13 05:44:48 -070099
100 if (rv == 0)
101 {
Brian Russell54be0cc2021-02-15 11:49:42 +0000102 policer_t *pp;
Brian Russellc5299ff2021-02-09 10:16:58 +0000103 qos_pol_cfg_params_st *cp;
Brian Russella71ed782021-01-27 11:34:33 +0000104 int i;
Matus Fabian65fcd4d2016-05-13 05:44:48 -0700105
106 pool_get (pm->configs, cp);
107 pool_get (pm->policer_templates, pp);
108
109 ASSERT (cp - pm->configs == pp - pm->policer_templates);
110
111 clib_memcpy (cp, cfg, sizeof (*cp));
112 clib_memcpy (pp, &test_policer, sizeof (*pp));
113
114 hash_set_mem (pm->policer_config_by_name, name, cp - pm->configs);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700115 pool_get_aligned (pm->policers, policer, CLIB_CACHE_LINE_BYTES);
116 policer[0] = pp[0];
117 pi = policer - pm->policers;
118 hash_set_mem (pm->policer_index_by_name, name, pi);
119 *policer_index = pi;
Brian Russell89cd7442021-01-19 16:46:08 +0000120 policer->thread_index = ~0;
Brian Russella71ed782021-01-27 11:34:33 +0000121
122 for (i = 0; i < NUM_POLICE_RESULTS; i++)
123 {
124 vlib_validate_combined_counter (&policer_counters[i], pi);
125 vlib_zero_combined_counter (&policer_counters[i], pi);
126 }
Matus Fabian65fcd4d2016-05-13 05:44:48 -0700127 }
128 else
129 {
130 vec_free (name);
131 return clib_error_return (0, "Config failed sanity check");
132 }
133
134 return 0;
135}
136
Brian Russell48e26362021-02-10 13:53:42 +0000137int
138policer_bind_worker (u8 *name, u32 worker, bool bind)
139{
140 vnet_policer_main_t *pm = &vnet_policer_main;
Brian Russell54be0cc2021-02-15 11:49:42 +0000141 policer_t *policer;
Brian Russell48e26362021-02-10 13:53:42 +0000142 uword *p;
143
144 p = hash_get_mem (pm->policer_index_by_name, name);
145 if (p == 0)
146 {
147 return VNET_API_ERROR_NO_SUCH_ENTRY;
148 }
149
150 policer = &pm->policers[p[0]];
151
152 if (bind)
153 {
154 if (worker >= vlib_num_workers ())
155 {
156 return VNET_API_ERROR_INVALID_WORKER;
157 }
158
159 policer->thread_index = vlib_get_worker_thread_index (worker);
160 }
161 else
162 {
163 policer->thread_index = ~0;
164 }
165 return 0;
166}
167
Brian Russellb0468302021-02-17 15:51:45 +0000168int
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200169policer_input (u8 *name, u32 sw_if_index, vlib_dir_t dir, bool apply)
Brian Russellb0468302021-02-17 15:51:45 +0000170{
171 vnet_policer_main_t *pm = &vnet_policer_main;
172 policer_t *policer;
173 u32 policer_index;
174 uword *p;
175
176 p = hash_get_mem (pm->policer_index_by_name, name);
177 if (p == 0)
178 {
179 return VNET_API_ERROR_NO_SUCH_ENTRY;
180 }
181
182 policer = &pm->policers[p[0]];
183 policer_index = policer - pm->policers;
184
185 if (apply)
186 {
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200187 vec_validate (pm->policer_index_by_sw_if_index[dir], sw_if_index);
188 pm->policer_index_by_sw_if_index[dir][sw_if_index] = policer_index;
Brian Russellb0468302021-02-17 15:51:45 +0000189 }
190 else
191 {
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200192 pm->policer_index_by_sw_if_index[dir][sw_if_index] = ~0;
Brian Russellb0468302021-02-17 15:51:45 +0000193 }
194
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200195 if (dir == VLIB_RX)
196 {
197 vnet_feature_enable_disable ("device-input", "policer-input",
198 sw_if_index, apply, 0, 0);
199 }
200 else
201 {
202 vnet_feature_enable_disable ("ip4-output", "policer-output", sw_if_index,
203 apply, 0, 0);
204 vnet_feature_enable_disable ("ip6-output", "policer-output", sw_if_index,
205 apply, 0, 0);
206 }
Brian Russellb0468302021-02-17 15:51:45 +0000207 return 0;
208}
209
Damjan Marion3891cd82016-10-27 10:27:00 +0200210u8 *
211format_policer_instance (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700212{
Brian Russell54be0cc2021-02-15 11:49:42 +0000213 policer_t *i = va_arg (*va, policer_t *);
Brian Russella71ed782021-01-27 11:34:33 +0000214 uword pi = va_arg (*va, uword);
215 int result;
216 vlib_counter_t counts[NUM_POLICE_RESULTS];
217
218 for (result = 0; result < NUM_POLICE_RESULTS; result++)
219 {
220 vlib_get_combined_counter (&policer_counters[result], pi,
221 &counts[result]);
222 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700223
Damjan Marion3891cd82016-10-27 10:27:00 +0200224 s = format (s, "policer at %llx: %s rate, %s color-aware\n",
225 i, i->single_rate ? "single" : "dual",
226 i->color_aware ? "is" : "not");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700227 s = format (s, "cir %u tok/period, pir %u tok/period, scale %u\n",
Damjan Marion3891cd82016-10-27 10:27:00 +0200228 i->cir_tokens_per_period, i->pir_tokens_per_period, i->scale);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700229 s = format (s, "cur lim %u, cur bkt %u, ext lim %u, ext bkt %u\n",
Damjan Marion3891cd82016-10-27 10:27:00 +0200230 i->current_limit,
231 i->current_bucket, i->extended_limit, i->extended_bucket);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700232 s = format (s, "last update %llu\n", i->last_update_time);
Brian Russella71ed782021-01-27 11:34:33 +0000233 s = format (s, "conform %llu packets, %llu bytes\n",
234 counts[POLICE_CONFORM].packets, counts[POLICE_CONFORM].bytes);
235 s = format (s, "exceed %llu packets, %llu bytes\n",
236 counts[POLICE_EXCEED].packets, counts[POLICE_EXCEED].bytes);
237 s = format (s, "violate %llu packets, %llu bytes\n",
238 counts[POLICE_VIOLATE].packets, counts[POLICE_VIOLATE].bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700239 return s;
Damjan Marion3891cd82016-10-27 10:27:00 +0200240}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700241
Damjan Marion3891cd82016-10-27 10:27:00 +0200242static u8 *
243format_policer_round_type (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700244{
Brian Russellc5299ff2021-02-09 10:16:58 +0000245 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700246
Brian Russellc5299ff2021-02-09 10:16:58 +0000247 if (c->rnd_type == QOS_ROUND_TO_CLOSEST)
Damjan Marion3891cd82016-10-27 10:27:00 +0200248 s = format (s, "closest");
Brian Russellc5299ff2021-02-09 10:16:58 +0000249 else if (c->rnd_type == QOS_ROUND_TO_UP)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700250 s = format (s, "up");
Brian Russellc5299ff2021-02-09 10:16:58 +0000251 else if (c->rnd_type == QOS_ROUND_TO_DOWN)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700252 s = format (s, "down");
253 else
254 s = format (s, "ILLEGAL");
255 return s;
256}
257
258
Damjan Marion3891cd82016-10-27 10:27:00 +0200259static u8 *
260format_policer_rate_type (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700261{
Brian Russellc5299ff2021-02-09 10:16:58 +0000262 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700263
Brian Russellc5299ff2021-02-09 10:16:58 +0000264 if (c->rate_type == QOS_RATE_KBPS)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700265 s = format (s, "kbps");
Brian Russellc5299ff2021-02-09 10:16:58 +0000266 else if (c->rate_type == QOS_RATE_PPS)
Damjan Marion3891cd82016-10-27 10:27:00 +0200267 s = format (s, "pps");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700268 else
269 s = format (s, "ILLEGAL");
270 return s;
271}
272
Damjan Marion3891cd82016-10-27 10:27:00 +0200273static u8 *
274format_policer_type (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700275{
Brian Russellc5299ff2021-02-09 10:16:58 +0000276 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Damjan Marion3891cd82016-10-27 10:27:00 +0200277
Brian Russellc5299ff2021-02-09 10:16:58 +0000278 if (c->rfc == QOS_POLICER_TYPE_1R2C)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700279 s = format (s, "1r2c");
Damjan Marion3891cd82016-10-27 10:27:00 +0200280
Brian Russellc5299ff2021-02-09 10:16:58 +0000281 else if (c->rfc == QOS_POLICER_TYPE_1R3C_RFC_2697)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700282 s = format (s, "1r3c");
283
Brian Russellc5299ff2021-02-09 10:16:58 +0000284 else if (c->rfc == QOS_POLICER_TYPE_2R3C_RFC_2698)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700285 s = format (s, "2r3c-2698");
286
Brian Russellc5299ff2021-02-09 10:16:58 +0000287 else if (c->rfc == QOS_POLICER_TYPE_2R3C_RFC_4115)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700288 s = format (s, "2r3c-4115");
289
Brian Russellc5299ff2021-02-09 10:16:58 +0000290 else if (c->rfc == QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700291 s = format (s, "2r3c-mef5cf1");
292 else
293 s = format (s, "ILLEGAL");
294 return s;
295}
296
Damjan Marion3891cd82016-10-27 10:27:00 +0200297static u8 *
Damjan Marion3891cd82016-10-27 10:27:00 +0200298format_policer_action_type (u8 * s, va_list * va)
Matus Fabian4ac74c92016-05-31 07:33:29 -0700299{
Brian Russellc5299ff2021-02-09 10:16:58 +0000300 qos_pol_action_params_st *a = va_arg (*va, qos_pol_action_params_st *);
Matus Fabian4ac74c92016-05-31 07:33:29 -0700301
Brian Russellc5299ff2021-02-09 10:16:58 +0000302 if (a->action_type == QOS_ACTION_DROP)
Matus Fabian4ac74c92016-05-31 07:33:29 -0700303 s = format (s, "drop");
Brian Russellc5299ff2021-02-09 10:16:58 +0000304 else if (a->action_type == QOS_ACTION_TRANSMIT)
Matus Fabian4ac74c92016-05-31 07:33:29 -0700305 s = format (s, "transmit");
Brian Russellc5299ff2021-02-09 10:16:58 +0000306 else if (a->action_type == QOS_ACTION_MARK_AND_TRANSMIT)
Brian Russelle3845d72021-02-08 15:33:18 +0000307 s = format (s, "mark-and-transmit %U", format_ip_dscp, a->dscp);
Matus Fabian4ac74c92016-05-31 07:33:29 -0700308 else
309 s = format (s, "ILLEGAL");
310 return s;
311}
312
Damjan Marion3891cd82016-10-27 10:27:00 +0200313u8 *
314format_policer_config (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700315{
Brian Russellc5299ff2021-02-09 10:16:58 +0000316 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700317
318 s = format (s, "type %U cir %u eir %u cb %u eb %u\n",
Damjan Marion3891cd82016-10-27 10:27:00 +0200319 format_policer_type, c,
320 c->rb.kbps.cir_kbps,
321 c->rb.kbps.eir_kbps, c->rb.kbps.cb_bytes, c->rb.kbps.eb_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700322 s = format (s, "rate type %U, round type %U\n",
Damjan Marion3891cd82016-10-27 10:27:00 +0200323 format_policer_rate_type, c, format_policer_round_type, c);
Matus Fabian4ac74c92016-05-31 07:33:29 -0700324 s = format (s, "conform action %U, exceed action %U, violate action %U\n",
Damjan Marion3891cd82016-10-27 10:27:00 +0200325 format_policer_action_type, &c->conform_action,
326 format_policer_action_type, &c->exceed_action,
327 format_policer_action_type, &c->violate_action);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700328 return s;
329}
330
331static uword
332unformat_policer_type (unformat_input_t * input, va_list * va)
333{
Brian Russellc5299ff2021-02-09 10:16:58 +0000334 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700335
336 if (!unformat (input, "type"))
337 return 0;
338
339 if (unformat (input, "1r2c"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000340 c->rfc = QOS_POLICER_TYPE_1R2C;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700341 else if (unformat (input, "1r3c"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000342 c->rfc = QOS_POLICER_TYPE_1R3C_RFC_2697;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700343 else if (unformat (input, "2r3c-2698"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000344 c->rfc = QOS_POLICER_TYPE_2R3C_RFC_2698;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700345 else if (unformat (input, "2r3c-4115"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000346 c->rfc = QOS_POLICER_TYPE_2R3C_RFC_4115;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700347 else if (unformat (input, "2r3c-mef5cf1"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000348 c->rfc = QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700349 else
350 return 0;
351 return 1;
352}
353
354static uword
355unformat_policer_round_type (unformat_input_t * input, va_list * va)
356{
Brian Russellc5299ff2021-02-09 10:16:58 +0000357 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700358
Damjan Marion3891cd82016-10-27 10:27:00 +0200359 if (!unformat (input, "round"))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700360 return 0;
361
Damjan Marion3891cd82016-10-27 10:27:00 +0200362 if (unformat (input, "closest"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000363 c->rnd_type = QOS_ROUND_TO_CLOSEST;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700364 else if (unformat (input, "up"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000365 c->rnd_type = QOS_ROUND_TO_UP;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700366 else if (unformat (input, "down"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000367 c->rnd_type = QOS_ROUND_TO_DOWN;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700368 else
369 return 0;
370 return 1;
371}
372
373static uword
374unformat_policer_rate_type (unformat_input_t * input, va_list * va)
375{
Brian Russellc5299ff2021-02-09 10:16:58 +0000376 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700377
Damjan Marion3891cd82016-10-27 10:27:00 +0200378 if (!unformat (input, "rate"))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700379 return 0;
380
381 if (unformat (input, "kbps"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000382 c->rate_type = QOS_RATE_KBPS;
Damjan Marion3891cd82016-10-27 10:27:00 +0200383 else if (unformat (input, "pps"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000384 c->rate_type = QOS_RATE_PPS;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700385 else
386 return 0;
387 return 1;
388}
389
390static uword
391unformat_policer_cir (unformat_input_t * input, va_list * va)
392{
Brian Russellc5299ff2021-02-09 10:16:58 +0000393 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700394
395 if (unformat (input, "cir %u", &c->rb.kbps.cir_kbps))
396 return 1;
397 return 0;
398}
399
400static uword
401unformat_policer_eir (unformat_input_t * input, va_list * va)
402{
Brian Russellc5299ff2021-02-09 10:16:58 +0000403 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700404
405 if (unformat (input, "eir %u", &c->rb.kbps.eir_kbps))
406 return 1;
407 return 0;
408}
409
410static uword
411unformat_policer_cb (unformat_input_t * input, va_list * va)
412{
Brian Russellc5299ff2021-02-09 10:16:58 +0000413 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700414
415 if (unformat (input, "cb %u", &c->rb.kbps.cb_bytes))
416 return 1;
417 return 0;
418}
419
420static uword
421unformat_policer_eb (unformat_input_t * input, va_list * va)
422{
Brian Russellc5299ff2021-02-09 10:16:58 +0000423 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700424
425 if (unformat (input, "eb %u", &c->rb.kbps.eb_bytes))
426 return 1;
427 return 0;
428}
429
Matus Fabian4ac74c92016-05-31 07:33:29 -0700430static uword
Matus Fabian4ac74c92016-05-31 07:33:29 -0700431unformat_policer_action_type (unformat_input_t * input, va_list * va)
432{
Brian Russellc5299ff2021-02-09 10:16:58 +0000433 qos_pol_action_params_st *a = va_arg (*va, qos_pol_action_params_st *);
Matus Fabian4ac74c92016-05-31 07:33:29 -0700434
435 if (unformat (input, "drop"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000436 a->action_type = QOS_ACTION_DROP;
Matus Fabian4ac74c92016-05-31 07:33:29 -0700437 else if (unformat (input, "transmit"))
Brian Russellc5299ff2021-02-09 10:16:58 +0000438 a->action_type = QOS_ACTION_TRANSMIT;
Brian Russelle3845d72021-02-08 15:33:18 +0000439 else if (unformat (input, "mark-and-transmit %U", unformat_ip_dscp,
440 &a->dscp))
Brian Russellc5299ff2021-02-09 10:16:58 +0000441 a->action_type = QOS_ACTION_MARK_AND_TRANSMIT;
Matus Fabian4ac74c92016-05-31 07:33:29 -0700442 else
443 return 0;
444 return 1;
445}
446
447static uword
448unformat_policer_action (unformat_input_t * input, va_list * va)
449{
Brian Russellc5299ff2021-02-09 10:16:58 +0000450 qos_pol_cfg_params_st *c = va_arg (*va, qos_pol_cfg_params_st *);
Matus Fabian4ac74c92016-05-31 07:33:29 -0700451
452 if (unformat (input, "conform-action %U", unformat_policer_action_type,
Damjan Marion3891cd82016-10-27 10:27:00 +0200453 &c->conform_action))
Matus Fabian4ac74c92016-05-31 07:33:29 -0700454 return 1;
455 else if (unformat (input, "exceed-action %U", unformat_policer_action_type,
Damjan Marion3891cd82016-10-27 10:27:00 +0200456 &c->exceed_action))
Matus Fabian4ac74c92016-05-31 07:33:29 -0700457 return 1;
458 else if (unformat (input, "violate-action %U", unformat_policer_action_type,
Damjan Marion3891cd82016-10-27 10:27:00 +0200459 &c->violate_action))
Matus Fabian4ac74c92016-05-31 07:33:29 -0700460 return 1;
461 return 0;
462}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700463
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700464static uword
465unformat_policer_classify_next_index (unformat_input_t * input, va_list * va)
466{
Damjan Marion3891cd82016-10-27 10:27:00 +0200467 u32 *r = va_arg (*va, u32 *);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700468 vnet_policer_main_t *pm = &vnet_policer_main;
Damjan Marion3891cd82016-10-27 10:27:00 +0200469 uword *p;
470 u8 *match_name = 0;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700471
472 if (unformat (input, "%s", &match_name))
473 ;
474 else
475 return 0;
476
477 p = hash_get_mem (pm->policer_index_by_name, match_name);
478
479 if (p == 0)
480 return 0;
481
482 *r = p[0];
483
484 return 1;
485}
486
487static uword
488unformat_policer_classify_precolor (unformat_input_t * input, va_list * va)
489{
Damjan Marion3891cd82016-10-27 10:27:00 +0200490 u32 *r = va_arg (*va, u32 *);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700491
492 if (unformat (input, "conform-color"))
493 *r = POLICE_CONFORM;
494 else if (unformat (input, "exceed-color"))
495 *r = POLICE_EXCEED;
496 else
497 return 0;
498
499 return 1;
500}
501
Ed Warnickecb9cada2015-12-08 15:45:58 -0700502#define foreach_config_param \
503_(eb) \
504_(cb) \
505_(eir) \
506_(cir) \
507_(rate_type) \
508_(round_type) \
Matus Fabian4ac74c92016-05-31 07:33:29 -0700509_(type) \
510_(action)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700511
512static clib_error_t *
Neale Ranns415cd672021-03-19 08:54:38 +0000513policer_add_command_fn (vlib_main_t *vm, unformat_input_t *input,
514 vlib_cli_command_t *cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700515{
Brian Russellc5299ff2021-02-09 10:16:58 +0000516 qos_pol_cfg_params_st c;
Damjan Marion3891cd82016-10-27 10:27:00 +0200517 unformat_input_t _line_input, *line_input = &_line_input;
Matus Fabian65fcd4d2016-05-13 05:44:48 -0700518 u8 is_add = 1;
Damjan Marion3891cd82016-10-27 10:27:00 +0200519 u8 *name = 0;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700520 u32 pi;
Billy McFalla9a20e72017-02-15 11:39:12 -0500521 clib_error_t *error = NULL;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700522
523 /* Get a line of input. */
Damjan Marion3891cd82016-10-27 10:27:00 +0200524 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700525 return 0;
526
Dave Barachb7b92992018-10-17 10:38:51 -0400527 clib_memset (&c, 0, sizeof (c));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700528
Damjan Marion3891cd82016-10-27 10:27:00 +0200529 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700530 {
531 if (unformat (line_input, "del"))
Damjan Marion3891cd82016-10-27 10:27:00 +0200532 is_add = 0;
533 else if (unformat (line_input, "name %s", &name))
534 ;
535 else if (unformat (line_input, "color-aware"))
536 c.color_aware = 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700537
538#define _(a) else if (unformat (line_input, "%U", unformat_policer_##a, &c)) ;
539 foreach_config_param
540#undef _
Damjan Marion3891cd82016-10-27 10:27:00 +0200541 else
Billy McFalla9a20e72017-02-15 11:39:12 -0500542 {
543 error = clib_error_return (0, "unknown input `%U'",
544 format_unformat_error, line_input);
545 goto done;
546 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700547 }
548
Billy McFalla9a20e72017-02-15 11:39:12 -0500549 error = policer_add_del (vm, name, &c, &pi, is_add);
550
551done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700552 unformat_free (line_input);
553
Billy McFalla9a20e72017-02-15 11:39:12 -0500554 return error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700555}
556
Neale Ranns415cd672021-03-19 08:54:38 +0000557static clib_error_t *
558policer_del_command_fn (vlib_main_t *vm, unformat_input_t *input,
559 vlib_cli_command_t *cmd)
560{
561 unformat_input_t _line_input, *line_input = &_line_input;
562 clib_error_t *error = NULL;
563 u8 *name = 0;
564
565 /* Get a line of input. */
566 if (!unformat_user (input, unformat_line_input, line_input))
567 return 0;
568
569 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
570 {
571 if (unformat (line_input, "name %s", &name))
572 ;
573 else
574 {
575 error = clib_error_return (0, "unknown input `%U'",
576 format_unformat_error, line_input);
577 goto done;
578 }
579 }
580
581 error = policer_add_del (vm, name, NULL, NULL, 0);
582
583done:
584 unformat_free (line_input);
585
586 return error;
587}
588
589static clib_error_t *
590policer_bind_command_fn (vlib_main_t *vm, unformat_input_t *input,
591 vlib_cli_command_t *cmd)
592{
593 unformat_input_t _line_input, *line_input = &_line_input;
594 clib_error_t *error = NULL;
595 u8 bind, *name = 0;
596 u32 worker;
597 int rv;
598
599 bind = 1;
600 worker = ~0;
601
602 /* Get a line of input. */
603 if (!unformat_user (input, unformat_line_input, line_input))
604 return 0;
605
606 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
607 {
608 if (unformat (line_input, "name %s", &name))
609 ;
jinshaohuidcd7e242021-05-30 05:40:56 +0100610 else if (unformat (line_input, "unbind"))
Neale Ranns415cd672021-03-19 08:54:38 +0000611 bind = 0;
jinshaohuidcd7e242021-05-30 05:40:56 +0100612 else if (unformat (line_input, "%d", &worker))
Neale Ranns415cd672021-03-19 08:54:38 +0000613 ;
614 else
615 {
616 error = clib_error_return (0, "unknown input `%U'",
617 format_unformat_error, line_input);
618 goto done;
619 }
620 }
621
622 if (bind && ~0 == worker)
623 {
624 error = clib_error_return (0, "specify worker to bind to: `%U'",
625 format_unformat_error, line_input);
626 }
627 else
628 {
629 rv = policer_bind_worker (name, worker, bind);
630
631 if (rv)
632 error = clib_error_return (0, "failed: `%d'", rv);
633 }
634
635done:
636 unformat_free (line_input);
637
638 return error;
639}
640
641static clib_error_t *
642policer_input_command_fn (vlib_main_t *vm, unformat_input_t *input,
643 vlib_cli_command_t *cmd)
644{
645 unformat_input_t _line_input, *line_input = &_line_input;
646 clib_error_t *error = NULL;
647 u8 apply, *name = 0;
648 u32 sw_if_index;
649 int rv;
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200650 vlib_dir_t dir = cmd->function_arg;
Neale Ranns415cd672021-03-19 08:54:38 +0000651
652 apply = 1;
653 sw_if_index = ~0;
654
655 /* Get a line of input. */
656 if (!unformat_user (input, unformat_line_input, line_input))
657 return 0;
658
659 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
660 {
661 if (unformat (line_input, "name %s", &name))
662 ;
663 else if (unformat (line_input, "unapply"))
664 apply = 0;
665 else if (unformat (line_input, "%U", unformat_vnet_sw_interface,
666 vnet_get_main (), &sw_if_index))
667 ;
668 else
669 {
670 error = clib_error_return (0, "unknown input `%U'",
671 format_unformat_error, line_input);
672 goto done;
673 }
674 }
675
676 if (~0 == sw_if_index)
677 {
678 error = clib_error_return (0, "specify interface to apply to: `%U'",
679 format_unformat_error, line_input);
680 }
681 else
682 {
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200683 rv = policer_input (name, sw_if_index, dir, apply);
Neale Ranns415cd672021-03-19 08:54:38 +0000684
685 if (rv)
686 error = clib_error_return (0, "failed: `%d'", rv);
687 }
688
689done:
690 unformat_free (line_input);
691
692 return error;
693}
694
Ed Warnickecb9cada2015-12-08 15:45:58 -0700695VLIB_CLI_COMMAND (configure_policer_command, static) = {
Neale Ranns415cd672021-03-19 08:54:38 +0000696 .path = "configure policer",
Maxime Peimed5f2912022-11-17 15:29:10 +0000697 .short_help = "configure policer name <name> [type 1r2c | 1r3c | 2r3c-2698 "
698 "| 2r3c-4115] [color-aware] [cir <cir>] [cb <cb>] [eir <eir>] "
699 "[eb <eb>] [rate kbps | pps] [round closest | up | down] "
700 "[conform-action drop | transmit | mark-and-transmit <dscp>] "
701 "[exceed-action drop | transmit | mark-and-transmit <dscp>] "
702 "[violate-action drop | transmit | mark-and-transmit <dscp>]",
Neale Ranns415cd672021-03-19 08:54:38 +0000703 .function = policer_add_command_fn,
704};
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200705
Neale Ranns415cd672021-03-19 08:54:38 +0000706VLIB_CLI_COMMAND (policer_add_command, static) = {
707 .path = "policer add",
Maxime Peimed5f2912022-11-17 15:29:10 +0000708 .short_help = "policer name <name> [type 1r2c | 1r3c | 2r3c-2698 | "
709 "2r3c-4115] [color-aware] [cir <cir>] [cb <cb>] [eir <eir>] "
710 "[eb <eb>] [rate kbps | pps] [round closest | up | down] "
711 "[conform-action drop | transmit | mark-and-transmit <dscp>] "
712 "[exceed-action drop | transmit | mark-and-transmit <dscp>] "
713 "[violate-action drop | transmit | mark-and-transmit <dscp>]",
Neale Ranns415cd672021-03-19 08:54:38 +0000714 .function = policer_add_command_fn,
715};
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200716
Neale Ranns415cd672021-03-19 08:54:38 +0000717VLIB_CLI_COMMAND (policer_del_command, static) = {
718 .path = "policer del",
719 .short_help = "policer del name <name> ",
720 .function = policer_del_command_fn,
721};
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200722
Neale Ranns415cd672021-03-19 08:54:38 +0000723VLIB_CLI_COMMAND (policer_bind_command, static) = {
724 .path = "policer bind",
725 .short_help = "policer bind [unbind] name <name> <worker>",
726 .function = policer_bind_command_fn,
727};
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200728
Neale Ranns415cd672021-03-19 08:54:38 +0000729VLIB_CLI_COMMAND (policer_input_command, static) = {
730 .path = "policer input",
Maxime Peimed5f2912022-11-17 15:29:10 +0000731 .short_help = "policer input [unapply] name <name> <interface>",
Neale Ranns415cd672021-03-19 08:54:38 +0000732 .function = policer_input_command_fn,
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200733 .function_arg = VLIB_RX,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700734};
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200735
736VLIB_CLI_COMMAND (policer_output_command, static) = {
737 .path = "policer output",
Maxime Peimed5f2912022-11-17 15:29:10 +0000738 .short_help = "policer output [unapply] name <name> <interface>",
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200739 .function = policer_input_command_fn,
740 .function_arg = VLIB_TX,
741};
Ed Warnickecb9cada2015-12-08 15:45:58 -0700742
743static clib_error_t *
744show_policer_command_fn (vlib_main_t * vm,
Damjan Marion3891cd82016-10-27 10:27:00 +0200745 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700746{
747 vnet_policer_main_t *pm = &vnet_policer_main;
Damjan Marion3891cd82016-10-27 10:27:00 +0200748 hash_pair_t *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700749 u32 pool_index;
Damjan Marion3891cd82016-10-27 10:27:00 +0200750 u8 *match_name = 0;
751 u8 *name;
Brian Russella71ed782021-01-27 11:34:33 +0000752 uword *pi;
Brian Russellc5299ff2021-02-09 10:16:58 +0000753 qos_pol_cfg_params_st *config;
Brian Russell54be0cc2021-02-15 11:49:42 +0000754 policer_t *templ;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700755
756 (void) unformat (input, "name %s", &match_name);
757
Damjan Marion3891cd82016-10-27 10:27:00 +0200758 /* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700759 hash_foreach_pair (p, pm->policer_config_by_name,
760 ({
761 name = (u8 *) p->key;
762 if (match_name == 0 || !strcmp((char *) name, (char *) match_name))
763 {
Brian Russella71ed782021-01-27 11:34:33 +0000764 pi = hash_get_mem (pm->policer_index_by_name, name);
765
766 pool_index = p->value[0];
767 config = pool_elt_at_index (pm->configs, pool_index);
768 templ = pool_elt_at_index (pm->policer_templates, pool_index);
769 vlib_cli_output (vm, "Name \"%s\" %U ", name, format_policer_config,
770 config);
Klement Sekeraba875632021-10-27 10:56:38 +0200771 if (pi)
772 {
773 vlib_cli_output (vm, "Template %U", format_policer_instance, templ,
774 pi[0]);
775 }
776 else
777 {
778 vlib_cli_output (
779 vm, "Cannot print template - policer index hash lookup failed");
780 }
Brian Russella71ed782021-01-27 11:34:33 +0000781 vlib_cli_output (vm, "-----------");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700782 }
783 }));
Damjan Marion3891cd82016-10-27 10:27:00 +0200784 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700785 return 0;
786}
787
788
Damjan Marion3891cd82016-10-27 10:27:00 +0200789/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700790VLIB_CLI_COMMAND (show_policer_command, static) = {
Huawei LI1f4b6512022-11-05 02:50:53 +0800791 .path = "show policer",
792 .short_help = "show policer [name <name>]",
793 .function = show_policer_command_fn,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700794};
Damjan Marion3891cd82016-10-27 10:27:00 +0200795/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700796
Chaoyu Jin913b8732017-08-08 13:36:23 -0700797static clib_error_t *
798show_policer_pools_command_fn (vlib_main_t * vm,
799 unformat_input_t * input,
800 vlib_cli_command_t * cmd)
801{
802 vnet_policer_main_t *pm = &vnet_policer_main;
803
804 vlib_cli_output (vm, "pool sizes: configs=%d templates=%d policers=%d",
805 pool_elts (pm->configs),
806 pool_elts (pm->policer_templates),
807 pool_elts (pm->policers));
808 return 0;
809}
810/* *INDENT-OFF* */
811VLIB_CLI_COMMAND (show_policer_pools_command, static) = {
812 .path = "show policer pools",
813 .short_help = "show policer pools",
814 .function = show_policer_pools_command_fn,
815};
816/* *INDENT-ON* */
817
Damjan Marion3891cd82016-10-27 10:27:00 +0200818clib_error_t *
819policer_init (vlib_main_t * vm)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700820{
Damjan Marion3891cd82016-10-27 10:27:00 +0200821 vnet_policer_main_t *pm = &vnet_policer_main;
Damjan Marion3891cd82016-10-27 10:27:00 +0200822
Ed Warnickecb9cada2015-12-08 15:45:58 -0700823 pm->vlib_main = vm;
Damjan Marion3891cd82016-10-27 10:27:00 +0200824 pm->vnet_main = vnet_get_main ();
Brian Russellbbccdc52021-02-10 18:34:48 +0000825 pm->log_class = vlib_log_register_class ("policer", 0);
Stanislav Zaikine5a3ae02022-04-05 19:23:12 +0200826 pm->fq_index[VLIB_RX] =
827 vlib_frame_queue_main_init (policer_input_node.index, 0);
828 pm->fq_index[VLIB_TX] =
829 vlib_frame_queue_main_init (policer_output_node.index, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700830
831 pm->policer_config_by_name = hash_create_string (0, sizeof (uword));
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700832 pm->policer_index_by_name = hash_create_string (0, sizeof (uword));
833
834 vnet_classify_register_unformat_policer_next_index_fn
835 (unformat_policer_classify_next_index);
836 vnet_classify_register_unformat_opaque_index_fn
837 (unformat_policer_classify_precolor);
838
Ed Warnickecb9cada2015-12-08 15:45:58 -0700839 return 0;
840}
841
Damjan Marion3891cd82016-10-27 10:27:00 +0200842VLIB_INIT_FUNCTION (policer_init);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700843
844
Damjan Marion3891cd82016-10-27 10:27:00 +0200845
846/*
847 * fd.io coding-style-patch-verification: ON
848 *
849 * Local Variables:
850 * eval: (c-set-style "gnu")
851 * End:
852 */