149 lines
4.9 KiB
Diff
149 lines
4.9 KiB
Diff
# UNDF: UNDF-2026-000000074
|
|
diff --git a/ospfd/ospf_ti_lfa.c b/ospfd/ospf_ti_lfa.c
|
|
index 9b8b2fd..21fb960 100644
|
|
--- a/ospfd/ospf_ti_lfa.c
|
|
+++ b/ospfd/ospf_ti_lfa.c
|
|
@@ -10,6 +10,8 @@
|
|
#include "prefix.h"
|
|
#include "table.h"
|
|
#include "printfrr.h"
|
|
+#include "hash.h"
|
|
+#include "jhash.h"
|
|
|
|
#include "ospfd/ospfd.h"
|
|
#include "ospfd/ospf_asbr.h"
|
|
@@ -31,6 +33,56 @@ ospf_ti_lfa_generate_p_space(struct ospf_area *area, struct vertex *child,
|
|
struct protected_resource *protected_resource,
|
|
bool recursive, struct list *pc_path);
|
|
|
|
+struct pc_path_entry {
|
|
+ struct vertex *vertex;
|
|
+ struct listnode *node;
|
|
+};
|
|
+
|
|
+static unsigned int pc_path_entry_hash(const void *data)
|
|
+{
|
|
+ const struct pc_path_entry *e = data;
|
|
+ return jhash_1word(e->vertex->id.s_addr, 0);
|
|
+}
|
|
+
|
|
+static bool pc_path_entry_cmp(const void *a, const void *b)
|
|
+{
|
|
+ const struct pc_path_entry *ea = a, *eb = b;
|
|
+ return ea->vertex->id.s_addr == eb->vertex->id.s_addr;
|
|
+}
|
|
+
|
|
+static void pc_path_entry_free(void *data)
|
|
+{
|
|
+ XFREE(MTYPE_OSPF_Q_SPACE, data);
|
|
+}
|
|
+
|
|
+static struct hash *ospf_ti_lfa_build_pc_path_index(struct list *pc_path)
|
|
+{
|
|
+ struct hash *idx;
|
|
+ struct listnode *ln;
|
|
+ struct vertex *v;
|
|
+ struct pc_path_entry *e;
|
|
+
|
|
+ idx = hash_create(pc_path_entry_hash, pc_path_entry_cmp, NULL);
|
|
+ for (ln = pc_path->head; ln; ln = ln->next) {
|
|
+ v = listgetdata(ln);
|
|
+ e = XCALLOC(MTYPE_OSPF_Q_SPACE, sizeof(*e));
|
|
+ e->vertex = v;
|
|
+ e->node = ln;
|
|
+ hash_get(idx, e, hash_alloc_intern);
|
|
+ }
|
|
+ return idx;
|
|
+}
|
|
+
|
|
+static struct listnode *
|
|
+ospf_ti_lfa_pc_path_lookup(struct hash *pc_path_index, struct vertex *vertex)
|
|
+{
|
|
+ struct pc_path_entry key = {.vertex = vertex};
|
|
+ struct pc_path_entry *e;
|
|
+
|
|
+ e = hash_lookup(pc_path_index, &key);
|
|
+ return e ? e->node : NULL;
|
|
+}
|
|
+
|
|
static void ospf_rt_cleanup(struct route_table *rt, struct route_node *rn)
|
|
{
|
|
if (rn->info)
|
|
@@ -69,7 +121,7 @@ ospf_ti_lfa_find_p_node(struct vertex *pc_node, struct p_space *p_space,
|
|
struct vertex *p_node = NULL, *pc_node_parent, *p_node_pc_parent;
|
|
struct vertex_parent *pc_vertex_parent;
|
|
|
|
- curr_node = listnode_lookup(q_space->pc_path, pc_node);
|
|
+ curr_node = ospf_ti_lfa_pc_path_lookup(q_space->pc_path_index, pc_node);
|
|
assert(curr_node);
|
|
pc_node_parent = listgetdata(curr_node->next);
|
|
|
|
@@ -111,7 +163,7 @@ static void ospf_ti_lfa_find_q_node(struct vertex *pc_node,
|
|
struct vertex *p_node, *q_node, *q_space_parent = NULL, *pc_node_parent;
|
|
struct vertex_parent *pc_vertex_parent;
|
|
|
|
- curr_node = listnode_lookup(q_space->pc_path, pc_node);
|
|
+ curr_node = ospf_ti_lfa_pc_path_lookup(q_space->pc_path_index, pc_node);
|
|
assert(curr_node);
|
|
next_node = curr_node->next;
|
|
pc_node_parent = listgetdata(next_node);
|
|
@@ -275,15 +327,17 @@ static void ospf_ti_lfa_generate_inner_label_stack(
|
|
start_label = MPLS_INVALID_LABEL;
|
|
end_label = MPLS_INVALID_LABEL;
|
|
if (p_node_info->node->id.s_addr == p_space->root->id.s_addr) {
|
|
- pc_p_node = listnode_lookup(q_space->pc_path, p_space->pc_spf);
|
|
+ pc_p_node = ospf_ti_lfa_pc_path_lookup(q_space->pc_path_index,
|
|
+ p_space->pc_spf);
|
|
assert(pc_p_node);
|
|
start_vertex = listgetdata(pc_p_node->prev);
|
|
start_label = ospf_sr_get_adj_sid_by_id(&p_node_info->node->id,
|
|
&start_vertex->id);
|
|
}
|
|
if (q_node_info->node->id.s_addr == q_space->root->id.s_addr) {
|
|
- pc_q_node = listnode_lookup(q_space->pc_path,
|
|
- listnode_head(q_space->pc_path));
|
|
+ pc_q_node = ospf_ti_lfa_pc_path_lookup(
|
|
+ q_space->pc_path_index,
|
|
+ listnode_head(q_space->pc_path));
|
|
assert(pc_q_node);
|
|
end_vertex = listgetdata(pc_q_node->next);
|
|
end_label = ospf_sr_get_adj_sid_by_id(&end_vertex->id,
|
|
@@ -713,6 +767,10 @@ static void ospf_ti_lfa_generate_q_spaces(struct ospf_area *area,
|
|
return;
|
|
}
|
|
|
|
+ /* Build O(1) vertex→listnode lookup index for pc_path */
|
|
+ q_space->pc_path_index =
|
|
+ ospf_ti_lfa_build_pc_path_index(q_space->pc_path);
|
|
+
|
|
/* 'Cut' the protected resource out of the new SPF tree */
|
|
ospf_spf_remove_resource(q_space->root, q_space->vertex_list,
|
|
p_space->protected_resource);
|
|
@@ -1085,6 +1143,12 @@ void ospf_ti_lfa_free_p_spaces(struct ospf_area *area)
|
|
while ((q_space = q_spaces_pop(p_space->q_spaces))) {
|
|
ospf_spf_cleanup(q_space->root, q_space->vertex_list);
|
|
|
|
+ if (q_space->pc_path_index) {
|
|
+ hash_clean(q_space->pc_path_index,
|
|
+ pc_path_entry_free);
|
|
+ hash_free(q_space->pc_path_index);
|
|
+ q_space->pc_path_index = NULL;
|
|
+ }
|
|
if (q_space->pc_path)
|
|
list_delete(&q_space->pc_path);
|
|
|
|
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
|
|
index 33f6bcf..f7d09c2 100644
|
|
--- a/ospfd/ospfd.h
|
|
+++ b/ospfd/ospfd.h
|
|
@@ -484,6 +484,10 @@ struct q_space {
|
|
struct mpls_label_stack *label_stack;
|
|
struct in_addr nexthop;
|
|
struct list *pc_path;
|
|
+ /* CWE-407 fix: O(1) index for pc_path lookup.
|
|
+ * Maps vertex id (in_addr.s_addr) to struct listnode* to replace
|
|
+ * O(n) listnode_lookup(pc_path, vertex) with O(1) hash lookup. */
|
|
+ struct hash *pc_path_index;
|
|
struct ospf_ti_lfa_node_info *p_node_info;
|
|
struct ospf_ti_lfa_node_info *q_node_info;
|
|
struct q_spaces_item q_spaces_item;
|