diff options
Diffstat (limited to 'src/vnet/bier/bier_entry.c')
-rw-r--r-- | src/vnet/bier/bier_entry.c | 105 |
1 files changed, 83 insertions, 22 deletions
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, @@ -161,6 +140,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 */ |