#include <vnet/fib/fib_internal.h>
#include <vnet/fib/fib_node_list.h>
#include <vnet/fib/fib_walk.h>
+#include <vnet/fib/fib_urpf_list.h>
/**
* FIB path-list
fib_protocol_t fpl_nh_proto;
/**
- * Vector of paths indecies for all configured paths.
+ * Vector of paths indicies for all configured paths.
* For shareable path-lists this list MUST not change.
*/
fib_node_index_t *fpl_paths;
+
+ /**
+ * the RPF list calculated for this path list
+ */
+ fib_node_index_t fpl_urpf;
} fib_path_list_t;
/*
}
}
}
+ s = format (s, " %U\n", format_fib_urpf_list, path_list->fpl_urpf);
+
vec_foreach (path_index, path_list->fpl_paths)
{
s = fib_path_format(*path_index, s);
vec_foreach (path_index, path_list->fpl_paths)
{
fib_path_destroy(*path_index);
- }
+ }
vec_free(path_list->fpl_paths);
+ fib_urpf_list_unlock(path_list->fpl_urpf);
fib_node_deinit(&path_list->fpl_node);
pool_put(fib_path_list_pool, path_list);
*/
static void
fib_path_list_mk_lb (fib_path_list_t *path_list,
- fib_forward_chain_type_t type,
+ fib_forward_chain_type_t fct,
dpo_id_t *dpo)
{
load_balance_path_t *hash_key;
hash_key = NULL;
+ if (!dpo_id_is_valid(dpo))
+ {
+ /*
+ * first time create
+ */
+ dpo_set(dpo,
+ DPO_LOAD_BALANCE,
+ fib_forw_chain_type_to_dpo_proto(fct),
+ load_balance_create(0,
+ fib_forw_chain_type_to_dpo_proto(fct),
+ 0 /* FIXME FLOW HASH */));
+ }
+
/*
* We gather the DPOs from resolved paths.
*/
{
hash_key = fib_path_append_nh_for_multipath_hash(
*path_index,
- type,
+ fct,
hash_key);
}
vec_free(hash_key);
}
+/**
+ * @brief [re]build the path list's uRPF list
+ */
+static void
+fib_path_list_mk_urpf (fib_path_list_t *path_list)
+{
+ fib_node_index_t *path_index;
+
+ /*
+ * ditch the old one. by iterating through all paths we are going
+ * to re-find all the adjs that were in the old one anyway. If we
+ * keep the old one, then the |sort|uniq requires more work.
+ * All users of the RPF list have their own lock, so we can release
+ * immediately.
+ */
+ fib_urpf_list_unlock(path_list->fpl_urpf);
+ path_list->fpl_urpf = fib_urpf_list_alloc_and_lock();
+
+ vec_foreach (path_index, path_list->fpl_paths)
+ {
+ fib_path_contribute_urpf(*path_index, path_list->fpl_urpf);
+ }
+
+ fib_urpf_list_bake(path_list->fpl_urpf);
+}
+
+/**
+ * @brief Contribute (add) this path list's uRPF list. This allows the child
+ * to construct an aggregate list.
+ */
+void
+fib_path_list_contribute_urpf (fib_node_index_t path_list_index,
+ index_t urpf)
+{
+ fib_path_list_t *path_list;
+
+ path_list = fib_path_list_get(path_list_index);
+
+ fib_urpf_list_combine(urpf, path_list->fpl_urpf);
+}
+
+/**
+ * @brief Return the the child the RPF list pre-built for this path list
+ */
+index_t
+fib_path_list_get_urpf (fib_node_index_t path_list_index)
+{
+ fib_path_list_t *path_list;
+
+ path_list = fib_path_list_get(path_list_index);
+
+ return (path_list->fpl_urpf);
+}
+
/*
* fib_path_list_back_walk
*
path_list = fib_path_list_get(path_list_index);
+ fib_path_list_mk_urpf(path_list);
+
/*
* propagate the backwalk further
*/
return (FIB_NODE_BACK_WALK_CONTINUE);
}
+/*
+ * Display the path-list memory usage
+ */
+static void
+fib_path_list_memory_show (void)
+{
+ fib_show_memory_usage("Path-list",
+ pool_elts(fib_path_list_pool),
+ pool_len(fib_path_list_pool),
+ sizeof(fib_path_list_t));
+ fib_urpf_list_show_mem();
+}
+
/*
* The FIB path-list's graph node virtual function table
*/
.fnv_get = fib_path_list_get_node,
.fnv_last_lock = fib_path_list_last_lock_gone,
.fnv_back_walk = fib_path_list_back_walk_notify,
+ .fnv_mem_show = fib_path_list_memory_show,
};
static fib_path_list_t *
fib_node_init(&path_list->fpl_node,
FIB_NODE_TYPE_PATH_LIST);
+ path_list->fpl_urpf = INDEX_INVALID;
if (NULL != path_list_index)
{
path_list = fib_path_list_get(path_list_index);
FIB_PATH_LIST_DBG(path_list, "resovled");
+ fib_path_list_mk_urpf(path_list);
return (path_list);
}
fib_path_list_flags_t flags,
const fib_route_path_t *rpaths)
{
- fib_node_index_t path_index, path_list_index, *orig_path_index;
+ fib_node_index_t path_index, new_path_index, *orig_path_index;
fib_path_list_t *path_list, *orig_path_list;
+ fib_node_index_t path_list_index;
fib_node_index_t pi;
ASSERT(1 == vec_len(rpaths));
vec_validate(path_list->fpl_paths, vec_len(orig_path_list->fpl_paths));
pi = 0;
+ new_path_index = fib_path_create(path_list_index,
+ path_list->fpl_nh_proto,
+ fib_path_list_flags_2_path_flags(flags),
+ rpaths);
+
vec_foreach (orig_path_index, orig_path_list->fpl_paths)
{
- path_index = fib_path_copy(*orig_path_index, path_list_index);
- path_list->fpl_paths[pi++] = path_index;
+ /*
+ * don't add duplicate paths
+ * In the unlikely event the path is a duplicate, then we'll
+ * find a matching path-list later and this one will be toast.
+ */
+ if (0 != fib_path_cmp(new_path_index, *orig_path_index))
+ {
+ path_index = fib_path_copy(*orig_path_index, path_list_index);
+ path_list->fpl_paths[pi++] = path_index;
+ }
+ else
+ {
+ _vec_len(path_list->fpl_paths) = vec_len(orig_path_list->fpl_paths);
+ }
}
- path_index = fib_path_create(path_list_index,
- path_list->fpl_nh_proto,
- fib_path_list_flags_2_path_flags(flags),
- rpaths);
- path_list->fpl_paths[pi] = path_index;
+
+ path_list->fpl_paths[pi] = new_path_index;
/*
* we sort the paths since the key for the path-list is
}
VLIB_CLI_COMMAND (show_fib_path_list, static) = {
- .path = "show fib path list",
+ .path = "show fib path-lists",
.function = show_fib_path_list_command,
- .short_help = "show fib path list",
+ .short_help = "show fib path-lists",
};