qos: QoS dump APIs
[vpp.git] / src / vnet / qos / qos_egress_map.c
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2018 Cisco and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *------------------------------------------------------------------
16  */
17
18 #include <vnet/qos/qos_egress_map.h>
19 #include <vnet/qos/qos_mark.h>
20
21 /**
22  * Pool from which to allocate table
23  */
24 qos_egress_map_t *qem_pool;
25
26 /**
27  * DB to map user table-IDs to internal table indicies.
28  */
29 uword *qem_db;
30
31 index_t
32 qos_egress_map_find (qos_egress_map_id_t mid)
33 {
34   uword *p = NULL;
35
36   p = hash_get (qem_db, mid);
37
38   if (NULL != p)
39     return p[0];
40
41   return (INDEX_INVALID);
42 }
43
44 qos_egress_map_id_t
45 qos_egress_map_get_id (index_t qemi)
46 {
47   qos_egress_map_id_t qid;
48   index_t qmi;
49
50   /* *INDENT-OFF* */
51   hash_foreach(qid, qmi, qem_db,
52   ({
53     if (qmi == qemi)
54       return (qid);
55   }));
56   /* *INDENT-OFF* */
57
58   return (~0);
59 }
60
61 qos_egress_map_t *
62 qos_egress_map_find_i (qos_egress_map_id_t mid)
63 {
64   index_t qemi;
65
66   qemi = qos_egress_map_find (mid);
67
68   if (INDEX_INVALID != qemi)
69     {
70       return (pool_elt_at_index (qem_pool, qemi));
71     }
72
73   return (NULL);
74 }
75
76 static qos_egress_map_t *
77 qos_egress_map_find_or_create (qos_egress_map_id_t mid)
78 {
79   qos_egress_map_t *qem;
80
81   /*
82    * Find the existing or create a new table
83    */
84   qem = qos_egress_map_find_i (mid);
85
86   if (NULL == qem)
87     {
88       index_t qemi;
89
90       pool_get_aligned (qem_pool, qem, CLIB_CACHE_LINE_BYTES);
91       qemi = qem - qem_pool;
92
93       clib_memset (qem, 0, sizeof (*qem));
94       hash_set (qem_db, mid, qemi);
95     }
96
97   return (qem);
98 }
99
100 void
101 qos_egress_map_update (qos_egress_map_id_t mid,
102                        qos_source_t input_source, qos_bits_t * values)
103 {
104   qos_egress_map_t *qem;
105
106   qem = qos_egress_map_find_or_create (mid);
107
108   clib_memcpy (qem->qem_output[input_source],
109                values, sizeof (qem->qem_output[input_source]));
110 }
111
112 void
113 qos_egress_map_delete (qos_egress_map_id_t mid)
114 {
115   qos_egress_map_t *qem;
116
117   qem = qos_egress_map_find_i (mid);
118   hash_unset (qem_db, mid);
119
120   if (NULL != qem)
121     {
122       pool_put (qem_pool, qem);
123     }
124 }
125
126 void
127 qos_egress_map_walk (qos_egress_map_walk_cb_t fn, void *c)
128 {
129   qos_egress_map_id_t qid;
130   index_t qmi;
131
132   /* *INDENT-OFF* */
133   hash_foreach(qid, qmi, qem_db,
134   ({
135     fn(qid, pool_elt_at_index(qem_pool, qmi), c);
136   }));
137   /* *INDENT-OFF* */
138 }
139
140 static clib_error_t *
141 qos_egress_map_update_cli (vlib_main_t * vm,
142                            unformat_input_t * input, vlib_cli_command_t * cmd)
143 {
144   qos_egress_map_id_t map_id;
145   qos_egress_map_t *qem;
146   u8 add;
147
148   add = 1;
149   map_id = ~0;
150   qem = NULL;
151
152   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
153     {
154       if (unformat (input, "delete") || unformat (input, "del"))
155         add = 0;
156       else if (unformat (input, "id %d", &map_id))
157         qem = qos_egress_map_find_or_create (map_id);
158       else
159         {
160           int qs, qi, qo;
161
162           if (NULL == qem)
163             return clib_error_return (0, "map-id must be specified");
164
165           while (unformat
166                  (input, "[%U][%d]=%d", unformat_qos_source, &qs, &qi, &qo))
167             qem->qem_output[qs][qi] = qo;
168           break;
169         }
170     }
171
172   if (!add)
173     qos_egress_map_delete (map_id);
174
175   return (NULL);
176 }
177
178 /*?
179  * Update a Egress Qos Map table
180  *
181  * @cliexpar
182  * @cliexcmd{qos egress map id 0 [ip][4]=4}
183  ?*/
184 /* *INDENT-OFF* */
185 VLIB_CLI_COMMAND (qos_egress_map_update_command, static) = {
186   .path = "qos egress map",
187   .short_help = "qos egress map id %d [delete] {[SOURCE][INPUT]=OUTPUT}",
188   .function = qos_egress_map_update_cli,
189   .is_mp_safe = 1,
190 };
191 /* *INDENT-ON* */
192
193   u8 *format_qos_egress_map (u8 * s, va_list * args)
194   {
195     qos_egress_map_t *qem = va_arg (*args, qos_egress_map_t *);
196     u32 indent = va_arg (*args, u32);
197     int qs;
198     u32 ii;
199
200     FOR_EACH_QOS_SOURCE (qs)
201     {
202       s = format (s, "%U%U:[",
203                   format_white_space, indent, format_qos_source, qs);
204
205       for (ii = 0; ii < ARRAY_LEN (qem->qem_output[qs]) - 1; ii++)
206         {
207           s = format (s, "%d,", qem->qem_output[qs][ii]);
208         }
209       s = format (s, "%d]\n", qem->qem_output[qs][ii]);
210     }
211
212     return (s);
213   }
214
215   static clib_error_t *qos_egress_map_show (vlib_main_t * vm,
216                                             unformat_input_t * input,
217                                             vlib_cli_command_t * cmd)
218   {
219     qos_egress_map_id_t map_id;
220     qos_egress_map_t *qem;
221     clib_error_t *error;
222
223     map_id = ~0;
224     qem = NULL;
225     error = NULL;
226
227     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
228       {
229         if (unformat (input, "id %d", &map_id))
230           ;
231         else
232           {
233             error = unformat_parse_error (input);
234             goto done;
235           }
236       }
237
238     if (~0 == map_id)
239       {
240         index_t qemi;
241
242       /* *INDENT-OFF* */
243       hash_foreach(map_id, qemi, qem_db,
244       ({
245           vlib_cli_output (vm, " Map-ID:%d\n%U",
246                            map_id,
247                            format_qos_egress_map,
248                            pool_elt_at_index(qem_pool, qemi), 2);
249       }));
250       /* *INDENT-ON* */
251       }
252     else
253       {
254         qem = qos_egress_map_find_i (map_id);
255
256         if (NULL == qem)
257           {
258             error = clib_error_return (0, "No Map for ID %d", map_id);
259           }
260         else
261           {
262             vlib_cli_output (vm, " Map-ID:%d\n%U",
263                              map_id, format_qos_egress_map, qem, 2);
264           }
265       }
266
267   done:
268     return (error);
269   }
270
271 /*?
272  * Show Egress Qos Maps
273  *
274  * @cliexpar
275  * @cliexcmd{show qos egress map}
276  ?*/
277 /* *INDENT-OFF* */
278 VLIB_CLI_COMMAND (qos_egress_map_show_command, static) = {
279   .path = "show qos egress map",
280   .short_help = "show qos egress map id %d",
281   .function = qos_egress_map_show,
282   .is_mp_safe = 1,
283 };
284 /* *INDENT-ON* */
285
286 /*
287  * fd.io coding-style-patch-verification: ON
288  *
289  * Local Variables:
290  * eval: (c-set-style "gnu")
291  * End:
292  */