misc: remove GNU Indent directives
[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   hash_foreach(qid, qmi, qem_db,
51   ({
52     if (qmi == qemi)
53       return (qid);
54   }));
55
56   return (~0);
57 }
58
59 qos_egress_map_t *
60 qos_egress_map_find_i (qos_egress_map_id_t mid)
61 {
62   index_t qemi;
63
64   qemi = qos_egress_map_find (mid);
65
66   if (INDEX_INVALID != qemi)
67     {
68       return (pool_elt_at_index (qem_pool, qemi));
69     }
70
71   return (NULL);
72 }
73
74 static qos_egress_map_t *
75 qos_egress_map_find_or_create (qos_egress_map_id_t mid)
76 {
77   qos_egress_map_t *qem;
78
79   /*
80    * Find the existing or create a new table
81    */
82   qem = qos_egress_map_find_i (mid);
83
84   if (NULL == qem)
85     {
86       index_t qemi;
87
88       pool_get_aligned (qem_pool, qem, CLIB_CACHE_LINE_BYTES);
89       qemi = qem - qem_pool;
90
91       clib_memset (qem, 0, sizeof (*qem));
92       hash_set (qem_db, mid, qemi);
93     }
94
95   return (qem);
96 }
97
98 void
99 qos_egress_map_update (qos_egress_map_id_t mid,
100                        qos_source_t input_source, qos_bits_t * values)
101 {
102   qos_egress_map_t *qem;
103
104   qem = qos_egress_map_find_or_create (mid);
105
106   clib_memcpy (qem->qem_output[input_source],
107                values, sizeof (qem->qem_output[input_source]));
108 }
109
110 void
111 qos_egress_map_delete (qos_egress_map_id_t mid)
112 {
113   qos_egress_map_t *qem;
114
115   qem = qos_egress_map_find_i (mid);
116   hash_unset (qem_db, mid);
117
118   if (NULL != qem)
119     {
120       pool_put (qem_pool, qem);
121     }
122 }
123
124 void
125 qos_egress_map_walk (qos_egress_map_walk_cb_t fn, void *c)
126 {
127   qos_egress_map_id_t qid;
128   index_t qmi;
129
130   hash_foreach(qid, qmi, qem_db,
131   ({
132     fn(qid, pool_elt_at_index(qem_pool, qmi), c);
133   }));
134 }
135
136 static clib_error_t *
137 qos_egress_map_update_cli (vlib_main_t * vm,
138                            unformat_input_t * input, vlib_cli_command_t * cmd)
139 {
140   qos_egress_map_id_t map_id;
141   qos_egress_map_t *qem;
142   u8 add;
143
144   add = 1;
145   map_id = ~0;
146   qem = NULL;
147
148   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
149     {
150       if (unformat (input, "delete") || unformat (input, "del"))
151         add = 0;
152       else if (unformat (input, "id %d", &map_id))
153         qem = qos_egress_map_find_or_create (map_id);
154       else
155         {
156           int qs, qi, qo;
157
158           if (NULL == qem)
159             return clib_error_return (0, "map-id must be specified");
160
161           while (unformat
162                  (input, "[%U][%d]=%d", unformat_qos_source, &qs, &qi, &qo))
163             qem->qem_output[qs][qi] = qo;
164           break;
165         }
166     }
167
168   if (!add)
169     qos_egress_map_delete (map_id);
170
171   return (NULL);
172 }
173
174 /*?
175  * Update a Egress Qos Map table
176  *
177  * @cliexpar
178  * @cliexcmd{qos egress map id 0 [ip][4]=4}
179  ?*/
180 VLIB_CLI_COMMAND (qos_egress_map_update_command, static) = {
181   .path = "qos egress map",
182   .short_help = "qos egress map id %d [delete] {[SOURCE][INPUT]=OUTPUT}",
183   .function = qos_egress_map_update_cli,
184   .is_mp_safe = 1,
185 };
186
187   u8 *format_qos_egress_map (u8 * s, va_list * args)
188   {
189     qos_egress_map_t *qem = va_arg (*args, qos_egress_map_t *);
190     u32 indent = va_arg (*args, u32);
191     int qs;
192     u32 ii;
193
194     FOR_EACH_QOS_SOURCE (qs)
195     {
196       s = format (s, "%U%U:[",
197                   format_white_space, indent, format_qos_source, qs);
198
199       for (ii = 0; ii < ARRAY_LEN (qem->qem_output[qs]) - 1; ii++)
200         {
201           s = format (s, "%d,", qem->qem_output[qs][ii]);
202         }
203       s = format (s, "%d]\n", qem->qem_output[qs][ii]);
204     }
205
206     return (s);
207   }
208
209   static clib_error_t *qos_egress_map_show (vlib_main_t * vm,
210                                             unformat_input_t * input,
211                                             vlib_cli_command_t * cmd)
212   {
213     qos_egress_map_id_t map_id;
214     qos_egress_map_t *qem;
215     clib_error_t *error;
216
217     map_id = ~0;
218     qem = NULL;
219     error = NULL;
220
221     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
222       {
223         if (unformat (input, "id %d", &map_id))
224           ;
225         else
226           {
227             error = unformat_parse_error (input);
228             goto done;
229           }
230       }
231
232     if (~0 == map_id)
233       {
234         index_t qemi;
235
236       hash_foreach(map_id, qemi, qem_db,
237       ({
238           vlib_cli_output (vm, " Map-ID:%d\n%U",
239                            map_id,
240                            format_qos_egress_map,
241                            pool_elt_at_index(qem_pool, qemi), 2);
242       }));
243       }
244     else
245       {
246         qem = qos_egress_map_find_i (map_id);
247
248         if (NULL == qem)
249           {
250             error = clib_error_return (0, "No Map for ID %d", map_id);
251           }
252         else
253           {
254             vlib_cli_output (vm, " Map-ID:%d\n%U",
255                              map_id, format_qos_egress_map, qem, 2);
256           }
257       }
258
259   done:
260     return (error);
261   }
262
263 /*?
264  * Show Egress Qos Maps
265  *
266  * @cliexpar
267  * @cliexcmd{show qos egress map}
268  ?*/
269 VLIB_CLI_COMMAND (qos_egress_map_show_command, static) = {
270   .path = "show qos egress map",
271   .short_help = "show qos egress map id %d",
272   .function = qos_egress_map_show,
273   .is_mp_safe = 1,
274 };
275
276 /*
277  * fd.io coding-style-patch-verification: ON
278  *
279  * Local Variables:
280  * eval: (c-set-style "gnu")
281  * End:
282  */