From ef90ed08fbcde7535b4a789349b39dc25798c77d Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Thu, 13 Sep 2018 08:45:12 -0700 Subject: BIER API and load-balancing fixes Change-Id: Ibda19d786070c942c75016ab568c8361de2f24af Signed-off-by: Neale Ranns --- src/vnet/bier/bier.api | 2 + src/vnet/bier/bier_api.c | 17 +++++-- src/vnet/bier/bier_entry.c | 105 ++++++++++++++++++++++++++++++++++---------- src/vnet/bier/bier_entry.h | 3 ++ src/vnet/bier/bier_fmask.c | 18 ++++---- src/vnet/bier/bier_fwd.h | 32 ++++++++++++++ src/vnet/bier/bier_lookup.c | 6 +-- src/vnet/bier/bier_table.c | 88 ++++++++++++++++++++++++++++++++----- src/vnet/bier/bier_table.h | 17 ++++--- src/vnet/bier/bier_test.c | 24 +++++----- src/vnet/bier/bier_update.c | 8 ++-- src/vnet/dpo/load_balance.c | 4 +- src/vnet/mpls/mpls_lookup.h | 5 +++ 13 files changed, 257 insertions(+), 72 deletions(-) create mode 100644 src/vnet/bier/bier_fwd.h (limited to 'src') diff --git a/src/vnet/bier/bier.api b/src/vnet/bier/bier.api index fb6923b4a01..da2989bbe44 100644 --- a/src/vnet/bier/bier.api +++ b/src/vnet/bier/bier.api @@ -72,6 +72,8 @@ define bier_table_details @param br_is_add - Is this a route add or delete @param br_is_replace - Are the paths specfied replacing those already present or are they to be combined. + is_replace = 1 and n_paths=0 implies delete the + route and all paths; @param br_n_paths - The number of paths @param br_paths - The array of paths */ diff --git a/src/vnet/bier/bier_api.c b/src/vnet/bier/bier_api.c index 93048a0a890..2e8fc626baa 100644 --- a/src/vnet/bier/bier_api.c +++ b/src/vnet/bier/bier_api.c @@ -204,13 +204,24 @@ vl_api_bier_route_add_del_t_handler (vl_api_bier_route_add_del_t * mp) } } - if (mp->br_is_add) + if (mp->br_is_replace) { - bier_table_route_add(&bti, bp, brpaths); + if (0 == vec_len(brpaths)) + { + bier_table_route_delete(&bti, bp); + } + else + { + bier_table_route_path_update(&bti, bp, brpaths); + } + } + else if (mp->br_is_add) + { + bier_table_route_path_add(&bti, bp, brpaths); } else { - bier_table_route_remove(&bti, bp, brpaths); + bier_table_route_path_remove(&bti, bp, brpaths); } vec_free(brpaths); diff --git a/src/vnet/bier/bier_entry.c b/src/vnet/bier/bier_entry.c index 2f8d25008cc..80f7cfd8e56 100644 --- a/src/vnet/bier/bier_entry.c +++ b/src/vnet/bier/bier_entry.c @@ -73,27 +73,6 @@ bier_entry_create (index_t bti, return (bier_entry_get_index(be)); } -void -bier_entry_delete (index_t bei) -{ - bier_entry_t *be; - - be = bier_entry_get(bei); - - /* - * if we still ahve a path-list, unlink from it - */ - if (FIB_NODE_INDEX_INVALID != be->be_path_list) - { - fib_path_list_walk(be->be_path_list, - bier_entry_unlink_walk, - be); - fib_path_list_child_remove(be->be_path_list, - be->be_sibling_index); - } - - pool_put(bier_entry_pool, be); -} static void bier_entry_table_ecmp_walk_add_fmask (index_t btei, @@ -160,6 +139,33 @@ bier_entry_table_ecmp_walk_add_fmask (index_t btei, } } +void +bier_entry_delete (index_t bei) +{ + bier_entry_t *be; + + be = bier_entry_get(bei); + + /* + * if we still ahve a path-list, unlink from it + */ + if (FIB_NODE_INDEX_INVALID != be->be_path_list) + { + fib_path_list_walk(be->be_path_list, + bier_entry_unlink_walk, + be); + fib_path_list_child_remove(be->be_path_list, + be->be_sibling_index); + + be->be_path_list = FIB_NODE_INDEX_INVALID; + bier_table_ecmp_walk(be->be_bti, + bier_entry_table_ecmp_walk_add_fmask, + be); + } + + pool_put(bier_entry_pool, be); +} + void bier_entry_path_add (index_t bei, const fib_route_path_t *rpaths) @@ -230,6 +236,62 @@ bier_entry_path_add (index_t bei, fib_path_list_unlock(old_pl_index); } +void +bier_entry_path_update (index_t bei, + const fib_route_path_t *rpaths) +{ + fib_node_index_t old_pl_index; + bier_entry_t *be; + + be = bier_entry_get(bei); + old_pl_index = be->be_path_list; + + /* + * lock the path-list so it does not go away before we unlink + * from its resolved fmasks + */ + fib_path_list_lock(old_pl_index); + + if (FIB_NODE_INDEX_INVALID != old_pl_index) + { + fib_path_list_child_remove(old_pl_index, + be->be_sibling_index); + } + + be->be_path_list = fib_path_list_create((FIB_PATH_LIST_FLAG_SHARED | + FIB_PATH_LIST_FLAG_NO_URPF), + rpaths); + be->be_sibling_index = fib_path_list_child_add(be->be_path_list, + FIB_NODE_TYPE_BIER_ENTRY, + bier_entry_get_index(be)); + + /* + * link the entry's bit-position to each fmask in the new path-list + * then unlink from the old. + */ + fib_path_list_walk(be->be_path_list, + bier_entry_link_walk, + be); + if (FIB_NODE_INDEX_INVALID != old_pl_index) + { + fib_path_list_walk(old_pl_index, + bier_entry_unlink_walk, + be); + } + + /* + * update the ECNP tables with the new choice + */ + bier_table_ecmp_walk(be->be_bti, + bier_entry_table_ecmp_walk_add_fmask, + be); + + /* + * symmetric unlock. The old path-list may not exist hereinafter + */ + fib_path_list_unlock(old_pl_index); +} + int bier_entry_path_remove (index_t bei, const fib_route_path_t *rpaths) @@ -279,7 +341,6 @@ bier_entry_path_remove (index_t bei, } fib_path_list_unlock(old_pl_index); - /* * update the ECNP tables with the new choice */ diff --git a/src/vnet/bier/bier_entry.h b/src/vnet/bier/bier_entry.h index e514c64bb24..629e47a859a 100644 --- a/src/vnet/bier/bier_entry.h +++ b/src/vnet/bier/bier_entry.h @@ -75,6 +75,9 @@ extern index_t bier_entry_create(index_t bti, bier_bp_t bp); extern void bier_entry_delete(index_t bei); +extern void bier_entry_path_update (index_t bei, + const fib_route_path_t *rpaths); + extern void bier_entry_path_add(index_t bei, const fib_route_path_t *brp); diff --git a/src/vnet/bier/bier_fmask.c b/src/vnet/bier/bier_fmask.c index 73f719460aa..cb61681385d 100644 --- a/src/vnet/bier/bier_fmask.c +++ b/src/vnet/bier/bier_fmask.c @@ -165,14 +165,14 @@ bier_fmask_child_remove (fib_node_index_t bfmi, static void bier_fmask_init (bier_fmask_t *bfm, const bier_fmask_id_t *fmid, - const fib_route_path_t *rpaths) + const fib_route_path_t *rpath) { const bier_table_id_t *btid; + fib_route_path_t *rpaths; mpls_label_t olabel; - ASSERT(1 == vec_len(rpaths)); memset(bfm, 0, sizeof(*bfm)); - + bfm->bfm_id = clib_mem_alloc(sizeof(*bfm->bfm_id)); fib_node_init(&bfm->bfm_node, FIB_NODE_TYPE_BIER_FMASK); @@ -188,9 +188,9 @@ bier_fmask_init (bier_fmask_t *bfm, if (!(bfm->bfm_flags & BIER_FMASK_FLAG_DISP)) { - if (NULL != rpaths->frp_label_stack) + if (NULL != rpath->frp_label_stack) { - olabel = rpaths->frp_label_stack[0].fml_value; + olabel = rpath->frp_label_stack[0].fml_value; vnet_mpls_uc_set_label(&bfm->bfm_label, olabel); vnet_mpls_uc_set_exp(&bfm->bfm_label, 0); vnet_mpls_uc_set_s(&bfm->bfm_label, 1); @@ -220,13 +220,15 @@ bier_fmask_init (bier_fmask_t *bfm, bfm->bfm_label = clib_host_to_net_u32(bfm->bfm_label); } + rpaths = NULL; + vec_add1(rpaths, *rpath); bfm->bfm_pl = fib_path_list_create((FIB_PATH_LIST_FLAG_SHARED | FIB_PATH_LIST_FLAG_NO_URPF), rpaths); bfm->bfm_sibling = fib_path_list_child_add(bfm->bfm_pl, FIB_NODE_TYPE_BIER_FMASK, bier_fmask_get_index(bfm)); - + vec_free(rpaths); bier_fmask_stack(bfm); } @@ -276,7 +278,7 @@ bier_fmask_lock (index_t bfmi) index_t bier_fmask_create_and_lock (const bier_fmask_id_t *fmid, - const fib_route_path_t *rpaths) + const fib_route_path_t *rpath) { bier_fmask_t *bfm; index_t bfmi; @@ -287,7 +289,7 @@ bier_fmask_create_and_lock (const bier_fmask_id_t *fmid, vlib_validate_combined_counter (&(bier_fmask_counters), bfmi); vlib_zero_combined_counter (&(bier_fmask_counters), bfmi); - bier_fmask_init(bfm, fmid, rpaths); + bier_fmask_init(bfm, fmid, rpath); bier_fmask_lock(bfmi); diff --git a/src/vnet/bier/bier_fwd.h b/src/vnet/bier/bier_fwd.h new file mode 100644 index 00000000000..3b0b93b4baf --- /dev/null +++ b/src/vnet/bier/bier_fwd.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __BIER_FWD_H__ +#define __BIER_FWD_H__ + +#include +#include + +static_always_inline u32 +bier_compute_flow_hash (const bier_hdr_t *hdr) +{ + u32 first_word = clib_net_to_host_u32(hdr->bh_first_word); + + return ((first_word & + BIER_HDR_ENTROPY_FIELD_MASK) >> + BIER_HDR_ENTROPY_FIELD_SHIFT); +} + +#endif diff --git a/src/vnet/bier/bier_lookup.c b/src/vnet/bier/bier_lookup.c index 4e544a3aca5..d4500823f13 100644 --- a/src/vnet/bier/bier_lookup.c +++ b/src/vnet/bier/bier_lookup.c @@ -250,12 +250,12 @@ bier_lookup (vlib_main_t * vm, { bier_lookup_trace_t *tr; - vlib_trace_buffer (vm, node, next0, c0, 0); + if (c0 != b0) + vlib_buffer_copy_trace_flag (vm, b0, ci0); + tr = vlib_add_trace (vm, node, c0, sizeof (*tr)); tr->bt_index = bti0; tr->bfm_index = blm->blm_fmasks[thread_index][clone]; - - c0->flags |= VLIB_BUFFER_IS_TRACED; } vlib_validate_buffer_enqueue_x1(vm, node, next_index, diff --git a/src/vnet/bier/bier_table.c b/src/vnet/bier/bier_table.c index 80231fd8a72..3ecda105457 100644 --- a/src/vnet/bier/bier_table.c +++ b/src/vnet/bier/bier_table.c @@ -510,9 +510,10 @@ bier_table_remove (bier_table_t *bt, } void -bier_table_route_add (const bier_table_id_t *btid, - bier_bp_t bp, - fib_route_path_t *brps) +bier_table_route_path_update_i (const bier_table_id_t *btid, + bier_bp_t bp, + fib_route_path_t *brps, + u8 is_replace) { index_t bfmi, bti, bei, *bfmip, *bfmis = NULL; fib_route_path_t *brp; @@ -552,7 +553,23 @@ bier_table_route_add (const bier_table_id_t *btid, bei = bier_entry_create(bti, bp); bier_table_insert(bt, bp, bei); } - bier_entry_path_add(bei, brps); + + if (is_replace) + { + bier_entry_path_update(bei, brps); + } + else + { + fib_route_path_t *t_paths = NULL; + + vec_foreach(brp, brps) + { + vec_add1(t_paths, *brp); + bier_entry_path_add(bei, t_paths); + vec_reset_length(t_paths); + } + vec_free(t_paths); + } vec_foreach(bfmip, bfmis) { @@ -562,11 +579,51 @@ bier_table_route_add (const bier_table_id_t *btid, } void -bier_table_route_remove (const bier_table_id_t *btid, - bier_bp_t bp, - fib_route_path_t *brps) +bier_table_route_path_update (const bier_table_id_t *btid, + bier_bp_t bp, + fib_route_path_t *brps) +{ + bier_table_route_path_update_i(btid, bp, brps, 1); +} +void +bier_table_route_path_add (const bier_table_id_t *btid, + bier_bp_t bp, + fib_route_path_t *brps) +{ + bier_table_route_path_update_i(btid, bp, brps, 0); +} + +void +bier_table_route_delete (const bier_table_id_t *btid, + bier_bp_t bp) +{ + bier_table_t *bt; + index_t bei; + + bt = bier_table_find(btid); + + if (NULL == bt) { + return; + } + + bei = bier_table_lookup(bt, bp); + + if (INDEX_INVALID == bei) + { + /* no such entry */ + return; + } + + bier_table_remove(bt, bp); + bier_entry_delete(bei); +} + +void +bier_table_route_path_remove (const bier_table_id_t *btid, + bier_bp_t bp, + fib_route_path_t *brps) { - fib_route_path_t *brp = NULL; + fib_route_path_t *brp = NULL, *t_paths = NULL; index_t bfmi, bti, bei; bier_table_t *bt; u32 ii; @@ -616,12 +673,19 @@ bier_table_route_remove (const bier_table_id_t *btid, return; } - if (0 == bier_entry_path_remove(bei, brps)) + vec_foreach(brp, brps) { - /* 0 remaining paths */ - bier_table_remove(bt, bp); - bier_entry_delete(bei); + vec_add1(t_paths, *brp); + if (0 == bier_entry_path_remove(bei, t_paths)) + { + /* 0 remaining paths */ + bier_table_remove(bt, bp); + bier_entry_delete(bei); + break; + } + vec_reset_length(t_paths); } + vec_free(t_paths); } void diff --git a/src/vnet/bier/bier_table.h b/src/vnet/bier/bier_table.h index 5af275f104a..9cd9937d76c 100644 --- a/src/vnet/bier/bier_table.h +++ b/src/vnet/bier/bier_table.h @@ -93,12 +93,17 @@ extern index_t bier_table_add_or_lock(const bier_table_id_t *id, mpls_label_t ll); extern void bier_table_unlock(const bier_table_id_t *id); -extern void bier_table_route_add(const bier_table_id_t *bti, - bier_bp_t bp, - fib_route_path_t *brp); -extern void bier_table_route_remove(const bier_table_id_t *bti, - bier_bp_t bp, - fib_route_path_t *brp); +extern void bier_table_route_path_add(const bier_table_id_t *bti, + bier_bp_t bp, + fib_route_path_t *brp); +extern void bier_table_route_path_remove(const bier_table_id_t *bti, + bier_bp_t bp, + fib_route_path_t *brp); +extern void bier_table_route_path_update(const bier_table_id_t *bti, + bier_bp_t bp, + fib_route_path_t *brp); +extern void bier_table_route_delete(const bier_table_id_t *bti, + bier_bp_t b); extern void bier_table_show_all(vlib_main_t * vm, bier_show_flags_t flags); diff --git a/src/vnet/bier/bier_test.c b/src/vnet/bier/bier_test.c index d4d1692643c..06160f60aab 100644 --- a/src/vnet/bier/bier_test.c +++ b/src/vnet/bier/bier_test.c @@ -335,7 +335,7 @@ bier_test_mpls_spf (void) index_t bei_1; input_paths_1_1_1_1 = vec_dup(paths_1_1_1_1); - bier_table_route_add(&bt_0_0_0_256, 1, input_paths_1_1_1_1); + bier_table_route_path_add(&bt_0_0_0_256, 1, input_paths_1_1_1_1); bei_1 = bier_table_lookup(bier_table_get(bti), 1); BIER_TEST((INDEX_INVALID != bei_1), "BP:1 present"); @@ -492,7 +492,7 @@ bier_test_mpls_spf (void) index_t bei_2; input_paths_1_1_1_1 = vec_dup(paths_1_1_1_1); - bier_table_route_add(&bt_0_0_0_256, 2, input_paths_1_1_1_1); + bier_table_route_path_add(&bt_0_0_0_256, 2, input_paths_1_1_1_1); bei_2 = bier_table_lookup(bier_table_get(bti), 2); bier_entry_contribute_forwarding(bei_2, &dpo_bei); @@ -541,7 +541,7 @@ bier_test_mpls_spf (void) 1, out_lbl_101, FIB_ROUTE_PATH_FLAG_NONE); - bier_table_route_add(&bt_0_0_0_256, 3, input_paths_1_1_1_2); + bier_table_route_path_update(&bt_0_0_0_256, 3, input_paths_1_1_1_2); bei_3 = bier_table_lookup(bier_table_get(bti), 3); BIER_TEST((INDEX_INVALID != bei_3), "BP:3 present"); @@ -584,7 +584,7 @@ bier_test_mpls_spf (void) */ paths_1_1_1_1[0] = path_1_1_1_1; input_paths_1_1_1_1 = vec_dup(paths_1_1_1_1); - bier_table_route_add(&bt_0_0_0_256, 3, input_paths_1_1_1_1); + bier_table_route_path_add(&bt_0_0_0_256, 3, input_paths_1_1_1_1); BIER_TEST(!bier_test_validate_entry(bei_3, 2, &dpo_o_bfm_1_1_1_1, @@ -653,7 +653,7 @@ bier_test_mpls_spf (void) * remove the original 1.1.1.2 fmask from BP:3 */ input_paths_1_1_1_2 = vec_dup(paths_1_1_1_2); - bier_table_route_remove(&bt_0_0_0_256, 3, input_paths_1_1_1_2); + bier_table_route_path_remove(&bt_0_0_0_256, 3, input_paths_1_1_1_2); bier_entry_contribute_forwarding(bei_3, &dpo_bei); BIER_TEST((dpo_bei.dpoi_index == bfmi_1_1_1_1), "BP:3 stacks on fmask 1.1.1.1"); @@ -672,13 +672,13 @@ bier_test_mpls_spf (void) * remove the routes added */ input_paths_1_1_1_1 = vec_dup(paths_1_1_1_1); - bier_table_route_remove(&bt_0_0_0_256, 2, input_paths_1_1_1_1); + bier_table_route_path_remove(&bt_0_0_0_256, 2, input_paths_1_1_1_1); input_paths_1_1_1_2 = vec_dup(paths_1_1_1_2); - bier_table_route_remove(&bt_0_0_0_256, 3, input_paths_1_1_1_2); + bier_table_route_path_remove(&bt_0_0_0_256, 3, input_paths_1_1_1_2); input_paths_1_1_1_1 = vec_dup(paths_1_1_1_1); - bier_table_route_remove(&bt_0_0_0_256, 3, input_paths_1_1_1_1); - input_paths_1_1_1_1 = vec_dup(paths_1_1_1_1); - bier_table_route_remove(&bt_0_0_0_256, 1, input_paths_1_1_1_1); + bier_table_route_path_remove(&bt_0_0_0_256, 3, input_paths_1_1_1_1); + + bier_table_route_delete(&bt_0_0_0_256, 1); /* * delete the table @@ -827,7 +827,7 @@ bier_test_mpls_disp (void) }; vec_add1(paths_via_disp, path_via_disp); - bier_table_route_add(&bt_0_0_0_256, 3, paths_via_disp); + bier_table_route_path_add(&bt_0_0_0_256, 3, paths_via_disp); /* * the fmask should stack on the BIER disp table @@ -890,7 +890,7 @@ bier_test_mpls_disp (void) bier_disp_table_entry_path_remove(bier_disp_tbl_id, src, BIER_HDR_PROTO_IPV4, rpaths); - bier_table_route_remove(&bt_0_0_0_256, 3, paths_via_disp); + bier_table_route_path_remove(&bt_0_0_0_256, 3, paths_via_disp); bier_disp_table_unlock_w_table_id(bier_disp_tbl_id); diff --git a/src/vnet/bier/bier_update.c b/src/vnet/bier/bier_update.c index 326f8bf3f0b..4108d09f51e 100644 --- a/src/vnet/bier/bier_update.c +++ b/src/vnet/bier/bier_update.c @@ -115,11 +115,11 @@ vnet_bier_route_cmd (vlib_main_t * vm, if (add) { - bier_table_route_add(&bti, bp, brps); + bier_table_route_path_add(&bti, bp, brps); } else { - bier_table_route_remove(&bti, bp, brps); + bier_table_route_path_remove(&bti, bp, brps); } done: @@ -149,11 +149,11 @@ show_bier_fib_command_fn (vlib_main_t * vm, while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "%d %d", &bti, &bp)) { - flags = BIER_SHOW_DETAIL; + flags = BIER_SHOW_DETAIL; } else if (unformat (input, "%d", &bti)) { - flags = BIER_SHOW_DETAIL; + flags = BIER_SHOW_DETAIL; } else { diff --git a/src/vnet/dpo/load_balance.c b/src/vnet/dpo/load_balance.c index bb38233a55e..ae95b6e1b3e 100644 --- a/src/vnet/dpo/load_balance.c +++ b/src/vnet/dpo/load_balance.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include /* * distribution error tolerance for load-balancing @@ -999,7 +999,7 @@ load_balance_inline (vlib_main_t * vm, { /* it's BIER */ const bier_hdr_t *bh0 = vlib_buffer_get_current(b0); - vnet_buffer(b0)->ip.flow_hash = bier_hdr_get_entropy(bh0); + vnet_buffer(b0)->ip.flow_hash = bier_compute_flow_hash(bh0); } dpo0 = load_balance_get_bucket_i(lb0, diff --git a/src/vnet/mpls/mpls_lookup.h b/src/vnet/mpls/mpls_lookup.h index 4311dc053ec..95558e05a4e 100644 --- a/src/vnet/mpls/mpls_lookup.h +++ b/src/vnet/mpls/mpls_lookup.h @@ -18,6 +18,7 @@ #include #include +#include /** * The arc/edge from the MPLS lookup node to the MPLS replicate node @@ -100,6 +101,10 @@ mpls_compute_flow_hash (const mpls_unicast_header_t * hdr, hash ^= ip6_compute_flow_hash ((const ip6_header_t *)hdr, IP_FLOW_HASH_DEFAULT); break; + case 5: + /* incorporate the bier flow-hash */ + hash ^= bier_compute_flow_hash ((const bier_hdr_t *)hdr); + break; default: break; } -- cgit 1.2.3-korg