Line data Source code
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 59 : qos_egress_map_find (qos_egress_map_id_t mid)
33 : {
34 59 : uword *p = NULL;
35 :
36 59 : p = hash_get (qem_db, mid);
37 :
38 59 : if (NULL != p)
39 49 : return p[0];
40 :
41 10 : return (INDEX_INVALID);
42 : }
43 :
44 : qos_egress_map_id_t
45 15 : 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 718 : hash_foreach(qid, qmi, qem_db,
52 : ({
53 : if (qmi == qemi)
54 : return (qid);
55 : }));
56 : /* *INDENT-OFF* */
57 :
58 0 : return (~0);
59 : }
60 :
61 : qos_egress_map_t *
62 50 : qos_egress_map_find_i (qos_egress_map_id_t mid)
63 : {
64 : index_t qemi;
65 :
66 50 : qemi = qos_egress_map_find (mid);
67 :
68 50 : if (INDEX_INVALID != qemi)
69 : {
70 40 : return (pool_elt_at_index (qem_pool, qemi));
71 : }
72 :
73 10 : return (NULL);
74 : }
75 :
76 : static qos_egress_map_t *
77 40 : 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 40 : qem = qos_egress_map_find_i (mid);
85 :
86 40 : if (NULL == qem)
87 : {
88 : index_t qemi;
89 :
90 10 : pool_get_aligned (qem_pool, qem, CLIB_CACHE_LINE_BYTES);
91 10 : qemi = qem - qem_pool;
92 :
93 10 : clib_memset (qem, 0, sizeof (*qem));
94 10 : hash_set (qem_db, mid, qemi);
95 : }
96 :
97 40 : return (qem);
98 : }
99 :
100 : void
101 40 : 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 40 : qem = qos_egress_map_find_or_create (mid);
107 :
108 40 : clib_memcpy (qem->qem_output[input_source],
109 : values, sizeof (qem->qem_output[input_source]));
110 40 : }
111 :
112 : void
113 10 : qos_egress_map_delete (qos_egress_map_id_t mid)
114 : {
115 : qos_egress_map_t *qem;
116 :
117 10 : qem = qos_egress_map_find_i (mid);
118 10 : hash_unset (qem_db, mid);
119 :
120 10 : if (NULL != qem)
121 : {
122 10 : pool_put (qem_pool, qem);
123 : }
124 10 : }
125 :
126 : void
127 21 : 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 1424 : hash_foreach(qid, qmi, qem_db,
134 : ({
135 : fn(qid, pool_elt_at_index(qem_pool, qmi), c);
136 : }));
137 : /* *INDENT-OFF* */
138 21 : }
139 :
140 : static clib_error_t *
141 0 : 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 0 : add = 1;
149 0 : map_id = ~0;
150 0 : qem = NULL;
151 :
152 0 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
153 : {
154 0 : if (unformat (input, "delete") || unformat (input, "del"))
155 0 : add = 0;
156 0 : else if (unformat (input, "id %d", &map_id))
157 0 : qem = qos_egress_map_find_or_create (map_id);
158 : else
159 : {
160 : int qs, qi, qo;
161 :
162 0 : if (NULL == qem)
163 0 : return clib_error_return (0, "map-id must be specified");
164 :
165 0 : while (unformat
166 : (input, "[%U][%d]=%d", unformat_qos_source, &qs, &qi, &qo))
167 0 : qem->qem_output[qs][qi] = qo;
168 0 : break;
169 : }
170 : }
171 :
172 0 : if (!add)
173 0 : qos_egress_map_delete (map_id);
174 :
175 0 : 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 272887 : 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 7 : u8 *format_qos_egress_map (u8 * s, va_list * args)
194 : {
195 7 : qos_egress_map_t *qem = va_arg (*args, qos_egress_map_t *);
196 7 : u32 indent = va_arg (*args, u32);
197 : int qs;
198 : u32 ii;
199 :
200 35 : FOR_EACH_QOS_SOURCE (qs)
201 : {
202 28 : s = format (s, "%U%U:[",
203 : format_white_space, indent, format_qos_source, qs);
204 :
205 7168 : for (ii = 0; ii < ARRAY_LEN (qem->qem_output[qs]) - 1; ii++)
206 : {
207 7140 : s = format (s, "%d,", qem->qem_output[qs][ii]);
208 : }
209 28 : s = format (s, "%d]\n", qem->qem_output[qs][ii]);
210 : }
211 :
212 7 : return (s);
213 : }
214 :
215 1 : 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 1 : map_id = ~0;
224 1 : qem = NULL;
225 1 : error = NULL;
226 :
227 1 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
228 : {
229 0 : if (unformat (input, "id %d", &map_id))
230 : ;
231 : else
232 : {
233 0 : error = unformat_parse_error (input);
234 0 : goto done;
235 : }
236 : }
237 :
238 1 : if (~0 == map_id)
239 : {
240 : index_t qemi;
241 :
242 : /* *INDENT-OFF* */
243 72 : 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 0 : qem = qos_egress_map_find_i (map_id);
255 :
256 0 : if (NULL == qem)
257 : {
258 0 : error = clib_error_return (0, "No Map for ID %d", map_id);
259 : }
260 : else
261 : {
262 0 : vlib_cli_output (vm, " Map-ID:%d\n%U",
263 : map_id, format_qos_egress_map, qem, 2);
264 : }
265 : }
266 :
267 1 : done:
268 1 : return (error);
269 : }
270 :
271 : /*?
272 : * Show Egress Qos Maps
273 : *
274 : * @cliexpar
275 : * @cliexcmd{show qos egress map}
276 : ?*/
277 : /* *INDENT-OFF* */
278 272887 : 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 : */
|