]> git.puffer.fish Git - mirror/frr.git/commitdiff
ospfd: Add support for reverse SPF (P2P only)
authorGalaxyGorilla <sascha@netdef.org>
Tue, 13 Oct 2020 11:53:04 +0000 (11:53 +0000)
committerGalaxyGorilla <sascha@netdef.org>
Tue, 19 Jan 2021 15:32:13 +0000 (15:32 +0000)
A reverse SPF is important in the context of TI-LFA, e.g. for
computing so called Q spaces. In case the weights of the links are
symmetric there is no difference to the 'normal' SPF and hence this
patch is really just needed for the case with asymmetric link
weights.

Signed-off-by: GalaxyGorilla <sascha@netdef.org>
ospfd/ospf_spf.c
ospfd/ospf_ti_lfa.c
ospfd/ospfd.h

index 6023b85a572a5ec031cefa75c1b749e39f62c0ce..3a5647ee9febdf2fd974a5b6fcc059d3f2f11aa7 100644 (file)
@@ -1099,6 +1099,51 @@ static int ospf_spf_is_protected_link(struct ospf_area *area,
        return 0;
 }
 
+/*
+ * For TI-LFA we need the reverse SPF for Q spaces. The reverse SPF is created
+ * by honoring the weight of the reverse 'edge', e.g. the edge from W to V, and
+ * NOT the weight of the 'edge' from V to W as usual. Hence we need to find the
+ * corresponding link in the LSA of W and extract the particular weight.
+ *
+ * TODO: Only P2P supported by now!
+ */
+static uint16_t get_reverse_distance(struct vertex *v,
+                                    struct router_lsa_link *l,
+                                    struct ospf_lsa *w_lsa)
+{
+       uint8_t *p, *lim;
+       struct router_lsa_link *w_link;
+       uint16_t distance = 0;
+
+       p = ((uint8_t *)w_lsa->data) + OSPF_LSA_HEADER_SIZE + 4;
+       lim = ((uint8_t *)w_lsa->data) + ntohs(w_lsa->data->length);
+
+       while (p < lim) {
+               w_link = (struct router_lsa_link *)p;
+               p += (OSPF_ROUTER_LSA_LINK_SIZE
+                     + (w_link->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
+
+               /* Only care about P2P with link ID equal to V's router id */
+               if (w_link->m[0].type == LSA_LINK_TYPE_POINTOPOINT
+                   && w_link->link_id.s_addr == v->id.s_addr) {
+                       distance = ntohs(w_link->m[0].metric);
+                       break;
+               }
+       }
+
+       /*
+        * This might happen if the LSA for W is not complete yet. In this
+        * case we take the weight of the 'forward' link from V. When the LSA
+        * for W is completed the reverse SPF is run again anyway.
+        */
+       if (distance == 0)
+               distance = ntohs(l->m[0].metric);
+
+       zlog_debug("%s: reversed distance is %u", __func__, distance);
+
+       return distance;
+}
+
 /*
  * RFC2328 16.1 (2).
  * v is on the SPF tree. Examine the links in v's LSA. Update the list of
@@ -1114,6 +1159,7 @@ static void ospf_spf_next(struct vertex *v, struct ospf_area *area,
        struct router_lsa_link *l = NULL;
        struct in_addr *r;
        int type = 0, lsa_pos = -1, lsa_pos_next = 0;
+       uint16_t link_distance;
 
        /*
         * If this is a router-LSA, and bit V of the router-LSA (see Section
@@ -1202,8 +1248,19 @@ static void ospf_spf_next(struct vertex *v, struct ospf_area *area,
                                continue;
                        }
 
+                       /*
+                        * For TI-LFA we might need the reverse SPF.
+                        * Currently only works with P2P!
+                        */
+                       if (type == LSA_LINK_TYPE_POINTOPOINT
+                           && area->spf_reversed)
+                               link_distance =
+                                       get_reverse_distance(v, l, w_lsa);
+                       else
+                               link_distance = ntohs(l->m[0].metric);
+
                        /* step (d) below */
-                       distance = v->distance + ntohs(l->m[0].metric);
+                       distance = v->distance + link_distance;
                } else {
                        /* In case of V is Network-LSA. */
                        r = (struct in_addr *)p;
index 61c278575c713833f55ad431bf44d3acfb286361..b0a10845c57d94059505e5538b390a55eb13fb81 100644 (file)
@@ -249,11 +249,15 @@ static void ospf_ti_lfa_generate_q_spaces(struct ospf_area *area,
        new_rtrs = route_table_init();
 
        /*
-        * Generate a new SPF tree for this vertex,
+        * Generate a new (reversed!) SPF tree for this vertex,
         * dry run true, root node false
         */
+       area->spf_reversed = true;
        ospf_spf_calculate(area, dest->lsa_p, new_table, new_rtrs, true, false);
 
+       /* Reset the flag for reverse SPF */
+       area->spf_reversed = false;
+
        q_space->root = area->spf;
        q_space->vertex_list = area->spf_vertex_list;
        q_space->label_stack = NULL;
index 420e6f22eb2977dc4ab305d8eb21aec46a0323a9..ad8f561610fe57504cc809eccd95f6aa43b523c7 100644 (file)
@@ -525,6 +525,9 @@ struct ospf_area {
        /* Statistics field. */
        uint32_t spf_calculation; /* SPF Calculation Count. */
 
+       /* reverse SPF (used for TI-LFA Q spaces) */
+       bool spf_reversed;
+
        /* Time stamps. */
        struct timeval ts_spf; /* SPF calculation time stamp. */