]> git.puffer.fish Git - mirror/frr.git/commitdiff
ospfd: Make use of adjacency SIDs in TI-LFA
authorGalaxyGorilla <sascha@netdef.org>
Thu, 22 Oct 2020 10:05:39 +0000 (10:05 +0000)
committerGalaxyGorilla <sascha@netdef.org>
Tue, 19 Jan 2021 15:32:13 +0000 (15:32 +0000)
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>
ospfd/ospf_spf.c
ospfd/ospf_spf.h
ospfd/ospf_sr.c
ospfd/ospf_sr.h
ospfd/ospf_ti_lfa.c
tests/ospfd/common.c
tests/ospfd/common.h
tests/ospfd/topologies.c

index 3a5647ee9febdf2fd974a5b6fcc059d3f2f11aa7..735cc4027d316912e4a128949cc3a6eff617540f 100644 (file)
@@ -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)
 {
index c679e5e71da94ec3ba2fe43251085d027a6d625d..c341b3ad092bf257d401ab7ac8dfc7c9c3e1eef6 100644 (file)
@@ -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);
index f3bb4cef836fe90ed0b28e39e019a06a1ec296fe..efe07e1411d744d1fd24139efceaa2fafb60cd87 100644 (file)
@@ -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;
index 13649ad4aaa48584f4d23d74df54bd0f52a75ef8..d8079c9905bd2609ddfd617a818192b25623c5af 100644 (file)
@@ -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 */
index b0a10845c57d94059505e5538b390a55eb13fb81..3771a412dee4d0d389401510422dfec1a72ac6cb 100644 (file)
@@ -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;
 }
index 16145652bd07f156e7552ad7fbf1616268a386a3..0ecc0f854ea30bd813c73aff263328d0853fbfc4 100644 (file)
@@ -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;
index ce2bb319edcd7f4494cc1397830cffbdab500a4c..03e4a53c003240869a314bea7bb78f07627284bf 100644 (file)
@@ -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 {
index 37fd89e49e313462ca94742b928789edfd713438..cf153e675eb20bde40c1e1c71c1b7096666aab4d 100644 (file)
@@ -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,
                                                },
                                        },
                        },