java-topology/defects/frrouting/patch/frrouting-0001-pc-path-index.patch

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;