#include <vnet/dpo/drop_dpo.h>
#include "fib_entry_src.h"
+#include "fib_entry_src_rr.h"
#include "fib_entry_cover.h"
#include "fib_entry.h"
#include "fib_table.h"
*
* Resolve via a connected cover.
*/
-static void
+void
fib_entry_src_rr_resolve_via_connected (fib_entry_src_t *src,
const fib_entry_t *fib_entry,
const fib_entry_t *cover)
{
const fib_route_path_t path = {
- .frp_proto = fib_entry->fe_prefix.fp_proto,
+ .frp_proto = fib_proto_to_dpo(fib_entry->fe_prefix.fp_proto),
.frp_addr = fib_entry->fe_prefix.fp_addr,
.frp_sw_if_index = fib_entry_get_resolving_interface(
fib_entry_get_index(cover)),
* shortly to over-rule this RR source.
*/
src->fes_pl = fib_path_list_create(FIB_PATH_LIST_FLAG_NONE, paths);
- src->fes_entry_flags = fib_entry_get_flags(fib_entry_get_index(cover));
+ src->fes_entry_flags |= (fib_entry_get_flags(fib_entry_get_index(cover)) &
+ FIB_ENTRY_FLAGS_RR_INHERITED);
vec_free(paths);
}
static void
fib_entry_src_rr_init (fib_entry_src_t *src)
{
- src->rr.fesr_cover = FIB_NODE_INDEX_INVALID;
- src->rr.fesr_sibling = FIB_NODE_INDEX_INVALID;
+ src->u.rr.fesr_cover = FIB_NODE_INDEX_INVALID;
+ src->u.rr.fesr_sibling = FIB_NODE_INDEX_INVALID;
+}
+
+
+/*
+ * use the path-list of the cover, unless it would form a loop.
+ * that is unless the cover is via this entry.
+ * If a loop were to form it would be a 1 level loop (i.e. X via X),
+ * and there would be 2 locks on the path-list; one since its used
+ * by the cover, and 1 from here. The first lock will go when the
+ * cover is removed, the second, and last, when the covered walk
+ * occurs during the cover's removal - this is not a place where
+ * we can handle last lock gone.
+ * In short, don't let the loop form. The usual rules of 'we must
+ * let it form so we know when it breaks' don't apply here, since
+ * the loop will break when the cover changes, and this function
+ * will be called again when that happens.
+ */
+void
+fib_entry_src_rr_use_covers_pl (fib_entry_src_t *src,
+ const fib_entry_t *fib_entry,
+ const fib_entry_t *cover)
+{
+ fib_node_index_t *entries = NULL;
+ dpo_proto_t proto;
+
+ proto = fib_proto_to_dpo(fib_entry->fe_prefix.fp_proto);
+ vec_add1(entries, fib_entry_get_index(fib_entry));
+
+ if (fib_path_list_recursive_loop_detect(cover->fe_parent,
+ &entries))
+ {
+ src->fes_pl = fib_path_list_create_special(proto,
+ FIB_PATH_LIST_FLAG_DROP,
+ drop_dpo_get(proto));
+ }
+ else
+ {
+ src->fes_pl = cover->fe_parent;
+ }
+ vec_free(entries);
}
/*
*/
if (FIB_PROTOCOL_MPLS == fib_entry->fe_prefix.fp_proto)
{
- src->fes_pl = fib_path_list_create_special(FIB_PROTOCOL_MPLS,
+ src->fes_pl = fib_path_list_create_special(DPO_PROTO_MPLS,
FIB_PATH_LIST_FLAG_DROP,
NULL);
fib_path_list_lock(src->fes_pl);
return (!0);
}
- src->rr.fesr_cover = fib_table_get_less_specific(fib_entry->fe_fib_index,
+ src->u.rr.fesr_cover = fib_table_get_less_specific(fib_entry->fe_fib_index,
&fib_entry->fe_prefix);
- ASSERT(FIB_NODE_INDEX_INVALID != src->rr.fesr_cover);
+ ASSERT(FIB_NODE_INDEX_INVALID != src->u.rr.fesr_cover);
- cover = fib_entry_get(src->rr.fesr_cover);
+ cover = fib_entry_get(src->u.rr.fesr_cover);
- src->rr.fesr_sibling =
+ src->u.rr.fesr_sibling =
fib_entry_cover_track(cover, fib_entry_get_index(fib_entry));
/*
- * if the ocver is attached then install an attached-host path
+ * if the cover is attached then install an attached-host path
* (like an adj-fib). Otherwise inherit the forwarding from the cover
*/
if (FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags_i(cover))
}
else
{
- /*
- * use the path-list of the cover, unless it would form a loop.
- * that is unless the cover is via this entry.
- * If a loop were to form it would be a 1 level loop (i.e. X via X),
- * and there would be 2 locks on the path-list; one since its used
- * by the cover, and 1 from here. The first lock will go when the
- * cover is removed, the second, and last, when the covered walk
- * occurs during the cover's removel - this is not a place where
- * we can handle last lock gone.
- * In short, don't let the loop form. The usual rules of 'we must
- * let it form so we know when it breaks' don't apply here, since
- * the loop will break when the cover changes, and this function
- * will be called again when that happens.
- */
- fib_node_index_t *entries = NULL;
- fib_protocol_t proto;
-
- proto = fib_entry->fe_prefix.fp_proto;
- vec_add1(entries, fib_entry_get_index(fib_entry));
-
- if (fib_path_list_recursive_loop_detect(cover->fe_parent,
- &entries))
- {
- src->fes_pl = fib_path_list_create_special(
- proto,
- FIB_PATH_LIST_FLAG_DROP,
- drop_dpo_get(fib_proto_to_dpo(proto)));
- }
- else
- {
- src->fes_pl = cover->fe_parent;
- }
- vec_free(entries);
-
+ fib_entry_src_rr_use_covers_pl(src, fib_entry, cover);
}
fib_path_list_lock(src->fes_pl);
fib_entry_t *cover;
/*
- * remove the depednecy on the covering entry
+ * remove the dependency on the covering entry
*/
- if (FIB_NODE_INDEX_INVALID != src->rr.fesr_cover)
+ if (FIB_NODE_INDEX_INVALID != src->u.rr.fesr_cover)
{
- cover = fib_entry_get(src->rr.fesr_cover);
- fib_entry_cover_untrack(cover, src->rr.fesr_sibling);
- src->rr.fesr_cover = FIB_NODE_INDEX_INVALID;
+ fib_node_index_t *entries = NULL;
+
+ cover = fib_entry_get(src->u.rr.fesr_cover);
+ fib_entry_cover_untrack(cover, src->u.rr.fesr_sibling);
+ src->u.rr.fesr_cover = FIB_NODE_INDEX_INVALID;
+
+ if (FIB_NODE_INDEX_INVALID != cover->fe_parent)
+ {
+ fib_path_list_recursive_loop_detect(cover->fe_parent, &entries);
+
+ vec_free(entries);
+ }
}
fib_path_list_unlock(src->fes_pl);
src->fes_entry_flags = FIB_ENTRY_FLAG_NONE;
}
-static fib_entry_src_cover_res_t
+fib_entry_src_cover_res_t
fib_entry_src_rr_cover_change (fib_entry_src_t *src,
const fib_entry_t *fib_entry)
{
.bw_reason = FIB_NODE_BW_REASON_FLAG_NONE,
};
- if (FIB_NODE_INDEX_INVALID == src->rr.fesr_cover)
+ if (FIB_NODE_INDEX_INVALID == src->u.rr.fesr_cover)
{
/*
* the source may be added, but it is not active
* entry inserted benaeth it. That does not necessarily mean that this
* entry is covered by the new prefix. check that
*/
- if (src->rr.fesr_cover != fib_table_get_less_specific(fib_entry->fe_fib_index,
+ if (src->u.rr.fesr_cover != fib_table_get_less_specific(fib_entry->fe_fib_index,
&fib_entry->fe_prefix))
{
fib_entry_src_rr_deactivate(src, fib_entry);
* This entry's cover has updated its forwarding info. This entry
* will need to re-inheret.
*/
-static fib_entry_src_cover_res_t
+fib_entry_src_cover_res_t
fib_entry_src_rr_cover_update (fib_entry_src_t *src,
const fib_entry_t *fib_entry)
{
fib_node_index_t old_path_list;
fib_entry_t *cover;
- if (FIB_NODE_INDEX_INVALID == src->rr.fesr_cover)
+ if (FIB_NODE_INDEX_INVALID == src->u.rr.fesr_cover)
{
/*
* the source may be added, but it is not active
return (res);
}
- cover = fib_entry_get(src->rr.fesr_cover);
+ cover = fib_entry_get(src->u.rr.fesr_cover);
old_path_list = src->fes_pl;
/*
}
else
{
- src->fes_pl = cover->fe_parent;
+ fib_entry_src_rr_use_covers_pl(src, fib_entry, cover);
}
fib_path_list_lock(src->fes_pl);
fib_path_list_unlock(old_path_list);
fib_entry_src_rr_format (fib_entry_src_t *src,
u8* s)
{
- return (format(s, "cover:%d", src->rr.fesr_cover));
+ return (format(s, " cover:%d", src->u.rr.fesr_cover));
}
const static fib_entry_src_vft_t rr_src_vft = {
void
fib_entry_src_rr_register (void)
{
- fib_entry_src_register(FIB_SOURCE_RR, &rr_src_vft);
- fib_entry_src_register(FIB_SOURCE_URPF_EXEMPT, &rr_src_vft);
+ fib_entry_src_behaviour_register(FIB_SOURCE_BH_RR, &rr_src_vft);
}