mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-06 18:04:03 +00:00
ospfd: Make use of adjacency SIDs in TI-LFA
When P and Q spaces are adjacent then it makes sense to use adjacency SIDs to from the P node to the Q node. There are some other corner cases where this makes also sense like when a P/Q node adjacent to root node. Signed-off-by: GalaxyGorilla <sascha@netdef.org>
This commit is contained in:
parent
133e59cfad
commit
cc1725bd34
@ -305,6 +305,21 @@ struct vertex *ospf_spf_vertex_find(struct in_addr id, struct list *vertex_list)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Find a vertex parent according to its router id */
|
||||
struct vertex_parent *ospf_spf_vertex_parent_find(struct in_addr id,
|
||||
struct vertex *vertex)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct vertex_parent *found;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(vertex->parents, node, found)) {
|
||||
if (found->parent->id.s_addr == id.s_addr)
|
||||
return found;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create a deep copy of a SPF vertex without children and parents */
|
||||
static struct vertex *ospf_spf_vertex_copy(struct vertex *vertex)
|
||||
{
|
||||
|
@ -90,6 +90,8 @@ extern int ospf_spf_remove_link(struct vertex *vertex, struct list *vertex_list,
|
||||
struct router_lsa_link *link);
|
||||
extern struct vertex *ospf_spf_vertex_find(struct in_addr id,
|
||||
struct list *vertex_list);
|
||||
extern struct vertex_parent *ospf_spf_vertex_parent_find(struct in_addr id,
|
||||
struct vertex *vertex);
|
||||
extern int vertex_parent_cmp(void *aa, void *bb);
|
||||
|
||||
extern void ospf_spf_print(struct vty *vty, struct vertex *v, int i);
|
||||
|
@ -687,6 +687,32 @@ mpls_label_t ospf_sr_get_prefix_sid_by_id(struct in_addr *id)
|
||||
return label;
|
||||
}
|
||||
|
||||
/* Get the adjacency sid for a specific 'root' id and 'neighbor' id */
|
||||
mpls_label_t ospf_sr_get_adj_sid_by_id(struct in_addr *root_id,
|
||||
struct in_addr *neighbor_id)
|
||||
{
|
||||
struct sr_node *srn;
|
||||
struct sr_link *srl;
|
||||
mpls_label_t label;
|
||||
struct listnode *node;
|
||||
|
||||
srn = (struct sr_node *)hash_lookup(OspfSR.neighbors, root_id);
|
||||
|
||||
label = MPLS_INVALID_LABEL;
|
||||
|
||||
if (srn) {
|
||||
for (ALL_LIST_ELEMENTS_RO(srn->ext_link, node, srl)) {
|
||||
if (srl->type == ADJ_SID
|
||||
&& srl->remote_id.s_addr == neighbor_id->s_addr) {
|
||||
label = srl->sid[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
/* Get neighbor full structure from address */
|
||||
static struct ospf_neighbor *get_neighbor_by_addr(struct ospf *top,
|
||||
struct in_addr addr)
|
||||
@ -1596,6 +1622,7 @@ void ospf_sr_ext_itf_add(struct ext_itf *exti)
|
||||
srl->itf_addr = exti->link.link_data;
|
||||
srl->instance =
|
||||
SET_OPAQUE_LSID(OPAQUE_TYPE_EXTENDED_LINK_LSA, exti->instance);
|
||||
srl->remote_id = exti->link.link_id;
|
||||
switch (exti->stype) {
|
||||
case ADJ_SID:
|
||||
srl->type = ADJ_SID;
|
||||
|
@ -290,6 +290,9 @@ struct sr_link {
|
||||
/* 24-bit Opaque-ID field value according to RFC 7684 specification */
|
||||
uint32_t instance;
|
||||
|
||||
/* Addressed (remote) router id */
|
||||
struct in_addr remote_id;
|
||||
|
||||
/* Interface address */
|
||||
struct in_addr itf_addr;
|
||||
|
||||
@ -364,6 +367,8 @@ extern void ospf_sr_update_task(struct ospf *ospf);
|
||||
|
||||
/* Support for TI-LFA */
|
||||
extern mpls_label_t ospf_sr_get_prefix_sid_by_id(struct in_addr *id);
|
||||
extern mpls_label_t ospf_sr_get_adj_sid_by_id(struct in_addr *root_id,
|
||||
struct in_addr *neighbor_id);
|
||||
extern struct sr_node *ospf_sr_node_create(struct in_addr *rid);
|
||||
|
||||
#endif /* _FRR_OSPF_SR_H */
|
||||
|
@ -178,6 +178,7 @@ static void ospf_ti_lfa_generate_label_stack(struct p_space *p_space,
|
||||
|
||||
pc_node = ospf_spf_vertex_find(q_space->root->id,
|
||||
p_space->pc_vertex_list);
|
||||
|
||||
if (!pc_node) {
|
||||
zlog_debug(
|
||||
"%s: There seems to be no post convergence path (yet).",
|
||||
@ -193,10 +194,22 @@ static void ospf_ti_lfa_generate_label_stack(struct p_space *p_space,
|
||||
|
||||
/* Found a PQ node? Then we are done here. */
|
||||
if (q_node_info.type == OSPF_TI_LFA_PQ_NODE) {
|
||||
labels[0] = ospf_sr_get_prefix_sid_by_id(&q_node_info.node->id);
|
||||
/*
|
||||
* If the PQ node is a child of the root, then we can use an
|
||||
* adjacency SID instead of a prefix SID for the backup path.
|
||||
*/
|
||||
if (ospf_spf_vertex_parent_find(p_space->root->id,
|
||||
q_node_info.node))
|
||||
labels[0] = ospf_sr_get_adj_sid_by_id(
|
||||
&p_space->root->id, &q_node_info.node->id);
|
||||
else
|
||||
labels[0] = ospf_sr_get_prefix_sid_by_id(
|
||||
&q_node_info.node->id);
|
||||
|
||||
q_space->label_stack =
|
||||
ospf_ti_lfa_create_label_stack(labels, 1);
|
||||
q_space->nexthop = q_node_info.nexthop;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -211,19 +224,33 @@ static void ospf_ti_lfa_generate_label_stack(struct p_space *p_space,
|
||||
|
||||
/*
|
||||
* It can happen that the P node is the root itself, therefore we don't
|
||||
* need a label for it.
|
||||
* need a label for it. So just one adjacency SID for the Q node.
|
||||
*/
|
||||
if (p_node_info.node->id.s_addr == p_space->root->id.s_addr) {
|
||||
labels[0] = ospf_sr_get_prefix_sid_by_id(&q_node_info.node->id);
|
||||
labels[0] = ospf_sr_get_adj_sid_by_id(&p_space->root->id,
|
||||
&q_node_info.node->id);
|
||||
q_space->label_stack =
|
||||
ospf_ti_lfa_create_label_stack(labels, 1);
|
||||
q_space->nexthop = q_node_info.nexthop;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise we have a P and also a Q node which we need labels for. */
|
||||
labels[0] = ospf_sr_get_prefix_sid_by_id(&p_node_info.node->id);
|
||||
labels[1] = ospf_sr_get_prefix_sid_by_id(&q_node_info.node->id);
|
||||
/*
|
||||
* Otherwise we have a P and also a Q node (which are adjacent).
|
||||
*
|
||||
* It can happen that the P node is a child of the root, therefore we
|
||||
* might just need the adjacency SID for the P node instead of the
|
||||
* prefix SID. For the Q node always take the adjacency SID.
|
||||
*/
|
||||
if (ospf_spf_vertex_parent_find(p_space->root->id, p_node_info.node))
|
||||
labels[0] = ospf_sr_get_adj_sid_by_id(&p_space->root->id,
|
||||
&p_node_info.node->id);
|
||||
else
|
||||
labels[0] = ospf_sr_get_prefix_sid_by_id(&p_node_info.node->id);
|
||||
|
||||
labels[1] = ospf_sr_get_adj_sid_by_id(&p_node_info.node->id,
|
||||
&q_node_info.node->id);
|
||||
|
||||
q_space->label_stack = ospf_ti_lfa_create_label_stack(labels, 2);
|
||||
q_space->nexthop = p_node_info.nexthop;
|
||||
}
|
||||
|
@ -124,11 +124,17 @@ static void inject_router_lsa(struct vty *vty, struct ospf *ospf,
|
||||
}
|
||||
}
|
||||
|
||||
static void inject_sr_db_entry(struct vty *vty, struct ospf_test_node *tnode)
|
||||
static void inject_sr_db_entry(struct vty *vty, struct ospf_test_node *tnode,
|
||||
struct ospf_topology *topology)
|
||||
{
|
||||
struct ospf_test_node *tfound_adj_node;
|
||||
struct ospf_test_adj *tadj;
|
||||
struct in_addr router_id;
|
||||
struct in_addr remote_id;
|
||||
struct sr_node *srn;
|
||||
struct sr_prefix *srp;
|
||||
struct sr_link *srl;
|
||||
int link_count;
|
||||
|
||||
inet_aton(tnode->router_id, &router_id);
|
||||
|
||||
@ -138,13 +144,35 @@ static void inject_sr_db_entry(struct vty *vty, struct ospf_test_node *tnode)
|
||||
srn->srgb.lower_bound = 16000;
|
||||
srn->msd = 16;
|
||||
|
||||
srp = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_prefix));
|
||||
srn->srlb.range_size = 1000;
|
||||
srn->srlb.lower_bound = 15000;
|
||||
|
||||
/* Prefix SID */
|
||||
srp = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_prefix));
|
||||
srp->adv_router = router_id;
|
||||
srp->sid = tnode->label;
|
||||
srp->srn = srn;
|
||||
|
||||
listnode_add(srn->ext_prefix, srp);
|
||||
|
||||
/* Adjacency SIDs for all adjacencies */
|
||||
for (link_count = 0; tnode->adjacencies[link_count].hostname[0];
|
||||
link_count++) {
|
||||
tadj = &tnode->adjacencies[link_count];
|
||||
tfound_adj_node = test_find_node(topology, tadj->hostname);
|
||||
|
||||
srl = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_link));
|
||||
srl->adv_router = router_id;
|
||||
|
||||
inet_aton(tfound_adj_node->router_id, &remote_id);
|
||||
srl->remote_id = remote_id;
|
||||
|
||||
srl->type = ADJ_SID;
|
||||
srl->sid[0] = srn->srlb.lower_bound + tadj->label;
|
||||
srl->srn = srn;
|
||||
|
||||
listnode_add(srn->ext_link, srl);
|
||||
}
|
||||
}
|
||||
|
||||
int topology_load(struct vty *vty, struct ospf_topology *topology,
|
||||
@ -162,7 +190,7 @@ int topology_load(struct vty *vty, struct ospf_topology *topology,
|
||||
* SR information could also be inected via LSAs, but directly
|
||||
* filling the SR DB with labels is just easier.
|
||||
*/
|
||||
inject_sr_db_entry(vty, tnode);
|
||||
inject_sr_db_entry(vty, tnode, topology);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -8,6 +8,7 @@ struct ospf_test_adj {
|
||||
char hostname[256];
|
||||
char network[256];
|
||||
uint32_t metric;
|
||||
mpls_label_t label;
|
||||
};
|
||||
|
||||
struct ospf_test_node {
|
||||
|
@ -43,12 +43,14 @@ struct ospf_topology topo1 = {
|
||||
.network =
|
||||
"10.0.1.1/24",
|
||||
.metric = 10,
|
||||
.label = 1,
|
||||
},
|
||||
{
|
||||
.hostname = "rt3",
|
||||
.network =
|
||||
"10.0.3.1/24",
|
||||
.metric = 10,
|
||||
.label = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -63,12 +65,14 @@ struct ospf_topology topo1 = {
|
||||
.network =
|
||||
"10.0.1.2/24",
|
||||
.metric = 10,
|
||||
.label = 3,
|
||||
},
|
||||
{
|
||||
.hostname = "rt3",
|
||||
.network =
|
||||
"10.0.2.1/24",
|
||||
.metric = 10,
|
||||
.label = 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -83,12 +87,14 @@ struct ospf_topology topo1 = {
|
||||
.network =
|
||||
"10.0.3.2/24",
|
||||
.metric = 10,
|
||||
.label = 5,
|
||||
},
|
||||
{
|
||||
.hostname = "rt2",
|
||||
.network =
|
||||
"10.0.2.2/24",
|
||||
.metric = 10,
|
||||
.label = 6,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -134,12 +140,14 @@ struct ospf_topology topo2 = {
|
||||
.network =
|
||||
"10.0.1.1/24",
|
||||
.metric = 10,
|
||||
.label = 1,
|
||||
},
|
||||
{
|
||||
.hostname = "rt3",
|
||||
.network =
|
||||
"10.0.3.1/24",
|
||||
.metric = 30,
|
||||
.label = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -154,12 +162,14 @@ struct ospf_topology topo2 = {
|
||||
.network =
|
||||
"10.0.1.2/24",
|
||||
.metric = 10,
|
||||
.label = 3,
|
||||
},
|
||||
{
|
||||
.hostname = "rt3",
|
||||
.network =
|
||||
"10.0.2.1/24",
|
||||
.metric = 10,
|
||||
.label = 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -174,12 +184,14 @@ struct ospf_topology topo2 = {
|
||||
.network =
|
||||
"10.0.3.2/24",
|
||||
.metric = 30,
|
||||
.label = 5,
|
||||
},
|
||||
{
|
||||
.hostname = "rt2",
|
||||
.network =
|
||||
"10.0.2.2/24",
|
||||
.metric = 10,
|
||||
.label = 6,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -207,7 +219,7 @@ struct ospf_topology topo2 = {
|
||||
*
|
||||
* Regarding the protected subnet 10.0.4.0/24, the P and Q spaces for root RT1
|
||||
* and destination RT4 are disjunct and the P node is RT2 while RT3 is the Q
|
||||
* node. Hence the backup label stack here is 16020/16030. Note that here the
|
||||
* node. Hence the backup label stack here is 16020/15004. Note that here the
|
||||
* P and Q nodes are neither the root nor the destination nodes, so this is a
|
||||
* case where you really need a label stack consisting of two labels.
|
||||
*/
|
||||
@ -225,12 +237,14 @@ struct ospf_topology topo3 = {
|
||||
.network =
|
||||
"10.0.1.1/24",
|
||||
.metric = 10,
|
||||
.label = 1,
|
||||
},
|
||||
{
|
||||
.hostname = "rt4",
|
||||
.network =
|
||||
"10.0.4.1/24",
|
||||
.metric = 10,
|
||||
.label = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -245,12 +259,14 @@ struct ospf_topology topo3 = {
|
||||
.network =
|
||||
"10.0.1.2/24",
|
||||
.metric = 10,
|
||||
.label = 3,
|
||||
},
|
||||
{
|
||||
.hostname = "rt3",
|
||||
.network =
|
||||
"10.0.2.1/24",
|
||||
.metric = 20,
|
||||
.label = 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -265,12 +281,14 @@ struct ospf_topology topo3 = {
|
||||
.network =
|
||||
"10.0.2.2/24",
|
||||
.metric = 20,
|
||||
.label = 5,
|
||||
},
|
||||
{
|
||||
.hostname = "rt4",
|
||||
.network =
|
||||
"10.0.3.1/24",
|
||||
.metric = 10,
|
||||
.label = 6,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -285,12 +303,14 @@ struct ospf_topology topo3 = {
|
||||
.network =
|
||||
"10.0.4.2/24",
|
||||
.metric = 10,
|
||||
.label = 7,
|
||||
},
|
||||
{
|
||||
.hostname = "rt3",
|
||||
.network =
|
||||
"10.0.3.2/24",
|
||||
.metric = 10,
|
||||
.label = 8,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user