Add support for native vpp_lite (non-dpdk) platform
[vpp.git] / vnet / vnet / policer / policer.c
1 /*
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  */
15 #include <stdint.h>
16 #include <vnet/policer/policer.h>
17
18 u8 * format_policer_instance (u8 * s, va_list * va)
19 {
20   policer_read_response_type_st * i 
21     = va_arg (*va, policer_read_response_type_st *);
22
23   s = format (s, "policer at %llx: %s rate, %s color-aware\n", 
24               i, i->single_rate ? "single" : "dual",
25               i->color_aware ? "is" : "not");
26   s = format (s, "cir %u tok/period, pir %u tok/period, scale %u\n",
27               i->cir_tokens_per_period, i->pir_tokens_per_period, 
28               i->scale);
29   s = format (s, "cur lim %u, cur bkt %u, ext lim %u, ext bkt %u\n",
30               i->current_limit,
31               i->current_bucket,
32               i->extended_limit,
33               i->extended_bucket);
34   s = format (s, "last update %llu\n", i->last_update_time);
35   return s;
36 }              
37
38 static u8 * format_policer_round_type (u8 * s, va_list * va)
39 {
40   sse2_qos_pol_cfg_params_st * c 
41     = va_arg (*va, sse2_qos_pol_cfg_params_st *);
42
43   if (c->rnd_type == SSE2_QOS_ROUND_TO_CLOSEST)
44     s = format(s, "closest");
45   else if (c->rnd_type == SSE2_QOS_ROUND_TO_UP)
46     s = format (s, "up");
47   else if (c->rnd_type == SSE2_QOS_ROUND_TO_DOWN)
48     s = format (s, "down");
49   else
50     s = format (s, "ILLEGAL");
51   return s;
52 }
53
54
55 static u8 * format_policer_rate_type (u8 * s, va_list * va)
56 {
57   sse2_qos_pol_cfg_params_st * c 
58     = va_arg (*va, sse2_qos_pol_cfg_params_st *);
59
60   if (c->rate_type == SSE2_QOS_RATE_KBPS)
61     s = format (s, "kbps");
62   else if (c->rate_type == SSE2_QOS_RATE_PPS)
63     s = format(s, "pps");
64   else
65     s = format (s, "ILLEGAL");
66   return s;
67 }
68
69 static u8 * format_policer_type (u8 * s, va_list * va)
70 {
71   sse2_qos_pol_cfg_params_st * c 
72     = va_arg (*va, sse2_qos_pol_cfg_params_st *);
73   
74   if (c->rfc == SSE2_QOS_POLICER_TYPE_1R2C)
75     s = format (s, "1r2c");
76       
77   else if (c->rfc == SSE2_QOS_POLICER_TYPE_1R3C_RFC_2697)
78     s = format (s, "1r3c");
79
80   else if (c->rfc == SSE2_QOS_POLICER_TYPE_2R3C_RFC_2698)
81     s = format (s, "2r3c-2698");
82
83   else if (c->rfc == SSE2_QOS_POLICER_TYPE_2R3C_RFC_4115)
84     s = format (s, "2r3c-4115");
85
86   else if (c->rfc == SSE2_QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1)
87     s = format (s, "2r3c-mef5cf1");
88   else
89     s = format (s, "ILLEGAL");
90   return s;
91 }
92
93 u8 * format_policer_config (u8 * s, va_list * va)
94 {
95   sse2_qos_pol_cfg_params_st * c 
96     = va_arg (*va, sse2_qos_pol_cfg_params_st *);
97
98   s = format (s, "type %U cir %u eir %u cb %u eb %u\n",
99               format_policer_type, c, 
100               c->rb.kbps.cir_kbps,
101               c->rb.kbps.eir_kbps,
102               c->rb.kbps.cb_bytes,
103               c->rb.kbps.eb_bytes);
104   s = format (s, "rate type %U, round type %U\n",
105               format_policer_rate_type, c,
106               format_policer_round_type, c);
107   return s;
108 }
109
110 static uword
111 unformat_policer_type (unformat_input_t * input, va_list * va)
112 {
113   sse2_qos_pol_cfg_params_st * c 
114     = va_arg (*va, sse2_qos_pol_cfg_params_st *);
115
116   if (!unformat (input, "type"))
117     return 0;
118
119   if (unformat (input, "1r2c"))
120     c->rfc = SSE2_QOS_POLICER_TYPE_1R2C;
121   else if (unformat (input, "1r3c"))
122     c->rfc = SSE2_QOS_POLICER_TYPE_1R3C_RFC_2697;
123   else if (unformat (input, "2r3c-2698"))
124     c->rfc = SSE2_QOS_POLICER_TYPE_2R3C_RFC_2698;
125   else if (unformat (input, "2r3c-4115"))
126     c->rfc = SSE2_QOS_POLICER_TYPE_2R3C_RFC_4115;
127   else if (unformat (input, "2r3c-mef5cf1"))
128     c->rfc = SSE2_QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1;
129   else
130     return 0;
131   return 1;
132 }
133
134 static uword
135 unformat_policer_round_type (unformat_input_t * input, va_list * va)
136 {
137   sse2_qos_pol_cfg_params_st * c 
138     = va_arg (*va, sse2_qos_pol_cfg_params_st *);
139
140   if (!unformat(input, "round"))
141     return 0;
142
143   if (unformat(input, "closest"))
144     c->rnd_type = SSE2_QOS_ROUND_TO_CLOSEST;
145   else if (unformat (input, "up"))
146     c->rnd_type = SSE2_QOS_ROUND_TO_UP;
147   else if (unformat (input, "down"))
148     c->rnd_type = SSE2_QOS_ROUND_TO_DOWN;
149   else
150     return 0;
151   return 1;
152 }
153
154 static uword
155 unformat_policer_rate_type (unformat_input_t * input, va_list * va)
156 {
157   sse2_qos_pol_cfg_params_st * c 
158     = va_arg (*va, sse2_qos_pol_cfg_params_st *);
159
160   if (!unformat(input, "rate"))
161     return 0;
162
163   if (unformat (input, "kbps"))
164     c->rate_type = SSE2_QOS_RATE_KBPS;
165   else if (unformat(input, "pps"))
166     c->rate_type = SSE2_QOS_RATE_PPS;
167   else
168     return 0;
169   return 1;
170 }
171
172 static uword
173 unformat_policer_cir (unformat_input_t * input, va_list * va)
174 {
175   sse2_qos_pol_cfg_params_st * c 
176     = va_arg (*va, sse2_qos_pol_cfg_params_st *);
177
178   if (unformat (input, "cir %u", &c->rb.kbps.cir_kbps))
179     return 1;
180   return 0;
181 }
182
183 static uword
184 unformat_policer_eir (unformat_input_t * input, va_list * va)
185 {
186   sse2_qos_pol_cfg_params_st * c 
187     = va_arg (*va, sse2_qos_pol_cfg_params_st *);
188
189   if (unformat (input, "eir %u", &c->rb.kbps.eir_kbps))
190     return 1;
191   return 0;
192 }
193
194 static uword
195 unformat_policer_cb (unformat_input_t * input, va_list * va)
196 {
197   sse2_qos_pol_cfg_params_st * c 
198     = va_arg (*va, sse2_qos_pol_cfg_params_st *);
199
200   if (unformat (input, "cb %u", &c->rb.kbps.cb_bytes))
201     return 1;
202   return 0;
203 }
204
205 static uword
206 unformat_policer_eb (unformat_input_t * input, va_list * va)
207 {
208   sse2_qos_pol_cfg_params_st * c 
209     = va_arg (*va, sse2_qos_pol_cfg_params_st *);
210
211   if (unformat (input, "eb %u", &c->rb.kbps.eb_bytes))
212     return 1;
213   return 0;
214 }
215
216
217 #define foreach_config_param                    \
218 _(eb)                                           \
219 _(cb)                                           \
220 _(eir)                                          \
221 _(cir)                                          \
222 _(rate_type)                                    \
223 _(round_type)                                   \
224 _(type)
225
226 static clib_error_t *
227 configure_policer_command_fn (vlib_main_t * vm,
228                               unformat_input_t * input,
229                               vlib_cli_command_t * cmd)
230 {
231   vnet_policer_main_t *pm = &vnet_policer_main;
232   sse2_qos_pol_cfg_params_st c;
233   policer_read_response_type_st test_policer;
234   unformat_input_t _line_input, * line_input = &_line_input;
235   int is_add = 1;
236   int rv;
237   u8 * name = 0;
238   uword * p;
239
240   /* Get a line of input. */
241   if (! unformat_user (input, unformat_line_input, line_input))
242     return 0;
243
244   memset (&c, 0, sizeof (c));
245
246   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) 
247     {
248       if (unformat (line_input, "del"))
249         is_add = 0;
250       else if (unformat(line_input, "name %s", &name))
251         ;
252
253 #define _(a) else if (unformat (line_input, "%U", unformat_policer_##a, &c)) ;
254       foreach_config_param
255 #undef _
256
257       else
258         return clib_error_return (0, "unknown input `%U'",
259                                   format_unformat_error, line_input);
260     }
261
262   unformat_free (line_input);
263
264   if (is_add == 0)
265     {
266       p = hash_get_mem (pm->policer_config_by_name, name);
267       if (p == 0)
268         {
269           vec_free(name);
270           return clib_error_return (0, "No such policer configuration");
271         }
272       hash_unset_mem (pm->policer_config_by_name, name);
273       vec_free(name);
274       return 0;
275     }
276
277   /* Vet the configuration before adding it to the table */
278   rv = sse2_pol_logical_2_physical (&c, &test_policer);
279   
280   if (rv == 0)
281     {
282       policer_read_response_type_st *pp;
283       sse2_qos_pol_cfg_params_st *cp;
284
285       pool_get (pm->configs, cp);
286       pool_get (pm->policer_templates, pp);
287
288       ASSERT (cp - pm->configs == pp - pm->policer_templates);
289
290       memcpy (cp, &c, sizeof (*cp));
291       memcpy (pp, &test_policer, sizeof (*pp));
292
293       hash_set_mem (pm->policer_config_by_name, name, cp - pm->configs);
294     }
295   else
296     {
297       vec_free (name);
298       return clib_error_return (0, "Config failed sanity check");
299     }
300   
301   return 0;
302 }
303
304 VLIB_CLI_COMMAND (configure_policer_command, static) = {
305     .path = "configure policer",
306     .short_help = "configure policer name <name> <params> ",
307     .function = configure_policer_command_fn,
308 };
309
310
311 static clib_error_t *
312 show_policer_command_fn (vlib_main_t * vm,
313                               unformat_input_t * input,
314                               vlib_cli_command_t * cmd)
315 {
316   vnet_policer_main_t *pm = &vnet_policer_main;
317   hash_pair_t * p;
318   u32 pool_index;
319   u8 * match_name = 0;
320   u8 * name;
321   sse2_qos_pol_cfg_params_st *config;
322   policer_read_response_type_st *templ;
323
324   (void) unformat (input, "name %s", &match_name);
325
326   hash_foreach_pair (p, pm->policer_config_by_name,
327   ({
328     name = (u8 *) p->key;
329     if (match_name == 0 || !strcmp((char *) name, (char *) match_name))
330       {
331         pool_index = p->value[0];
332         config = pool_elt_at_index (pm->configs, pool_index);
333         templ = pool_elt_at_index (pm->policer_templates, pool_index);
334         vlib_cli_output (vm, "Name \"%s\" %U ", 
335                          name, format_policer_config, config);
336         vlib_cli_output (vm, "Template %U", 
337                          format_policer_instance, templ);
338         vlib_cli_output (vm, "-----------");
339       }
340   }));
341   return 0;
342 }
343
344
345 VLIB_CLI_COMMAND (show_policer_command, static) = {
346     .path = "show policer",
347     .short_help = "show policer [name]",
348     .function = show_policer_command_fn,
349 };
350
351 clib_error_t *policer_init (vlib_main_t * vm)
352 {
353   vnet_policer_main_t * pm = &vnet_policer_main;
354   void vnet_policer_node_funcs_reference(void);
355
356   vnet_policer_node_funcs_reference();
357   
358   pm->vlib_main = vm;
359   pm->vnet_main = vnet_get_main();
360
361   pm->policer_config_by_name = hash_create_string (0, sizeof (uword));
362   return 0;
363 }
364
365 VLIB_INIT_FUNCTION(policer_init);
366
367