#include <vnet/bier/bier_update.h>
#include <vnet/bier/bier_fmask_db.h>
#include <vnet/bier/bier_fmask.h>
+#include <vnet/bier/bier_bift_table.h>
#include <vnet/fib/mpls_fib.h>
#include <vnet/mpls/mpls.h>
num_entries,
INDEX_INVALID,
CLIB_CACHE_LINE_BYTES);
- fib_table_find_or_create_and_lock(FIB_PROTOCOL_MPLS,
- MPLS_FIB_DEFAULT_TABLE_ID,
- FIB_SOURCE_BIER);
}
else
{
}
}
+static void
+bier_table_rm_bift (bier_table_t *bt)
+{
+ ASSERT(MPLS_LABEL_INVALID == bt->bt_ll);
+
+ bier_bift_table_entry_remove(bier_bift_id_encode(bt->bt_id.bti_set,
+ bt->bt_id.bti_sub_domain,
+ bt->bt_id.bti_hdr_len));
+}
+
+static void
+bier_table_mk_bift (bier_table_t *bt)
+{
+ dpo_id_t dpo = DPO_INVALID;
+
+ ASSERT(MPLS_LABEL_INVALID == bt->bt_ll);
+
+ bier_table_contribute_forwarding(bier_table_get_index(bt), &dpo);
+
+ bier_bift_table_entry_add(bier_bift_id_encode(bt->bt_id.bti_set,
+ bt->bt_id.bti_sub_domain,
+ bt->bt_id.bti_hdr_len),
+ &dpo);
+
+ dpo_reset(&dpo);
+}
+
static void
bier_table_rm_lfib (bier_table_t *bt)
{
{
fib_table_entry_delete_index(bt->bt_lfei,
FIB_SOURCE_BIER);
+ fib_table_unlock(MPLS_FIB_DEFAULT_TABLE_ID,
+ FIB_PROTOCOL_MPLS,
+ FIB_SOURCE_BIER);
}
bt->bt_lfei = FIB_NODE_INDEX_INVALID;
}
{
index_t *bei;
+ if (MPLS_LABEL_INVALID != bt->bt_ll)
+ {
+ bier_table_rm_lfib(bt);
+ }
+ else
+ {
+ bier_table_rm_bift(bt);
+ }
+
fib_path_list_unlock(bt->bt_pl);
bt->bt_pl = FIB_NODE_INDEX_INVALID;
/*
}
}
vec_free (bt->bt_entries);
- fib_table_unlock(fib_table_find(FIB_PROTOCOL_MPLS,
- MPLS_FIB_DEFAULT_TABLE_ID),
- FIB_PROTOCOL_MPLS,
- FIB_SOURCE_BIER);
}
else
{
if (0 == bt->bt_locks)
{
- bier_table_rm_lfib(bt);
bier_table_destroy(bt);
}
}
u32 mpls_fib_index;
dpo_id_t dpo = DPO_INVALID;
+ fib_table_find_or_create_and_lock(FIB_PROTOCOL_MPLS,
+ MPLS_FIB_DEFAULT_TABLE_ID,
+ FIB_SOURCE_BIER);
+
/*
* stack the entry on the forwarding chain prodcued by the
* path-list via the ECMP tables.
*/
fib_path_list_contribute_forwarding(bt->bt_pl,
FIB_FORW_CHAIN_TYPE_BIER,
+ FIB_PATH_LIST_FWD_FLAG_COLLAPSE,
&dpo);
mpls_fib_index = fib_table_find(FIB_PROTOCOL_MPLS,
return (bt);
}
-index_t
-bier_table_add_or_lock (const bier_table_id_t *btid,
- mpls_label_t local_label)
+
+static index_t
+bier_table_create (const bier_table_id_t *btid,
+ mpls_label_t local_label)
{
+ /*
+ * add a new table
+ */
bier_table_t *bt;
index_t bti;
+ u32 key;
- bt = bier_table_find(btid);
+ key = bier_table_mk_key(btid);
+
+ pool_get_aligned(bier_table_pool, bt, CLIB_CACHE_LINE_BYTES);
+ bier_table_init(bt, btid, local_label);
+
+ hash_set(bier_tables_by_key, key, bier_table_get_index(bt));
+ bti = bier_table_get_index(bt);
+
+ if (bier_table_is_main(bt))
+ {
+ bt = bier_table_mk_ecmp(bti);
- if (NULL != bt) {
/*
- * modify an existing table.
- * change the lfib entry to the new local label
+ * add whichever mpls-fib or bift we need
*/
- if (bier_table_is_main(bt) &&
- (local_label != MPLS_LABEL_INVALID))
+ if (local_label != MPLS_LABEL_INVALID)
{
- bier_table_rm_lfib(bt);
-
bt->bt_ll = local_label;
bier_table_mk_lfib(bt);
}
- bti = bier_table_get_index(bt);
+ else
+ {
+ bier_table_mk_bift(bt);
+ }
+ }
+
+ return (bti);
+}
+
+index_t
+bier_table_lock (const bier_table_id_t *btid)
+{
+ bier_table_t *bt;
+ index_t bti;
+
+ bt = bier_table_find(btid);
+
+ if (NULL == bt)
+ {
+ bti = bier_table_create(btid, MPLS_LABEL_INVALID);
+ bt = bier_table_get(bti);
}
else
{
- /*
- * add a new table
- */
- u32 key;
+ bti = bier_table_get_index(bt);
+ }
- key = bier_table_mk_key(btid);
+ bier_table_lock_i(bt);
- pool_get_aligned(bier_table_pool, bt, CLIB_CACHE_LINE_BYTES);
- bier_table_init(bt, btid, local_label);
+ return (bti);
+}
- hash_set(bier_tables_by_key, key, bier_table_get_index(bt));
- bti = bier_table_get_index(bt);
+index_t
+bier_table_add_or_lock (const bier_table_id_t *btid,
+ mpls_label_t local_label)
+{
+ bier_table_t *bt;
+ index_t bti;
+
+ bt = bier_table_find(btid);
+ if (NULL != bt) {
+ /*
+ * modify an existing table.
+ * change the lfib entry to the new local label
+ */
if (bier_table_is_main(bt))
{
- bt = bier_table_mk_ecmp(bti);
- bier_table_mk_lfib(bt);
+ /*
+ * remove the mpls-fib or bift entry
+ */
+ if (MPLS_LABEL_INVALID != bt->bt_ll)
+ {
+ bier_table_rm_lfib(bt);
+ }
+ else
+ {
+ bier_table_rm_bift(bt);
+ }
+
+ /*
+ * reset
+ */
+ bt->bt_ll = MPLS_LABEL_INVALID;
+
+ /*
+ * add whichever mpls-fib or bift we need
+ */
+ if (local_label != MPLS_LABEL_INVALID)
+ {
+ bt->bt_ll = local_label;
+ bier_table_mk_lfib(bt);
+ }
+ else
+ {
+ bier_table_mk_bift(bt);
+ }
}
+ bti = bier_table_get_index(bt);
+ }
+ else
+ {
+ bti = bier_table_create(btid, local_label);
+ bt = bier_table_get(bti);
}
bier_table_lock_i(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;
*/
vec_foreach(brp, brps)
{
- bier_fmask_id_t fmid = {
- .bfmi_nh = brp->frp_addr,
- .bfmi_hdr_type = BIER_HDR_O_MPLS,
- };
- bfmi = bier_fmask_db_find_or_create_and_lock(bier_table_get_index(bt),
- &fmid,
- brp);
-
- brp->frp_bier_fib_index = bti;
+ /*
+ * First use the path to find or construct an FMask object
+ * via the next-hop
+ */
+ bfmi = bier_fmask_db_find_or_create_and_lock(bti, brp);
vec_add1(bfmis, bfmi);
+
+ /*
+ * then modify the path to resolve via this fmask object
+ * and use it to resolve the BIER entry.
+ */
+ brp->frp_flags = FIB_ROUTE_PATH_BIER_FMASK;
+ brp->frp_bier_fmask = bfmi;
}
if (INDEX_INVALID == bei)
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)
{
}
void
-bier_table_route_remove (const bier_table_id_t *bti,
- 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)
{
- fib_route_path_t *brp = NULL;
bier_table_t *bt;
index_t bei;
- bt = bier_table_find(bti);
+ bt = bier_table_find(btid);
if (NULL == bt) {
return;
return;
}
- vec_foreach(brp, brps)
+ 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, *t_paths = NULL;
+ index_t bfmi, bti, bei;
+ bier_table_t *bt;
+ u32 ii;
+
+ bt = bier_table_find(btid);
+
+ if (NULL == bt) {
+ return;
+ }
+
+ bti = bier_table_get_index(bt);
+ bei = bier_table_lookup(bt, bp);
+
+ if (INDEX_INVALID == bei)
{
- brp->frp_bier_fib_index = bier_table_get_index(bt);
+ /* no such entry */
+ return;
}
- if (0 == bier_entry_path_remove(bei, brps))
+ /*
+ * set the FIB index in the path to the BIER table index
+ */
+ vec_foreach_index(ii, brps)
{
- /* 0 remaining paths */
- bier_table_remove(bt, bp);
- bier_entry_delete(bei);
+ brp = &brps[ii];
+ bfmi = bier_fmask_db_find(bti, brp);
+
+ if (INDEX_INVALID == bfmi)
+ {
+ /*
+ * no matching fmask, not a path we can remove
+ */
+ vec_del1(brps, ii);
+ continue;
+ }
+
+ /*
+ * then modify the path to resolve via this fmask object
+ * and use it to resolve the BIER entry.
+ */
+ brp->frp_flags = FIB_ROUTE_PATH_BIER_FMASK;
+ brp->frp_bier_fmask = bfmi;
+ }
+
+ if (0 == vec_len(brps))
+ {
+ return;
+ }
+
+ vec_foreach(brp, brps)
+ {
+ 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
*/
fib_path_list_contribute_forwarding(bt->bt_pl,
FIB_FORW_CHAIN_TYPE_BIER,
+ FIB_PATH_LIST_FWD_FLAG_COLLAPSE,
dpo);
}
else
if (pool_is_free_index(bier_table_pool, bti))
{
- return (format(s, "No BIER f-mask %d", bti));
+ return (format(s, "No BIER table %d", bti));
}
bt = bier_table_get(bti);
- s = format(s, "[@%d] bier-table:[%U local-label:%U]",
+ s = format(s, "[@%d] bier-table:[%U local-label:%U",
bti,
format_bier_table_id, &bt->bt_id,
format_mpls_unicast_label, bt->bt_ll);