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