blob: cf9f0538df7213557c5d2f9d10c05d2c504a8cc6 [file] [log] [blame]
Neale Rannsd792d9c2017-10-21 10:53:20 -07001/*
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 */
22bier_disp_table_t *bier_disp_table_pool;
23
24/**
25 * Hash table to map client table IDs to VPP index
26 */
27static uword *bier_disp_table_id_to_index;
28
29static index_t
30bier_disp_table_get_index (const bier_disp_table_t *bdt)
31{
32 return (bdt - bier_disp_table_pool);
33}
34
35static void
36bier_disp_table_lock_i (bier_disp_table_t *bdt)
37{
38 bdt->bdt_locks++;
39}
40
41index_t
42bier_disp_table_find(u32 table_id)
43{
44 uword *p;
45
46 p = hash_get(bier_disp_table_id_to_index, table_id);
47
48 if (NULL != p)
49 {
50 return (p[0]);
51 }
52
53 return (INDEX_INVALID);
54}
55
56index_t
57bier_disp_table_add_or_lock (u32 table_id)
58{
59 bier_disp_table_t *bdt;
60 index_t bdti;
61
62 bdti = bier_disp_table_find(table_id);
63
64 if (INDEX_INVALID == bdti)
65 {
66 pool_get_aligned(bier_disp_table_pool, bdt,
67 CLIB_CACHE_LINE_BYTES);
68
69 bdt->bdt_table_id = table_id;
70 bdt->bdt_locks = 0;
71
72 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 */
Dave Barachb7b92992018-10-17 10:38:51 -040078 clib_memset(bdt->bdt_db, 0xff, sizeof(bdt->bdt_db));
Neale Rannsd792d9c2017-10-21 10:53:20 -070079 }
80 else
81 {
82 bdt = pool_elt_at_index(bier_disp_table_pool, bdti);
83 }
84
85 bier_disp_table_lock_i(bdt);
86
87 return (bier_disp_table_get_index(bdt));
88}
89
90void
91bier_disp_table_unlock_w_table_id (u32 table_id)
92{
93 index_t bdti;
94
95 bdti = bier_disp_table_find(table_id);
96
97 if (INDEX_INVALID != bdti)
98 {
99 bier_disp_table_unlock(bdti);
100 }
101}
102
103void
104bier_disp_table_unlock (index_t bdti)
105{
106 bier_disp_table_t *bdt;
107
108 bdt = bier_disp_table_get(bdti);
109
110 bdt->bdt_locks--;
111
112 if (0 == bdt->bdt_locks)
113 {
114 u32 ii;
115
116 for (ii = 0; ii < BIER_BP_MAX; ii++)
117 {
118 bier_disp_entry_unlock(bdt->bdt_db[ii]);
119 }
120 hash_unset(bier_disp_table_id_to_index, bdt->bdt_table_id);
121 pool_put(bier_disp_table_pool, bdt);
122 }
123}
124
125void
126bier_disp_table_lock (index_t bdti)
127{
128 bier_disp_table_lock_i(bier_disp_table_get(bdti));
129}
130
131void
132bier_disp_table_contribute_forwarding (index_t bdti,
133 dpo_id_t *dpo)
134{
135 dpo_set(dpo,
136 DPO_BIER_DISP_TABLE,
137 DPO_PROTO_BIER,
138 bdti);
139}
140
141
142u8*
143format_bier_disp_table (u8* s, va_list *ap)
144{
145 index_t bdti = va_arg(*ap, index_t);
146 u32 indent = va_arg(*ap, u32);
147 bier_show_flags_t flags = va_arg(*ap, bier_show_flags_t);
148 bier_disp_table_t *bdt;
149
150 bdt = bier_disp_table_get(bdti);
151
152 s = format(s, "bier-disp-table:[%d]; table-id:%d locks:%d",
153 bdti, bdt->bdt_table_id, bdt->bdt_locks);
154
155 if (flags & BIER_SHOW_DETAIL)
156 {
157 u32 ii;
158
159 for (ii = 0; ii < BIER_BP_MAX; ii++)
160 {
161 if (INDEX_INVALID != bdt->bdt_db[ii])
162 {
163 u16 src = ii;
Neale Ranns91286372017-12-05 13:24:04 -0800164 s = format(s, "\n%Usrc:%d", format_white_space, indent+1,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700165 clib_host_to_net_u16(src));
Neale Ranns91286372017-12-05 13:24:04 -0800166 s = format(s, "\n%U",
Neale Rannsd792d9c2017-10-21 10:53:20 -0700167 format_bier_disp_entry, bdt->bdt_db[ii],
168 indent+4, BIER_SHOW_BRIEF);
169 }
170 }
171 }
172 return (s);
173}
174
175static u8*
176format_bier_disp_table_dpo (u8* s, va_list *ap)
177{
178 index_t bdti = va_arg(*ap, index_t);
179 u32 indent = va_arg(*ap, u32);
180
181 return (format(s, "%U",
182 format_bier_disp_table, bdti, indent,
183 BIER_SHOW_BRIEF));
184}
185
186static void
187bier_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 bdt = bier_disp_table_get(bdti);
194 bdt->bdt_db[clib_host_to_net_u16(src)] = bdei;
195}
196
197static void
198bier_disp_table_entry_remove (index_t bdti,
199 bier_bp_t src)
200{
201 bier_disp_table_t *bdt;
202
203 bdt = bier_disp_table_get(bdti);
204 bdt->bdt_db[clib_host_to_net_u16(src)] = INDEX_INVALID;
205}
206
207static index_t
208bier_disp_table_lookup_hton(index_t bdti,
Neale Ranns93149bb2017-11-15 10:44:07 -0800209 bier_bp_t bp)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700210{
Neale Ranns93149bb2017-11-15 10:44:07 -0800211 bier_hdr_src_id_t src = bp;
212
Neale Rannsf0510722018-01-31 11:35:41 -0800213 return (bier_disp_table_lookup(bdti, clib_host_to_net_u16(src)));
Neale Rannsd792d9c2017-10-21 10:53:20 -0700214}
215
216void
217bier_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 bdti = bier_disp_table_find(table_id);
225
226 if (INDEX_INVALID == bdti)
227 {
228 return;
229 }
230
231 bdei = bier_disp_table_lookup_hton(bdti, src);
232
233 if (INDEX_INVALID == bdei)
234 {
235 bdei = bier_disp_entry_add_or_lock();
236 bier_disp_table_entry_insert(bdti, src, bdei);
237 }
238
239 bier_disp_entry_path_add(bdei, payload_proto, rpaths);
240}
241
242void
243bier_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 bdti = bier_disp_table_find(table_id);
251
252 if (INDEX_INVALID == bdti)
253 {
254 return;
255 }
256
257 bdei = bier_disp_table_lookup_hton(bdti, src);
258
259 if (INDEX_INVALID != bdei)
260 {
261 int remove;
262
263 remove = bier_disp_entry_path_remove(bdei, payload_proto, rpath);
264
265 if (remove)
266 {
267 bier_disp_table_entry_remove(bdti, src);
268 bier_disp_entry_unlock(bdei);
269 }
270 }
271}
272
273void
274bier_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 bdti = bier_disp_table_find(table_id);
284
285 if (INDEX_INVALID != bdti)
286 {
287 bdt = bier_disp_table_get(bdti);
288
289 for (ii = 0; ii < BIER_BP_MAX; ii++)
290 {
291 if (INDEX_INVALID != bdt->bdt_db[ii])
292 {
293 u16 src = ii;
294
295 bde = bier_disp_entry_get(bdt->bdt_db[ii]);
296
297 fn(bdt, bde, clib_host_to_net_u16(src), ctx);
298 }
299 }
300 }
301}
302
303static void
304bier_disp_table_dpo_lock (dpo_id_t *dpo)
305{
306 bier_disp_table_lock(dpo->dpoi_index);
307}
308
309static void
310bier_disp_table_dpo_unlock (dpo_id_t *dpo)
311{
312 bier_disp_table_unlock(dpo->dpoi_index);
313}
314
315static void
316bier_disp_table_dpo_mem_show (void)
317{
318 fib_show_memory_usage("BIER disposition table",
319 pool_elts(bier_disp_table_pool),
320 pool_len(bier_disp_table_pool),
321 sizeof(bier_disp_table_t));
322}
323
324const 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
331const static char *const bier_disp_table_bier_nodes[] =
332{
Gabriel Ganne0f8a96c2017-11-14 14:43:34 +0100333 "bier-disp-lookup",
334 NULL
Neale Rannsd792d9c2017-10-21 10:53:20 -0700335};
336
337const static char * const * const bier_disp_table_nodes[DPO_PROTO_NUM] =
338{
339 [DPO_PROTO_BIER] = bier_disp_table_bier_nodes,
340};
341
342clib_error_t *
343bier_disp_table_module_init (vlib_main_t *vm)
344{
345 dpo_register(DPO_BIER_DISP_TABLE,
346 &bier_disp_table_dpo_vft,
347 bier_disp_table_nodes);
348
349 bier_disp_table_id_to_index = hash_create(0, sizeof(index_t));
350
351 return (NULL);
352}
353
354VLIB_INIT_FUNCTION (bier_disp_table_module_init);
355
356static clib_error_t *
357show_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 bdti = INDEX_INVALID;
365
366 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
367 if (unformat (input, "%d", &bdti))
368 ;
369 else if (unformat (input, "%d", &bdti))
370 ;
371 else
372 {
373 break;
374 }
375 }
376
377 if (INDEX_INVALID == bdti)
378 {
379 pool_foreach(bdt, bier_disp_table_pool,
380 ({
381 vlib_cli_output(vm, "%U", format_bier_disp_table,
382 bier_disp_table_get_index(bdt),
Neale Ranns91286372017-12-05 13:24:04 -0800383 0, BIER_SHOW_BRIEF);
Neale Rannsd792d9c2017-10-21 10:53:20 -0700384 }));
385 }
386 else
387 {
Neale Ranns8f6e3212018-06-04 17:10:18 -0700388 if (pool_is_free_index(bier_disp_table_pool, bdti))
389 {
390 vlib_cli_output(vm, "No such BIER disp table: %d", bdti);
391 }
392 else
393 {
394 vlib_cli_output(vm, "%U", format_bier_disp_table, bdti, 0,
395 BIER_SHOW_DETAIL);
396 }
Neale Rannsd792d9c2017-10-21 10:53:20 -0700397 }
398 return (NULL);
399}
400
401VLIB_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};