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)),
148 FIB_PATH_LIST_FWD_FLAG_COLLAPSE,
151 bier_disp_entry_path_list_walk_ctx_t ctx = {
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;
159 dpo_stack(DPO_BIER_DISP_ENTRY,
161 &bde->bde_fwd[pproto].bde_dpo,
166 bier_disp_entry_path_add (index_t bdei,
167 bier_hdr_proto_id_t pproto,
168 const fib_route_path_t *rpaths)
170 fib_node_index_t *pli, old_pli;
171 bier_disp_entry_t *bde;
173 bde = bier_disp_entry_get(bdei);
174 pli = &bde->bde_pl[pproto];
178 * create a new or update the exisitng path-list for this
181 if (FIB_NODE_INDEX_INVALID == *pli)
183 *pli = fib_path_list_create((FIB_PATH_LIST_FLAG_SHARED |
184 FIB_PATH_LIST_FLAG_NO_URPF),
189 *pli = fib_path_list_copy_and_path_add(old_pli,
190 (FIB_PATH_LIST_FLAG_SHARED |
191 FIB_PATH_LIST_FLAG_NO_URPF),
195 fib_path_list_lock(*pli);
196 fib_path_list_unlock(old_pli);
198 bier_disp_entry_restack(bde, pproto);
202 bier_disp_entry_path_remove (index_t bdei,
203 bier_hdr_proto_id_t pproto,
204 const fib_route_path_t *rpaths)
206 fib_node_index_t *pli, old_pli;
207 bier_disp_entry_t *bde;
209 bde = bier_disp_entry_get(bdei);
210 pli = &bde->bde_pl[pproto];
214 * update the exisitng path-list for this payload protocol
216 if (FIB_NODE_INDEX_INVALID != *pli)
218 *pli = fib_path_list_copy_and_path_remove(old_pli,
219 (FIB_PATH_LIST_FLAG_SHARED |
220 FIB_PATH_LIST_FLAG_NO_URPF),
223 fib_path_list_lock(*pli);
224 fib_path_list_unlock(old_pli);
226 bier_disp_entry_restack(bde, pproto);
230 * if there are no path-list defined for any payload protocol
231 * then this entry is OK for removal
235 FOR_EACH_BIER_HDR_PROTO(pproto)
237 if (FIB_NODE_INDEX_INVALID != bde->bde_pl[pproto])
248 format_bier_disp_entry (u8* s, va_list *args)
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;
256 bde = bier_disp_entry_get(bdei);
258 s = format(s, "%Ubier-disp:[%d]", format_white_space, indent, bdei);
260 FOR_EACH_BIER_HDR_PROTO(pproto)
262 if (INDEX_INVALID != bde->bde_pl[pproto])
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);
269 if (flags & BIER_SHOW_DETAIL)
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);
286 bier_disp_entry_contribute_forwarding (index_t bdei,
289 dpo_set(dpo, DPO_BIER_DISP_ENTRY, DPO_PROTO_BIER, bdei);
292 const static char* const bier_disp_entry_bier_nodes[] =
294 "bier-disp-dispatch",
298 const static char* const * const bier_disp_entry_nodes[DPO_PROTO_NUM] =
300 [DPO_PROTO_BIER] = bier_disp_entry_bier_nodes,
304 bier_disp_entry_dpo_lock (dpo_id_t *dpo)
306 bier_disp_entry_lock(dpo->dpoi_index);
310 bier_disp_entry_dpo_unlock (dpo_id_t *dpo)
312 bier_disp_entry_unlock(dpo->dpoi_index);
316 bier_disp_entry_dpo_mem_show (void)
318 fib_show_memory_usage("BIER dispositon",
319 pool_elts(bier_disp_entry_pool),
320 pool_len(bier_disp_entry_pool),
321 sizeof(bier_disp_entry_t));
325 format_bier_disp_entry_dpo (u8* s, va_list *ap)
327 index_t index = va_arg(*ap, index_t);
328 u32 indent = va_arg(*ap, u32);
330 s = format(s, "%U", format_bier_disp_entry, index, indent, BIER_SHOW_DETAIL);
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,
343 bier_disp_entry_db_module_init (vlib_main_t *vm)
345 dpo_register(DPO_BIER_DISP_ENTRY,
346 &bier_disp_entry_vft,
347 bier_disp_entry_nodes);
352 VLIB_INIT_FUNCTION (bier_disp_entry_db_module_init);
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)
361 bdei = INDEX_INVALID;
363 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
364 if (unformat (input, "%d", &bdei))
372 if (INDEX_INVALID == bdei)
378 vlib_cli_output(vm, "%U", format_bier_disp_entry, bdei, 1,
384 VLIB_CLI_COMMAND (show_bier_disp_entry_node, static) = {
385 .path = "show bier disp entry",
386 .short_help = "show bier disp entry index",
387 .function = show_bier_disp_entry,