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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 * bier_dispositon : The BIER dispositon object
18 * A BIER dispositon object is present in the IP mcast output list
19 * and represents the dispositon of a BIER bitmask. After BIER header
20 * dispositon the packet is forward within the appropriate/specifid
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>
30 * The memory pool of all imp objects
32 bier_disp_entry_t *bier_disp_entry_pool;
35 * When constructing the BIER imp ID from an index and BSL, shift
38 #define BIER_DISP_ENTRY_ID_HLEN_SHIFT 24
41 bier_disp_entry_lock_i (bier_disp_entry_t *bde)
47 bier_disp_entry_lock (index_t bdei)
49 bier_disp_entry_lock_i(bier_disp_entry_get(bdei));
53 bier_disp_entry_get_index(bier_disp_entry_t *bde)
55 return (bde - bier_disp_entry_pool);
59 bier_disp_entry_add_or_lock (void)
61 dpo_id_t invalid = DPO_INVALID;
62 bier_hdr_proto_id_t pproto;
63 bier_disp_entry_t *bde;
65 pool_get_aligned(bier_disp_entry_pool, bde, CLIB_CACHE_LINE_BYTES);
69 FOR_EACH_BIER_HDR_PROTO(pproto)
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;
76 bier_disp_entry_lock_i(bde);
77 return (bier_disp_entry_get_index(bde));
81 bier_disp_entry_unlock (index_t bdei)
83 bier_disp_entry_t *bde;
85 if (INDEX_INVALID == bdei)
90 bde = bier_disp_entry_get(bdei);
94 if (0 == bde->bde_locks)
96 bier_hdr_proto_id_t pproto;
98 FOR_EACH_BIER_HDR_PROTO(pproto)
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]);
104 pool_put(bier_disp_entry_pool, bde);
108 typedef struct bier_disp_entry_path_list_walk_ctx_t_
111 } bier_disp_entry_path_list_walk_ctx_t;
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,
118 bier_disp_entry_path_list_walk_ctx_t *ctx = arg;
120 ctx->bdew_rpf_id = fib_path_get_rpf_id(path_index);
122 if (~0 != ctx->bdew_rpf_id)
124 return (FIB_PATH_LIST_WALK_STOP);
126 return (FIB_PATH_LIST_WALK_CONTINUE);
130 bier_disp_entry_restack (bier_disp_entry_t *bde,
131 bier_hdr_proto_id_t pproto)
133 dpo_id_t via_dpo = DPO_INVALID;
134 fib_node_index_t pli;
136 pli = bde->bde_pl[pproto];
138 if (FIB_NODE_INDEX_INVALID == pli)
141 drop_dpo_get(bier_hdr_proto_to_dpo(pproto)));
145 fib_path_list_contribute_forwarding(pli,
146 fib_forw_chain_type_from_dpo_proto(
147 bier_hdr_proto_to_dpo(pproto)),
150 bier_disp_entry_path_list_walk_ctx_t ctx = {
154 fib_path_list_walk(pli, bier_disp_entry_path_list_walk, &ctx);
155 bde->bde_fwd[pproto].bde_rpf_id = ctx.bdew_rpf_id;
158 dpo_stack(DPO_BIER_DISP_ENTRY,
160 &bde->bde_fwd[pproto].bde_dpo,
165 bier_disp_entry_path_add (index_t bdei,
166 bier_hdr_proto_id_t pproto,
167 const fib_route_path_t *rpaths)
169 fib_node_index_t *pli, old_pli;
170 bier_disp_entry_t *bde;
172 bde = bier_disp_entry_get(bdei);
173 pli = &bde->bde_pl[pproto];
177 * create a new or update the exisitng path-list for this
180 if (FIB_NODE_INDEX_INVALID == *pli)
182 *pli = fib_path_list_create((FIB_PATH_LIST_FLAG_SHARED |
183 FIB_PATH_LIST_FLAG_NO_URPF),
188 *pli = fib_path_list_copy_and_path_add(old_pli,
189 (FIB_PATH_LIST_FLAG_SHARED |
190 FIB_PATH_LIST_FLAG_NO_URPF),
194 fib_path_list_lock(*pli);
195 fib_path_list_unlock(old_pli);
197 bier_disp_entry_restack(bde, pproto);
201 bier_disp_entry_path_remove (index_t bdei,
202 bier_hdr_proto_id_t pproto,
203 const fib_route_path_t *rpaths)
205 fib_node_index_t *pli, old_pli;
206 bier_disp_entry_t *bde;
208 bde = bier_disp_entry_get(bdei);
209 pli = &bde->bde_pl[pproto];
213 * update the exisitng path-list for this payload protocol
215 if (FIB_NODE_INDEX_INVALID != *pli)
217 *pli = fib_path_list_copy_and_path_remove(old_pli,
218 (FIB_PATH_LIST_FLAG_SHARED |
219 FIB_PATH_LIST_FLAG_NO_URPF),
222 fib_path_list_lock(*pli);
223 fib_path_list_unlock(old_pli);
225 bier_disp_entry_restack(bde, pproto);
229 * if there are no path-list defined for any payload protocol
230 * then this entry is OK for removal
234 FOR_EACH_BIER_HDR_PROTO(pproto)
236 if (FIB_NODE_INDEX_INVALID != bde->bde_pl[pproto])
247 format_bier_disp_entry (u8* s, va_list *args)
249 index_t bdei = va_arg (*args, index_t);
250 u32 indent = va_arg(*args, u32);
251 bier_show_flags_t flags = va_arg(*args, bier_show_flags_t);
252 bier_hdr_proto_id_t pproto;
253 bier_disp_entry_t *bde;
255 bde = bier_disp_entry_get(bdei);
257 s = format(s, "bier-disp:[%d]", bdei);
259 FOR_EACH_BIER_HDR_PROTO(pproto)
261 if (INDEX_INVALID != bde->bde_pl[pproto])
264 s = fib_path_list_format(bde->bde_pl[pproto], s);
266 if (flags & BIER_SHOW_DETAIL)
268 s = format(s, "\n%UForwarding:",
269 format_white_space, indent);
270 s = format(s, "\n%Urpf-id:%d",
271 format_white_space, indent+1,
272 bde->bde_fwd[pproto].bde_rpf_id);
273 s = format(s, "\n%U%U",
274 format_white_space, indent+1,
275 format_dpo_id, &bde->bde_fwd[pproto].bde_dpo, indent+2);
283 bier_disp_entry_contribute_forwarding (index_t bdei,
286 dpo_set(dpo, DPO_BIER_DISP_ENTRY, DPO_PROTO_BIER, bdei);
289 const static char* const bier_disp_entry_bier_nodes[] =
291 "bier-disp-dispatch",
295 const static char* const * const bier_disp_entry_nodes[DPO_PROTO_NUM] =
297 [DPO_PROTO_BIER] = bier_disp_entry_bier_nodes,
301 bier_disp_entry_dpo_lock (dpo_id_t *dpo)
303 bier_disp_entry_lock(dpo->dpoi_index);
307 bier_disp_entry_dpo_unlock (dpo_id_t *dpo)
309 bier_disp_entry_unlock(dpo->dpoi_index);
313 bier_disp_entry_dpo_mem_show (void)
315 fib_show_memory_usage("BIER dispositon",
316 pool_elts(bier_disp_entry_pool),
317 pool_len(bier_disp_entry_pool),
318 sizeof(bier_disp_entry_t));
322 format_bier_disp_entry_dpo (u8* s, va_list *ap)
324 index_t index = va_arg(*ap, index_t);
325 u32 indent = va_arg(*ap, u32);
327 s = format(s, "%U", format_bier_disp_entry, index, indent, BIER_SHOW_DETAIL);
332 const static dpo_vft_t bier_disp_entry_vft = {
333 .dv_lock = bier_disp_entry_dpo_lock,
334 .dv_unlock = bier_disp_entry_dpo_unlock,
335 .dv_format = format_bier_disp_entry_dpo,
336 .dv_mem_show = bier_disp_entry_dpo_mem_show,
340 bier_disp_entry_db_module_init (vlib_main_t *vm)
342 dpo_register(DPO_BIER_DISP_ENTRY,
343 &bier_disp_entry_vft,
344 bier_disp_entry_nodes);
349 VLIB_INIT_FUNCTION (bier_disp_entry_db_module_init);
351 static clib_error_t *
352 show_bier_disp_entry (vlib_main_t * vm,
353 unformat_input_t * input,
354 vlib_cli_command_t * cmd)
358 bdei = INDEX_INVALID;
360 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
361 if (unformat (input, "%d", &bdei))
369 if (INDEX_INVALID == bdei)
375 vlib_cli_output(vm, "%U", format_bier_disp_entry, bdei, 1,
381 VLIB_CLI_COMMAND (show_bier_disp_entry_node, static) = {
382 .path = "show bier disp entry",
383 .short_help = "show bier disp entry index",
384 .function = show_bier_disp_entry,