Typos. A bunch of typos I've been collecting.
[vpp.git] / src / vnet / bier / bier_disp_entry.c
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  * bier_dispositon : The BIER disposition object
17  *
18  * A BIER disposition object is present in the IP mcast output list
19  * and represents the disposition of a BIER bitmask. After BIER header
20  * disposition the packet is forward within the appropriate/specified
21  * BIER table
22  */
23
24 #include <vnet/bier/bier_disp_entry.h>
25 #include <vnet/bier/bier_hdr_inlines.h>
26 #include <vnet/fib/fib_path_list.h>
27 #include <vnet/dpo/drop_dpo.h>
28
29 /**
30  * The memory pool of all imp objects
31  */
32 bier_disp_entry_t *bier_disp_entry_pool;
33
34 /**
35  * When constructing the BIER imp ID from an index and BSL, shift
36  * the BSL this far
37  */
38 #define BIER_DISP_ENTRY_ID_HLEN_SHIFT 24
39
40 static void
41 bier_disp_entry_lock_i (bier_disp_entry_t *bde)
42 {
43     bde->bde_locks++;
44 }
45
46 void
47 bier_disp_entry_lock (index_t bdei)
48 {
49     bier_disp_entry_lock_i(bier_disp_entry_get(bdei));
50 }
51
52 static index_t
53 bier_disp_entry_get_index(bier_disp_entry_t *bde)
54 {
55     return (bde - bier_disp_entry_pool);
56 }
57
58 index_t
59 bier_disp_entry_add_or_lock (void)
60 {
61     dpo_id_t invalid = DPO_INVALID;
62     bier_hdr_proto_id_t pproto;
63     bier_disp_entry_t *bde;
64
65     pool_get_aligned(bier_disp_entry_pool, bde, CLIB_CACHE_LINE_BYTES);
66
67     bde->bde_locks = 0;
68
69     FOR_EACH_BIER_HDR_PROTO(pproto)
70     {
71         bde->bde_fwd[pproto].bde_dpo = invalid;
72         bde->bde_fwd[pproto].bde_rpf_id = ~0;
73         bde->bde_pl[pproto] = FIB_NODE_INDEX_INVALID;
74     }
75
76     bier_disp_entry_lock_i(bde);
77     return (bier_disp_entry_get_index(bde));
78 }
79
80 void
81 bier_disp_entry_unlock (index_t bdei)
82 {
83     bier_disp_entry_t *bde;
84
85     if (INDEX_INVALID == bdei)
86     {
87         return;
88     }
89
90     bde = bier_disp_entry_get(bdei);
91
92     bde->bde_locks--;
93
94     if (0 == bde->bde_locks)
95     {
96         bier_hdr_proto_id_t pproto;
97
98         FOR_EACH_BIER_HDR_PROTO(pproto)
99         {
100             dpo_unlock(&bde->bde_fwd[pproto].bde_dpo);
101             bde->bde_fwd[pproto].bde_rpf_id = ~0;
102             fib_path_list_unlock(bde->bde_pl[pproto]);
103         }
104         pool_put(bier_disp_entry_pool, bde);
105     }
106 }
107
108 typedef struct bier_disp_entry_path_list_walk_ctx_t_
109 {
110     u32 bdew_rpf_id;
111 } bier_disp_entry_path_list_walk_ctx_t;
112
113 static fib_path_list_walk_rc_t
114 bier_disp_entry_path_list_walk (fib_node_index_t pl_index,
115                                 fib_node_index_t path_index,
116                                 void *arg)
117 {
118     bier_disp_entry_path_list_walk_ctx_t *ctx = arg;
119
120     ctx->bdew_rpf_id = fib_path_get_rpf_id(path_index);
121
122     if (~0 != ctx->bdew_rpf_id)
123     {
124         return (FIB_PATH_LIST_WALK_STOP);
125     }
126     return (FIB_PATH_LIST_WALK_CONTINUE);
127 }
128
129 static void
130 bier_disp_entry_restack (bier_disp_entry_t *bde,
131                          bier_hdr_proto_id_t pproto)
132 {
133     dpo_id_t via_dpo = DPO_INVALID;
134     fib_node_index_t pli;
135
136     pli = bde->bde_pl[pproto];
137
138     if (FIB_NODE_INDEX_INVALID == pli)
139     {
140         dpo_copy(&via_dpo,
141                  drop_dpo_get(bier_hdr_proto_to_dpo(pproto)));
142     }
143     else
144     {
145         fib_path_list_contribute_forwarding(pli,
146                                             fib_forw_chain_type_from_dpo_proto(
147                                                 bier_hdr_proto_to_dpo(pproto)),
148                                             FIB_PATH_LIST_FWD_FLAG_COLLAPSE,
149                                             &via_dpo);
150
151         bier_disp_entry_path_list_walk_ctx_t ctx = {
152             .bdew_rpf_id = ~0,
153         };
154
155         fib_path_list_walk(pli, bier_disp_entry_path_list_walk, &ctx);
156         bde->bde_fwd[pproto].bde_rpf_id = ctx.bdew_rpf_id;
157     }
158
159     dpo_stack(DPO_BIER_DISP_ENTRY,
160               DPO_PROTO_BIER,
161               &bde->bde_fwd[pproto].bde_dpo,
162               &via_dpo);
163 }
164
165 void
166 bier_disp_entry_path_add (index_t bdei,
167                           bier_hdr_proto_id_t pproto,
168                           const fib_route_path_t *rpaths)
169 {
170     fib_node_index_t *pli, old_pli;
171     bier_disp_entry_t *bde;
172
173     bde = bier_disp_entry_get(bdei);
174     pli = &bde->bde_pl[pproto];
175     old_pli = *pli;
176
177     /*
178      * create a new or update the exisitng path-list for this
179      * payload protocol
180      */
181     if (FIB_NODE_INDEX_INVALID == *pli)
182     {
183         *pli = fib_path_list_create((FIB_PATH_LIST_FLAG_SHARED |
184                                      FIB_PATH_LIST_FLAG_NO_URPF),
185                                     rpaths);
186     }
187     else
188     {
189         *pli = fib_path_list_copy_and_path_add(old_pli,
190                                                (FIB_PATH_LIST_FLAG_SHARED |
191                                                 FIB_PATH_LIST_FLAG_NO_URPF),
192                                                rpaths);
193     }
194
195     fib_path_list_lock(*pli);
196     fib_path_list_unlock(old_pli);
197
198     bier_disp_entry_restack(bde, pproto);
199 }
200
201 int
202 bier_disp_entry_path_remove (index_t bdei,
203                              bier_hdr_proto_id_t pproto,
204                              const fib_route_path_t *rpaths)
205 {
206     fib_node_index_t *pli, old_pli;
207     bier_disp_entry_t *bde;
208
209     bde = bier_disp_entry_get(bdei);
210     pli = &bde->bde_pl[pproto];
211     old_pli = *pli;
212
213     /*
214      * update the exisitng path-list for this payload protocol
215      */
216     if (FIB_NODE_INDEX_INVALID != *pli)
217     {
218         *pli = fib_path_list_copy_and_path_remove(old_pli,
219                                                   (FIB_PATH_LIST_FLAG_SHARED |
220                                                    FIB_PATH_LIST_FLAG_NO_URPF),
221                                                   rpaths);
222
223         fib_path_list_lock(*pli);
224         fib_path_list_unlock(old_pli);
225
226         bier_disp_entry_restack(bde, pproto);
227     }
228
229     /*
230      * if there are no path-list defined for any payload protocol
231      * then this entry is OK for removal
232      */
233     int remove = 1;
234
235     FOR_EACH_BIER_HDR_PROTO(pproto)
236     {
237         if (FIB_NODE_INDEX_INVALID != bde->bde_pl[pproto])
238         {
239             remove = 0;
240             break;
241         }
242     }
243
244     return (remove);
245 }
246
247 u8*
248 format_bier_disp_entry (u8* s, va_list *args)
249 {
250     index_t bdei = va_arg (*args, index_t);
251     u32 indent = va_arg(*args, u32);
252     bier_show_flags_t flags = va_arg(*args, bier_show_flags_t);
253     bier_hdr_proto_id_t pproto;
254     bier_disp_entry_t *bde;
255
256     bde = bier_disp_entry_get(bdei);
257
258     s = format(s, "%Ubier-disp:[%d]", format_white_space, indent, bdei);
259
260     FOR_EACH_BIER_HDR_PROTO(pproto)
261     {
262         if (INDEX_INVALID != bde->bde_pl[pproto])
263         {
264             s = format(s, "\n%U%U\n",
265                        format_white_space, indent+2,
266                        format_bier_hdr_proto, pproto);
267             s = format(s, "%U", format_fib_path_list, bde->bde_pl[pproto], indent+4);
268
269             if (flags & BIER_SHOW_DETAIL)
270             {
271                 s = format(s, "\n%UForwarding:",
272                            format_white_space, indent+4);
273                 s = format(s, "\n%Urpf-id:%d",
274                            format_white_space, indent+6,
275                            bde->bde_fwd[pproto].bde_rpf_id);
276                 s = format(s, "\n%U%U",
277                            format_white_space, indent+6,
278                            format_dpo_id, &bde->bde_fwd[pproto].bde_dpo, indent+2);
279             }
280         }
281     }
282     return (s);
283 }
284
285 void
286 bier_disp_entry_contribute_forwarding (index_t bdei,
287                                        dpo_id_t *dpo)
288 {
289     dpo_set(dpo, DPO_BIER_DISP_ENTRY, DPO_PROTO_BIER, bdei);
290 }
291
292 const static char* const bier_disp_entry_bier_nodes[] =
293 {
294     "bier-disp-dispatch",
295     NULL,
296 };
297
298 const static char* const * const bier_disp_entry_nodes[DPO_PROTO_NUM] =
299 {
300     [DPO_PROTO_BIER]  = bier_disp_entry_bier_nodes,
301 };
302
303 static void
304 bier_disp_entry_dpo_lock (dpo_id_t *dpo)
305 {
306     bier_disp_entry_lock(dpo->dpoi_index);
307 }
308
309 static void
310 bier_disp_entry_dpo_unlock (dpo_id_t *dpo)
311 {
312     bier_disp_entry_unlock(dpo->dpoi_index);
313 }
314
315 static void
316 bier_disp_entry_dpo_mem_show (void)
317 {
318     fib_show_memory_usage("BIER disposition",
319                           pool_elts(bier_disp_entry_pool),
320                           pool_len(bier_disp_entry_pool),
321                           sizeof(bier_disp_entry_t));
322 }
323
324 static u8*
325 format_bier_disp_entry_dpo (u8* s, va_list *ap)
326 {
327     index_t index = va_arg(*ap, index_t);
328     u32 indent = va_arg(*ap, u32);
329
330     s = format(s, "%U", format_bier_disp_entry, index, indent, BIER_SHOW_DETAIL);
331
332     return (s);
333 }
334
335 const static dpo_vft_t bier_disp_entry_vft = {
336     .dv_lock = bier_disp_entry_dpo_lock,
337     .dv_unlock = bier_disp_entry_dpo_unlock,
338     .dv_format = format_bier_disp_entry_dpo,
339     .dv_mem_show = bier_disp_entry_dpo_mem_show,
340 };
341
342 clib_error_t *
343 bier_disp_entry_db_module_init (vlib_main_t *vm)
344 {
345     dpo_register(DPO_BIER_DISP_ENTRY,
346                  &bier_disp_entry_vft,
347                  bier_disp_entry_nodes);
348
349     return (NULL);
350 }
351
352 VLIB_INIT_FUNCTION (bier_disp_entry_db_module_init);
353
354 static clib_error_t *
355 show_bier_disp_entry (vlib_main_t * vm,
356                unformat_input_t * input,
357                vlib_cli_command_t * cmd)
358 {
359     index_t bdei;
360
361     bdei = INDEX_INVALID;
362
363     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
364         if (unformat (input, "%d", &bdei))
365             ;
366         else
367         {
368             break;
369         }
370     }
371
372     if (INDEX_INVALID == bdei)
373     {
374         return (NULL);
375     }
376     else
377     {
378         if (pool_is_free_index(bier_disp_entry_pool, bdei))
379         {
380             vlib_cli_output(vm, "No such BIER disp entry: %d", bdei);
381         }
382         else
383         {
384             vlib_cli_output(vm, "%U", format_bier_disp_entry, bdei, 1,
385                             BIER_SHOW_DETAIL);
386         }
387     }
388     return (NULL);
389 }
390
391 VLIB_CLI_COMMAND (show_bier_disp_entry_node, static) = {
392     .path = "show bier disp entry",
393     .short_help = "show bier disp entry index",
394     .function = show_bier_disp_entry,
395 };