switch (prefix->fp_proto)
{
case FIB_PROTOCOL_IP4:
- return (ip4_fib_table_lookup(&fib_table->v4,
+ return (ip4_fib_table_lookup(ip4_fib_get(fib_table->ft_index),
&prefix->fp_addr.ip4,
prefix->fp_len));
case FIB_PROTOCOL_IP6:
&prefix->fp_addr.ip6,
prefix->fp_len));
case FIB_PROTOCOL_MPLS:
- return (mpls_fib_table_lookup(&fib_table->mpls,
+ return (mpls_fib_table_lookup(mpls_fib_get(fib_table->ft_index),
prefix->fp_label,
prefix->fp_eos));
}
switch (prefix->fp_proto)
{
case FIB_PROTOCOL_IP4:
- return (ip4_fib_table_lookup_exact_match(&fib_table->v4,
+ return (ip4_fib_table_lookup_exact_match(ip4_fib_get(fib_table->ft_index),
&prefix->fp_addr.ip4,
prefix->fp_len));
case FIB_PROTOCOL_IP6:
&prefix->fp_addr.ip6,
prefix->fp_len));
case FIB_PROTOCOL_MPLS:
- return (mpls_fib_table_lookup(&fib_table->mpls,
+ return (mpls_fib_table_lookup(mpls_fib_get(fib_table->ft_index),
prefix->fp_label,
prefix->fp_eos));
}
switch (prefix->fp_proto)
{
case FIB_PROTOCOL_IP4:
- ip4_fib_table_entry_remove(&fib_table->v4,
+ ip4_fib_table_entry_remove(ip4_fib_get(fib_table->ft_index),
&prefix->fp_addr.ip4,
prefix->fp_len);
break;
prefix->fp_len);
break;
case FIB_PROTOCOL_MPLS:
- mpls_fib_table_entry_remove(&fib_table->mpls,
+ mpls_fib_table_entry_remove(mpls_fib_get(fib_table->ft_index),
prefix->fp_label,
prefix->fp_eos);
break;
return;
/*
- * find and inform the covering entry that a new more specific
- * has been inserted beneath it
+ * find the covering entry
*/
fib_entry_cover_index = fib_table_get_less_specific_i(fib_table, prefix);
/*
*/
if (fib_entry_cover_index != fib_entry_index)
{
- fib_entry_cover_change_notify(fib_entry_cover_index,
- fib_entry_index);
+ /*
+ * push any inherting sources from the cover onto the covered
+ */
+ fib_entry_inherit(fib_entry_cover_index,
+ fib_entry_index);
+
+ /*
+ * inform the covering entry that a new more specific
+ * has been inserted beneath it.
+ * If the prefix that has been inserted is a host route
+ * then it is not possible that it will be the cover for any
+ * other entry, so we can elide the walk. This is particularly
+ * beneficial since there are often many host entries sharing the
+ * same cover (i.e. ADJ or RR sourced entries).
+ */
+ if (!fib_entry_is_host(fib_entry_index))
+ {
+ fib_entry_cover_change_notify(fib_entry_cover_index,
+ fib_entry_index);
+ }
}
}
switch (prefix->fp_proto)
{
case FIB_PROTOCOL_IP4:
- ip4_fib_table_entry_insert(&fib_table->v4,
+ ip4_fib_table_entry_insert(ip4_fib_get(fib_table->ft_index),
&prefix->fp_addr.ip4,
prefix->fp_len,
fib_entry_index);
fib_entry_index);
break;
case FIB_PROTOCOL_MPLS:
- mpls_fib_table_entry_insert(&fib_table->mpls,
+ mpls_fib_table_entry_insert(mpls_fib_get(fib_table->ft_index),
prefix->fp_label,
prefix->fp_eos,
fib_entry_index);
return (ip4_fib_table_fwding_dpo_remove(ip4_fib_get(fib_index),
&prefix->fp_addr.ip4,
prefix->fp_len,
- dpo));
+ dpo,
+ fib_table_get_less_specific(fib_index,
+ prefix)));
case FIB_PROTOCOL_IP6:
return (ip6_fib_table_fwding_dpo_remove(fib_index,
&prefix->fp_addr.ip6,
fib_table_entry_special_add (u32 fib_index,
const fib_prefix_t *prefix,
fib_source_t source,
- fib_entry_flag_t flags,
- adj_index_t adj_index)
+ fib_entry_flag_t flags)
{
fib_node_index_t fib_entry_index;
dpo_id_t tmp_dpo = DPO_INVALID;
- if (ADJ_INDEX_INVALID != adj_index)
- {
- dpo_set(&tmp_dpo,
- DPO_ADJACENCY,
- FIB_PROTOCOL_MAX,
- adj_index);
- }
- else
- {
- dpo_copy(&tmp_dpo, drop_dpo_get(fib_proto_to_dpo(prefix->fp_proto)));
- }
+ dpo_copy(&tmp_dpo, drop_dpo_get(fib_proto_to_dpo(prefix->fp_proto)));
fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix, source,
flags, &tmp_dpo);
*/
static void
fib_table_route_path_fixup (const fib_prefix_t *prefix,
+ fib_entry_flag_t *eflags,
fib_route_path_t *path)
{
- if (fib_prefix_is_host(prefix) &&
+ /*
+ * not all zeros next hop &&
+ * is recursive path &&
+ * nexthop is same as the route's address
+ */
+ if ((!ip46_address_is_zero(&path->frp_addr)) &&
+ (~0 == path->frp_sw_if_index) &&
+ (0 == ip46_address_cmp(&path->frp_addr, &prefix->fp_addr)))
+ {
+ /* Prefix recurses via itse;f */
+ path->frp_flags |= FIB_ROUTE_PATH_DROP;
+ }
+ if (!(path->frp_flags & FIB_ROUTE_PATH_LOCAL) &&
+ fib_prefix_is_host(prefix) &&
ip46_address_is_zero(&path->frp_addr) &&
- path->frp_sw_if_index != ~0)
+ path->frp_sw_if_index != ~0 &&
+ path->frp_proto != DPO_PROTO_ETHERNET)
{
path->frp_addr = prefix->fp_addr;
+ path->frp_flags |= FIB_ROUTE_PATH_ATTACHED;
+ }
+ if (*eflags & FIB_ENTRY_FLAG_DROP)
+ {
+ path->frp_flags |= FIB_ROUTE_PATH_DROP;
+ }
+ if (*eflags & FIB_ENTRY_FLAG_LOCAL)
+ {
+ path->frp_flags |= FIB_ROUTE_PATH_LOCAL;
}
-}
+ if (*eflags & FIB_ENTRY_FLAG_EXCLUSIVE)
+ {
+ path->frp_flags |= FIB_ROUTE_PATH_EXCLUSIVE;
+ }
+ if (path->frp_flags & FIB_ROUTE_PATH_LOCAL)
+ {
+ *eflags |= FIB_ENTRY_FLAG_LOCAL;
+
+ if (path->frp_sw_if_index != ~0)
+ {
+ *eflags |= FIB_ENTRY_FLAG_CONNECTED;
+ }
+ }
+}
fib_node_index_t
fib_table_entry_path_add (u32 fib_index,
const fib_prefix_t *prefix,
fib_source_t source,
fib_entry_flag_t flags,
- fib_protocol_t next_hop_proto,
+ dpo_proto_t next_hop_proto,
const ip46_address_t *next_hop,
u32 next_hop_sw_if_index,
u32 next_hop_fib_index,
u32 next_hop_weight,
- mpls_label_t *next_hop_labels,
+ fib_mpls_label_t *next_hop_labels,
fib_route_path_flags_t path_flags)
{
fib_route_path_t path = {
.frp_fib_index = next_hop_fib_index,
.frp_weight = next_hop_weight,
.frp_flags = path_flags,
+ .frp_rpf_id = INDEX_INVALID,
.frp_label_stack = next_hop_labels,
};
fib_node_index_t fib_entry_index;
const fib_prefix_t *prefix,
fib_source_t source,
fib_entry_flag_t flags,
- fib_route_path_t *rpath)
+ fib_route_path_t *rpaths)
{
fib_node_index_t fib_entry_index;
fib_table_t *fib_table;
fib_table = fib_table_get(fib_index, prefix->fp_proto);
fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
- for (ii = 0; ii < vec_len(rpath); ii++)
+ for (ii = 0; ii < vec_len(rpaths); ii++)
{
- fib_table_route_path_fixup(prefix, &rpath[ii]);
+ fib_table_route_path_fixup(prefix, &flags, &rpaths[ii]);
}
if (FIB_NODE_INDEX_INVALID == fib_entry_index)
{
fib_entry_index = fib_entry_create(fib_index, prefix,
source, flags,
- rpath);
+ rpaths);
fib_table_entry_insert(fib_table, prefix, fib_entry_index);
fib_table->ft_src_route_counts[source]++;
int was_sourced;
was_sourced = fib_entry_is_sourced(fib_entry_index, source);
- fib_entry_path_add(fib_entry_index, source, flags, rpath);;
+ fib_entry_path_add(fib_entry_index, source, flags, rpaths);;
if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
{
fib_table_entry_path_remove2 (u32 fib_index,
const fib_prefix_t *prefix,
fib_source_t source,
- fib_route_path_t *rpath)
+ fib_route_path_t *rpaths)
{
/*
* 1 is it present
* no => cover walk
*/
fib_node_index_t fib_entry_index;
+ fib_route_path_t *rpath;
fib_table_t *fib_table;
- u32 ii;
fib_table = fib_table_get(fib_index, prefix->fp_proto);
fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
- for (ii = 0; ii < vec_len(rpath); ii++)
- {
- fib_table_route_path_fixup(prefix, &rpath[ii]);
- }
-
if (FIB_NODE_INDEX_INVALID == fib_entry_index)
{
/*
fib_entry_src_flag_t src_flag;
int was_sourced;
- /*
+ /*
+ * if it's not sourced, then there's nowt to remove
+ */
+ was_sourced = fib_entry_is_sourced(fib_entry_index, source);
+ if (!was_sourced)
+ {
+ return;
+ }
+
+ /*
* don't nobody go nowhere
*/
fib_entry_lock(fib_entry_index);
- was_sourced = fib_entry_is_sourced(fib_entry_index, source);
- src_flag = fib_entry_path_remove(fib_entry_index, source, rpath);
+ vec_foreach(rpath, rpaths)
+ {
+ fib_entry_flag_t eflags;
+
+ eflags = fib_entry_get_flags_for_source(fib_entry_index,
+ source);
+ fib_table_route_path_fixup(prefix, &eflags, rpath);
+ }
+
+ src_flag = fib_entry_path_remove(fib_entry_index, source, rpaths);
if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
{
fib_table_entry_path_remove (u32 fib_index,
const fib_prefix_t *prefix,
fib_source_t source,
- fib_protocol_t next_hop_proto,
+ dpo_proto_t next_hop_proto,
const ip46_address_t *next_hop,
u32 next_hop_sw_if_index,
u32 next_hop_fib_index,
};
fib_route_path_t *paths = NULL;
- fib_table_route_path_fixup(prefix, &path);
vec_add1(paths, path);
fib_table_entry_path_remove2(fib_index, prefix, source, paths);
for (ii = 0; ii < vec_len(paths); ii++)
{
- fib_table_route_path_fixup(prefix, &paths[ii]);
+ fib_table_route_path_fixup(prefix, &flags, &paths[ii]);
}
/*
* sort the paths provided by the control plane. this means
const fib_prefix_t *prefix,
fib_source_t source,
fib_entry_flag_t flags,
- fib_protocol_t next_hop_proto,
+ dpo_proto_t next_hop_proto,
const ip46_address_t *next_hop,
u32 next_hop_sw_if_index,
u32 next_hop_fib_index,
u32 next_hop_weight,
- mpls_label_t *next_hop_labels,
+ fib_mpls_label_t *next_hop_labels,
fib_route_path_flags_t path_flags)
{
fib_node_index_t fib_entry_index;
};
fib_route_path_t *paths = NULL;
- fib_table_route_path_fixup(prefix, &path);
vec_add1(paths, path);
fib_entry_index =
* removing an etry that does not exist.
* i'll allow it, but i won't like it.
*/
- clib_warning("%U not in FIB", format_fib_prefix, prefix);
+ if (0)
+ clib_warning("%U not in FIB", format_fib_prefix, prefix);
}
else
{
fib_table_entry_delete_index (fib_node_index_t fib_entry_index,
fib_source_t source)
{
- fib_prefix_t prefix;
+ const fib_prefix_t *prefix;
- fib_entry_get_prefix(fib_entry_index, &prefix);
+ prefix = fib_entry_get_prefix(fib_entry_index);
fib_table_entry_delete_i(fib_entry_get_fib_index(fib_entry_index),
- fib_entry_index, &prefix, source);
+ fib_entry_index, prefix, source);
+}
+
+u32
+fib_table_entry_get_stats_index (u32 fib_index,
+ const fib_prefix_t *prefix)
+{
+ return (fib_entry_get_stats_index(
+ fib_table_lookup_exact_match(fib_index, prefix)));
}
fib_node_index_t
flow_hash_config_t
fib_table_get_flow_hash_config (u32 fib_index,
fib_protocol_t proto)
+{
+ fib_table_t *fib;
+
+ fib = fib_table_get(fib_index, proto);
+
+ return (fib->ft_flow_hash_config);
+}
+
+flow_hash_config_t
+fib_table_get_default_flow_hash_config (fib_protocol_t proto)
{
switch (proto)
{
case FIB_PROTOCOL_IP4:
- return (ip4_fib_table_get_flow_hash_config(fib_index));
case FIB_PROTOCOL_IP6:
- return (ip6_fib_table_get_flow_hash_config(fib_index));
+ return (IP_FLOW_HASH_DEFAULT);
+
case FIB_PROTOCOL_MPLS:
- return (mpls_fib_table_get_flow_hash_config(fib_index));
+ return (MPLS_FLOW_HASH_DEFAULT);
}
- return (0);
+
+ ASSERT(0);
+ return (IP_FLOW_HASH_DEFAULT);
}
+/**
+ * @brief Table set flow hash config context.
+ */
+typedef struct fib_table_set_flow_hash_config_ctx_t_
+{
+ /**
+ * the flow hash config to set
+ */
+ flow_hash_config_t hash_config;
+} fib_table_set_flow_hash_config_ctx_t;
+
+static fib_table_walk_rc_t
+fib_table_set_flow_hash_config_cb (fib_node_index_t fib_entry_index,
+ void *arg)
+{
+ fib_table_set_flow_hash_config_ctx_t *ctx = arg;
+
+ fib_entry_set_flow_hash_config(fib_entry_index, ctx->hash_config);
+
+ return (FIB_TABLE_WALK_CONTINUE);
+}
+
+void
+fib_table_set_flow_hash_config (u32 fib_index,
+ fib_protocol_t proto,
+ flow_hash_config_t hash_config)
+{
+ fib_table_set_flow_hash_config_ctx_t ctx = {
+ .hash_config = hash_config,
+ };
+ fib_table_t *fib;
+
+ fib = fib_table_get(fib_index, proto);
+ fib->ft_flow_hash_config = hash_config;
+
+ fib_table_walk(fib_index, proto,
+ fib_table_set_flow_hash_config_cb,
+ &ctx);
+}
u32
fib_table_get_table_id_for_sw_if_index (fib_protocol_t proto,
return ((NULL != fib_table ? fib_table->ft_table_id : ~0));
}
+u32
+fib_table_get_table_id (u32 fib_index,
+ fib_protocol_t proto)
+{
+ fib_table_t *fib_table;
+
+ fib_table = fib_table_get(fib_index, proto);
+
+ return ((NULL != fib_table ? fib_table->ft_table_id : ~0));
+}
+
u32
fib_table_find (fib_protocol_t proto,
u32 table_id)
return (~0);
}
-u32
-fib_table_find_or_create_and_lock (fib_protocol_t proto,
- u32 table_id)
+static u32
+fib_table_find_or_create_and_lock_i (fib_protocol_t proto,
+ u32 table_id,
+ fib_source_t src,
+ const u8 *name)
{
fib_table_t *fib_table;
fib_node_index_t fi;
switch (proto)
{
case FIB_PROTOCOL_IP4:
- fi = ip4_fib_table_find_or_create_and_lock(table_id);
+ fi = ip4_fib_table_find_or_create_and_lock(table_id, src);
break;
case FIB_PROTOCOL_IP6:
- fi = ip6_fib_table_find_or_create_and_lock(table_id);
+ fi = ip6_fib_table_find_or_create_and_lock(table_id, src);
break;
case FIB_PROTOCOL_MPLS:
- fi = mpls_fib_table_find_or_create_and_lock(table_id);
+ fi = mpls_fib_table_find_or_create_and_lock(table_id, src);
break;
default:
return (~0);
fib_table = fib_table_get(fi, proto);
- fib_table->ft_desc = format(NULL, "%U-VRF:%d",
- format_fib_protocol, proto,
- table_id);
+ if (NULL == fib_table->ft_desc)
+ {
+ if (name && name[0])
+ {
+ fib_table->ft_desc = format(NULL, "%s", name);
+ }
+ else
+ {
+ fib_table->ft_desc = format(NULL, "%U-VRF:%d",
+ format_fib_protocol, proto,
+ table_id);
+ }
+ }
return (fi);
}
+u32
+fib_table_find_or_create_and_lock (fib_protocol_t proto,
+ u32 table_id,
+ fib_source_t src)
+{
+ return (fib_table_find_or_create_and_lock_i(proto, table_id,
+ src, NULL));
+}
+
+u32
+fib_table_find_or_create_and_lock_w_name (fib_protocol_t proto,
+ u32 table_id,
+ fib_source_t src,
+ const u8 *name)
+{
+ return (fib_table_find_or_create_and_lock_i(proto, table_id,
+ src, name));
+}
+
u32
fib_table_create_and_lock (fib_protocol_t proto,
+ fib_source_t src,
const char *const fmt,
...)
{
fib_node_index_t fi;
va_list ap;
- va_start(ap, fmt);
switch (proto)
{
case FIB_PROTOCOL_IP4:
- fi = ip4_fib_table_create_and_lock();
+ fi = ip4_fib_table_create_and_lock(src);
break;
case FIB_PROTOCOL_IP6:
- fi = ip6_fib_table_create_and_lock();
+ fi = ip6_fib_table_create_and_lock(src, FIB_TABLE_FLAG_NONE, NULL);
break;
case FIB_PROTOCOL_MPLS:
- fi = mpls_fib_table_create_and_lock();
+ fi = mpls_fib_table_create_and_lock(src);
break;
default:
return (~0);
fib_table = fib_table_get(fi, proto);
+ va_start(ap, fmt);
+
fib_table->ft_desc = va_format(fib_table->ft_desc, fmt, &ap);
va_end(ap);
switch (fib_table->ft_proto)
{
case FIB_PROTOCOL_IP4:
- ip4_fib_table_destroy(&fib_table->v4);
+ ip4_fib_table_destroy(fib_table->ft_index);
break;
case FIB_PROTOCOL_IP6:
ip6_fib_table_destroy(fib_table->ft_index);
break;
case FIB_PROTOCOL_MPLS:
- mpls_fib_table_destroy(&fib_table->mpls);
+ mpls_fib_table_destroy(fib_table->ft_index);
break;
}
}
}
}
+void
+fib_table_sub_tree_walk (u32 fib_index,
+ fib_protocol_t proto,
+ const fib_prefix_t *root,
+ fib_table_walk_fn_t fn,
+ void *ctx)
+{
+ switch (proto)
+ {
+ case FIB_PROTOCOL_IP4:
+ ip4_fib_table_sub_tree_walk(ip4_fib_get(fib_index), root, fn, ctx);
+ break;
+ case FIB_PROTOCOL_IP6:
+ ip6_fib_table_sub_tree_walk(fib_index, root, fn, ctx);
+ break;
+ case FIB_PROTOCOL_MPLS:
+ break;
+ }
+}
+
void
fib_table_unlock (u32 fib_index,
- fib_protocol_t proto)
+ fib_protocol_t proto,
+ fib_source_t source)
{
fib_table_t *fib_table;
fib_table = fib_table_get(fib_index, proto);
- fib_table->ft_locks--;
+ fib_table->ft_locks[source]--;
+ fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS]--;
- if (0 == fib_table->ft_locks)
+ if (0 == fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS])
{
+ /*
+ * no more locak from any source - kill it
+ */
fib_table_destroy(fib_table);
}
}
+
void
fib_table_lock (u32 fib_index,
- fib_protocol_t proto)
+ fib_protocol_t proto,
+ fib_source_t source)
{
fib_table_t *fib_table;
fib_table = fib_table_get(fib_index, proto);
- fib_table->ft_locks++;
+
+ ASSERT(fib_table->ft_locks[source] < (0xffff - 1));
+
+ fib_table->ft_locks[source]++;
+ fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS]++;
}
u32
}
u8*
-format_fib_table_name (u8* s, va_list ap)
+format_fib_table_name (u8* s, va_list* ap)
{
- fib_node_index_t fib_index = va_arg(ap, fib_node_index_t);
- fib_protocol_t proto = va_arg(ap, int); // int promotion
+ fib_node_index_t fib_index = va_arg(*ap, fib_node_index_t);
+ fib_protocol_t proto = va_arg(*ap, int); // int promotion
fib_table_t *fib_table;
fib_table = fib_table_get(fib_index, proto);
fib_source_t ftf_source;
} fib_table_flush_ctx_t;
-static int
+static fib_table_walk_rc_t
fib_table_flush_cb (fib_node_index_t fib_entry_index,
void *arg)
{
{
vec_add1(ctx->ftf_entries, fib_entry_index);
}
- return (1);
+ return (FIB_TABLE_WALK_CONTINUE);
}
vec_free(ctx.ftf_entries);
}
+
+u8 *
+format_fib_table_memory (u8 *s, va_list *args)
+{
+ s = format(s, "%U", format_ip4_fib_table_memory);
+ s = format(s, "%U", format_ip6_fib_table_memory);
+ s = format(s, "%U", format_mpls_fib_table_memory);
+
+ return (s);
+}