return (fib_entry->fe_prefix.fp_proto);
}
+static dpo_proto_t
+fib_entry_get_payload_proto (const fib_entry_t * fib_entry)
+{
+ switch (fib_entry->fe_prefix.fp_proto)
+ {
+ case FIB_PROTOCOL_IP4:
+ case FIB_PROTOCOL_IP6:
+ return fib_proto_to_dpo(fib_entry->fe_prefix.fp_proto);
+ case FIB_PROTOCOL_MPLS:
+ return fib_entry->fe_prefix.fp_payload_proto;
+ }
+
+ return (fib_proto_to_dpo(fib_entry->fe_prefix.fp_proto));
+}
+
void
fib_entry_src_register (fib_source_t source,
const fib_entry_src_vft_t *vft)
.fct = fct,
};
- lb_proto = fib_proto_to_dpo(fib_entry_get_proto(fib_entry));
+ lb_proto = fib_entry_get_payload_proto(fib_entry);
fib_path_list_walk(esrc->fes_pl,
fib_entry_src_collect_forwarding,
load_balance_multipath_update(dpo_lb,
ctx.next_hops,
fib_entry_calc_lb_flags(&ctx));
+ vec_free(ctx.next_hops);
/*
* if this entry is sourced by the uRPF-exempt source then we
*/
fib_forward_chain_type_t fct;
fib_entry_src_t *esrc;
+ int insert;
fct = fib_entry_get_default_chain_type(fib_entry);
esrc = fib_entry_src_find(fib_entry, source, NULL);
+ /*
+ * Every entry has its own load-balance object. All changes to the entry's
+ * forwarding result in an inplace modify of the load-balance. This means
+ * the load-balance object only needs to be added to the forwarding
+ * DB once, when it is created.
+ */
+ insert = !dpo_id_is_valid(&fib_entry->fe_lb[fct]);
+
fib_entry_src_mk_lb(fib_entry, esrc, fct, &fib_entry->fe_lb[fct]);
- FIB_ENTRY_DBG(fib_entry, "install: %d",
- fib_entry->fe_lb[fct]);
+ ASSERT(dpo_id_is_valid(&fib_entry->fe_lb[fct]));
+ FIB_ENTRY_DBG(fib_entry, "install: %d", fib_entry->fe_lb[fct]);
/*
* insert the adj into the data-plane forwarding trie
*/
- fib_table_fwding_dpo_update(fib_entry->fe_fib_index,
- &fib_entry->fe_prefix,
- &fib_entry->fe_lb[fct]);
+ if (insert)
+ {
+ fib_table_fwding_dpo_update(fib_entry->fe_fib_index,
+ &fib_entry->fe_prefix,
+ &fib_entry->fe_lb[fct]);
+ }
if (FIB_FORW_CHAIN_TYPE_UNICAST_IP4 == fct ||
FIB_FORW_CHAIN_TYPE_UNICAST_IP6 == fct)
return (fib_entry);
}
+/*
+ * fib_entry_src_action_update
+ *
+ * Adding a source can result in a new fib_entry being created, which
+ * can inturn mean the pool is realloc'd and thus the entry passed as
+ * an argument it also realloc'd
+ * @return the original entry
+ */
+fib_entry_t *
+fib_entry_src_action_update (fib_entry_t *fib_entry,
+ fib_source_t source,
+ fib_entry_flag_t flags,
+ const dpo_id_t *dpo)
+{
+ fib_node_index_t fib_entry_index, old_path_list_index;
+ fib_entry_src_t *esrc;
+
+ esrc = fib_entry_src_find_or_create(fib_entry, source, NULL);
+
+ if (NULL == esrc)
+ return (fib_entry_src_action_add(fib_entry, source, flags, dpo));
+
+ old_path_list_index = esrc->fes_pl;
+ esrc->fes_entry_flags = flags;
+
+ /*
+ * save variable so we can recover from a fib_entry realloc.
+ */
+ fib_entry_index = fib_entry_get_index(fib_entry);
+
+ if (NULL != fib_entry_src_vft[source].fesv_add)
+ {
+ fib_entry_src_vft[source].fesv_add(esrc,
+ fib_entry,
+ flags,
+ fib_entry_get_proto(fib_entry),
+ dpo);
+ }
+
+ fib_entry = fib_entry_get(fib_entry_index);
+
+ esrc->fes_flags |= FIB_ENTRY_SRC_FLAG_ADDED;
+
+ fib_path_list_lock(esrc->fes_pl);
+ fib_path_list_unlock(old_path_list_index);
+
+ return (fib_entry);
+}
+
+
fib_entry_src_flag_t
fib_entry_src_action_remove (fib_entry_t *fib_entry,
fib_source_t source)