Line data Source code
1 : /*
2 : * Copyright (c) 2017 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 :
16 : #include <vnet/bier/bier_disp_table.h>
17 : #include <vnet/bier/bier_disp_entry.h>
18 :
19 : /**
20 : * memory pool for disposition tables
21 : */
22 : bier_disp_table_t *bier_disp_table_pool;
23 :
24 : /**
25 : * Hash table to map client table IDs to VPP index
26 : */
27 : static uword *bier_disp_table_id_to_index;
28 :
29 : static index_t
30 8 : bier_disp_table_get_index (const bier_disp_table_t *bdt)
31 : {
32 8 : return (bdt - bier_disp_table_pool);
33 : }
34 :
35 : static void
36 33 : bier_disp_table_lock_i (bier_disp_table_t *bdt)
37 : {
38 33 : bdt->bdt_locks++;
39 33 : }
40 :
41 : index_t
42 38 : bier_disp_table_find(u32 table_id)
43 : {
44 : uword *p;
45 :
46 38 : p = hash_get(bier_disp_table_id_to_index, table_id);
47 :
48 38 : if (NULL != p)
49 : {
50 34 : return (p[0]);
51 : }
52 :
53 4 : return (INDEX_INVALID);
54 : }
55 :
56 : index_t
57 4 : bier_disp_table_add_or_lock (u32 table_id)
58 : {
59 : bier_disp_table_t *bdt;
60 : index_t bdti;
61 :
62 4 : bdti = bier_disp_table_find(table_id);
63 :
64 4 : if (INDEX_INVALID == bdti)
65 : {
66 4 : pool_get_aligned(bier_disp_table_pool, bdt,
67 : CLIB_CACHE_LINE_BYTES);
68 :
69 4 : bdt->bdt_table_id = table_id;
70 4 : bdt->bdt_locks = 0;
71 :
72 4 : hash_set(bier_disp_table_id_to_index, table_id,
73 : bier_disp_table_get_index(bdt));
74 :
75 : /**
76 : * Set the result for each entry in the DB to be invalid
77 : */
78 4 : clib_memset(bdt->bdt_db, 0xff, sizeof(bdt->bdt_db));
79 : }
80 : else
81 : {
82 0 : bdt = pool_elt_at_index(bier_disp_table_pool, bdti);
83 : }
84 :
85 4 : bier_disp_table_lock_i(bdt);
86 :
87 4 : return (bier_disp_table_get_index(bdt));
88 : }
89 :
90 : void
91 4 : bier_disp_table_unlock_w_table_id (u32 table_id)
92 : {
93 : index_t bdti;
94 :
95 4 : bdti = bier_disp_table_find(table_id);
96 :
97 4 : if (INDEX_INVALID != bdti)
98 : {
99 4 : bier_disp_table_unlock(bdti);
100 : }
101 4 : }
102 :
103 : void
104 33 : bier_disp_table_unlock (index_t bdti)
105 : {
106 : bier_disp_table_t *bdt;
107 :
108 33 : bdt = bier_disp_table_get(bdti);
109 :
110 33 : bdt->bdt_locks--;
111 :
112 33 : if (0 == bdt->bdt_locks)
113 : {
114 : u32 ii;
115 :
116 262148 : for (ii = 0; ii < BIER_BP_MAX; ii++)
117 : {
118 262144 : bier_disp_entry_unlock(bdt->bdt_db[ii]);
119 : }
120 4 : hash_unset(bier_disp_table_id_to_index, bdt->bdt_table_id);
121 4 : pool_put(bier_disp_table_pool, bdt);
122 : }
123 33 : }
124 :
125 : void
126 29 : bier_disp_table_lock (index_t bdti)
127 : {
128 29 : bier_disp_table_lock_i(bier_disp_table_get(bdti));
129 29 : }
130 :
131 : void
132 5 : bier_disp_table_contribute_forwarding (index_t bdti,
133 : dpo_id_t *dpo)
134 : {
135 5 : dpo_set(dpo,
136 : DPO_BIER_DISP_TABLE,
137 : DPO_PROTO_BIER,
138 : bdti);
139 5 : }
140 :
141 :
142 : u8*
143 0 : format_bier_disp_table (u8* s, va_list *ap)
144 : {
145 0 : index_t bdti = va_arg(*ap, index_t);
146 0 : u32 indent = va_arg(*ap, u32);
147 0 : bier_show_flags_t flags = va_arg(*ap, bier_show_flags_t);
148 : bier_disp_table_t *bdt;
149 :
150 0 : bdt = bier_disp_table_get(bdti);
151 :
152 0 : s = format(s, "bier-disp-table:[%d]; table-id:%d locks:%d",
153 0 : bdti, bdt->bdt_table_id, bdt->bdt_locks);
154 :
155 0 : if (flags & BIER_SHOW_DETAIL)
156 : {
157 : u32 ii;
158 :
159 0 : for (ii = 0; ii < BIER_BP_MAX; ii++)
160 : {
161 0 : if (INDEX_INVALID != bdt->bdt_db[ii])
162 : {
163 0 : u16 src = ii;
164 0 : s = format(s, "\n%Usrc:%d", format_white_space, indent+1,
165 0 : clib_host_to_net_u16(src));
166 0 : s = format(s, "\n%U",
167 : format_bier_disp_entry, bdt->bdt_db[ii],
168 : indent+4, BIER_SHOW_BRIEF);
169 : }
170 : }
171 : }
172 0 : return (s);
173 : }
174 :
175 : static u8*
176 0 : format_bier_disp_table_dpo (u8* s, va_list *ap)
177 : {
178 0 : index_t bdti = va_arg(*ap, index_t);
179 0 : u32 indent = va_arg(*ap, u32);
180 :
181 0 : return (format(s, "%U",
182 : format_bier_disp_table, bdti, indent,
183 : BIER_SHOW_BRIEF));
184 : }
185 :
186 : static void
187 6 : bier_disp_table_entry_insert (index_t bdti,
188 : bier_bp_t src,
189 : index_t bdei)
190 : {
191 : bier_disp_table_t *bdt;
192 :
193 6 : bdt = bier_disp_table_get(bdti);
194 6 : bdt->bdt_db[clib_host_to_net_u16(src)] = bdei;
195 6 : }
196 :
197 : static void
198 6 : bier_disp_table_entry_remove (index_t bdti,
199 : bier_bp_t src)
200 : {
201 : bier_disp_table_t *bdt;
202 :
203 6 : bdt = bier_disp_table_get(bdti);
204 6 : bdt->bdt_db[clib_host_to_net_u16(src)] = INDEX_INVALID;
205 6 : }
206 :
207 : static index_t
208 12 : bier_disp_table_lookup_hton(index_t bdti,
209 : bier_bp_t bp)
210 : {
211 12 : bier_hdr_src_id_t src = bp;
212 :
213 12 : return (bier_disp_table_lookup(bdti, clib_host_to_net_u16(src)));
214 : }
215 :
216 : void
217 6 : bier_disp_table_entry_path_add (u32 table_id,
218 : bier_bp_t src,
219 : bier_hdr_proto_id_t payload_proto,
220 : const fib_route_path_t *rpaths)
221 : {
222 : index_t bdti, bdei;
223 :
224 6 : bdti = bier_disp_table_find(table_id);
225 :
226 6 : if (INDEX_INVALID == bdti)
227 : {
228 0 : return;
229 : }
230 :
231 6 : bdei = bier_disp_table_lookup_hton(bdti, src);
232 :
233 6 : if (INDEX_INVALID == bdei)
234 : {
235 6 : bdei = bier_disp_entry_add_or_lock();
236 6 : bier_disp_table_entry_insert(bdti, src, bdei);
237 : }
238 :
239 6 : bier_disp_entry_path_add(bdei, payload_proto, rpaths);
240 : }
241 :
242 : void
243 6 : bier_disp_table_entry_path_remove (u32 table_id,
244 : bier_bp_t src,
245 : bier_hdr_proto_id_t payload_proto,
246 : const fib_route_path_t *rpath)
247 : {
248 : index_t bdti, bdei;
249 :
250 6 : bdti = bier_disp_table_find(table_id);
251 :
252 6 : if (INDEX_INVALID == bdti)
253 : {
254 0 : return;
255 : }
256 :
257 6 : bdei = bier_disp_table_lookup_hton(bdti, src);
258 :
259 6 : if (INDEX_INVALID != bdei)
260 : {
261 : int remove;
262 :
263 6 : remove = bier_disp_entry_path_remove(bdei, payload_proto, rpath);
264 :
265 6 : if (remove)
266 : {
267 6 : bier_disp_table_entry_remove(bdti, src);
268 6 : bier_disp_entry_unlock(bdei);
269 : }
270 : }
271 : }
272 :
273 : void
274 10 : bier_disp_table_walk (u32 table_id,
275 : bier_disp_table_walk_fn_t fn,
276 : void *ctx)
277 : {
278 : const bier_disp_table_t *bdt;
279 : const bier_disp_entry_t *bde;
280 : index_t bdti;
281 : u32 ii;
282 :
283 10 : bdti = bier_disp_table_find(table_id);
284 :
285 10 : if (INDEX_INVALID != bdti)
286 : {
287 10 : bdt = bier_disp_table_get(bdti);
288 :
289 655370 : for (ii = 0; ii < BIER_BP_MAX; ii++)
290 : {
291 655360 : if (INDEX_INVALID != bdt->bdt_db[ii])
292 : {
293 9 : u16 src = ii;
294 :
295 9 : bde = bier_disp_entry_get(bdt->bdt_db[ii]);
296 :
297 9 : fn(bdt, bde, clib_host_to_net_u16(src), ctx);
298 : }
299 : }
300 : }
301 10 : }
302 :
303 : static void
304 29 : bier_disp_table_dpo_lock (dpo_id_t *dpo)
305 : {
306 29 : bier_disp_table_lock(dpo->dpoi_index);
307 29 : }
308 :
309 : static void
310 29 : bier_disp_table_dpo_unlock (dpo_id_t *dpo)
311 : {
312 29 : bier_disp_table_unlock(dpo->dpoi_index);
313 29 : }
314 :
315 : static void
316 0 : bier_disp_table_dpo_mem_show (void)
317 : {
318 0 : fib_show_memory_usage("BIER disposition table",
319 0 : pool_elts(bier_disp_table_pool),
320 0 : pool_len(bier_disp_table_pool),
321 : sizeof(bier_disp_table_t));
322 0 : }
323 :
324 : const static dpo_vft_t bier_disp_table_dpo_vft = {
325 : .dv_lock = bier_disp_table_dpo_lock,
326 : .dv_unlock = bier_disp_table_dpo_unlock,
327 : .dv_mem_show = bier_disp_table_dpo_mem_show,
328 : .dv_format = format_bier_disp_table_dpo,
329 : };
330 :
331 : const static char *const bier_disp_table_bier_nodes[] =
332 : {
333 : "bier-disp-lookup",
334 : NULL
335 : };
336 :
337 : const static char * const * const bier_disp_table_nodes[DPO_PROTO_NUM] =
338 : {
339 : [DPO_PROTO_BIER] = bier_disp_table_bier_nodes,
340 : };
341 :
342 : clib_error_t *
343 575 : bier_disp_table_module_init (vlib_main_t *vm)
344 : {
345 575 : dpo_register(DPO_BIER_DISP_TABLE,
346 : &bier_disp_table_dpo_vft,
347 : bier_disp_table_nodes);
348 :
349 575 : bier_disp_table_id_to_index = hash_create(0, sizeof(index_t));
350 :
351 575 : return (NULL);
352 : }
353 :
354 93887 : VLIB_INIT_FUNCTION (bier_disp_table_module_init);
355 :
356 : static clib_error_t *
357 0 : show_bier_disp_table (vlib_main_t * vm,
358 : unformat_input_t * input,
359 : vlib_cli_command_t * cmd)
360 : {
361 : bier_disp_table_t *bdt;
362 : index_t bdti;
363 :
364 0 : bdti = INDEX_INVALID;
365 :
366 0 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
367 0 : if (unformat (input, "%d", &bdti))
368 : ;
369 0 : else if (unformat (input, "%d", &bdti))
370 : ;
371 : else
372 : {
373 0 : break;
374 : }
375 : }
376 :
377 0 : if (INDEX_INVALID == bdti)
378 : {
379 0 : pool_foreach (bdt, bier_disp_table_pool)
380 : {
381 0 : vlib_cli_output(vm, "%U", format_bier_disp_table,
382 : bier_disp_table_get_index(bdt),
383 : 0, BIER_SHOW_BRIEF);
384 : }
385 : }
386 : else
387 : {
388 0 : if (pool_is_free_index(bier_disp_table_pool, bdti))
389 : {
390 0 : vlib_cli_output(vm, "No such BIER disp table: %d", bdti);
391 : }
392 : else
393 : {
394 0 : vlib_cli_output(vm, "%U", format_bier_disp_table, bdti, 0,
395 : BIER_SHOW_DETAIL);
396 : }
397 : }
398 0 : return (NULL);
399 : }
400 :
401 285289 : VLIB_CLI_COMMAND (show_bier_disp_table_node, static) = {
402 : .path = "show bier disp table",
403 : .short_help = "show bier disp table [index]",
404 : .function = show_bier_disp_table,
405 : };
|