]> git.proxmox.com Git - mirror_frr.git/blobdiff - isisd/isis_lsp.c
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / isisd / isis_lsp.c
index fb69448d042c966635803c01c7bbe23a2be2a4ad..950d5f359c08ec60bcda27a3ad59d057a1cda5d9 100644 (file)
@@ -46,6 +46,7 @@
 #include "isisd/fabricd.h"
 #include "isisd/isis_tx_queue.h"
 #include "isisd/isis_nb.h"
+#include "isisd/isis_flex_algo.h"
 
 DEFINE_MTYPE_STATIC(ISISD, ISIS_LSP, "ISIS LSP");
 
@@ -879,6 +880,65 @@ static uint16_t lsp_refresh_time(struct isis_lsp *lsp, uint16_t rem_lifetime)
        return refresh_time;
 }
 
+static void lsp_build_internal_reach_ipv4(struct isis_lsp *lsp,
+                                         struct isis_area *area,
+                                         struct prefix_ipv4 *ipv4,
+                                         uint32_t metric)
+{
+       struct sr_prefix_cfg *pcfgs[SR_ALGORITHM_COUNT] = {NULL};
+
+       if (area->oldmetric) {
+               lsp_debug(
+                       "ISIS (%s): Adding old-style IP reachability for %pFX",
+                       area->area_tag, ipv4);
+               isis_tlvs_add_oldstyle_ip_reach(lsp->tlvs, ipv4, metric);
+       }
+
+       if (area->newmetric) {
+               lsp_debug("ISIS (%s): Adding te-style IP reachability for %pFX",
+                         area->area_tag, ipv4);
+
+               if (area->srdb.enabled)
+                       for (int i = 0; i < SR_ALGORITHM_COUNT; i++) {
+#ifndef FABRICD
+                               if (flex_algo_id_valid(i) &&
+                                   !isis_flex_algo_elected_supported(i, area))
+                                       continue;
+#endif /* ifndef FABRICD */
+                               pcfgs[i] =
+                                       isis_sr_cfg_prefix_find(area, ipv4, i);
+                       }
+
+               isis_tlvs_add_extended_ip_reach(lsp->tlvs, ipv4, metric, false,
+                                               pcfgs);
+       }
+}
+
+static void lsp_build_internal_reach_ipv6(struct isis_lsp *lsp,
+                                         struct isis_area *area,
+                                         struct prefix_ipv6 *ipv6,
+                                         uint32_t metric)
+{
+       struct sr_prefix_cfg *pcfgs[SR_ALGORITHM_COUNT] = {NULL};
+
+       lsp_debug("ISIS (%s): Adding IPv6 reachability for %pFX",
+                 area->area_tag, ipv6);
+
+       if (area->srdb.enabled)
+               for (int i = 0; i < SR_ALGORITHM_COUNT; i++) {
+#ifndef FABRICD
+                       if (flex_algo_id_valid(i) &&
+                           !isis_flex_algo_elected_supported(i, area))
+                               continue;
+#endif /* ifndef FABRICD */
+                       pcfgs[i] = isis_sr_cfg_prefix_find(area, ipv6, i);
+               }
+
+       isis_tlvs_add_ipv6_reach(lsp->tlvs, isis_area_ipv6_topology(area), ipv6,
+                                metric, false, pcfgs);
+}
+
+
 static void lsp_build_ext_reach_ipv4(struct isis_lsp *lsp,
                                     struct isis_area *area)
 {
@@ -904,13 +964,23 @@ static void lsp_build_ext_reach_ipv4(struct isis_lsp *lsp,
                        isis_tlvs_add_oldstyle_ip_reach(lsp->tlvs, ipv4,
                                                        metric);
                if (area->newmetric) {
-                       struct sr_prefix_cfg *pcfg = NULL;
+                       struct sr_prefix_cfg *pcfgs[SR_ALGORITHM_COUNT] = {
+                               NULL};
 
                        if (area->srdb.enabled)
-                               pcfg = isis_sr_cfg_prefix_find(area, ipv4);
+                               for (int i = 0; i < SR_ALGORITHM_COUNT; i++) {
+#ifndef FABRICD
+                                       if (flex_algo_id_valid(i) &&
+                                           !isis_flex_algo_elected_supported(
+                                                   i, area))
+                                               continue;
+#endif /* ifndef FABRICD */
+                                       pcfgs[i] = isis_sr_cfg_prefix_find(
+                                               area, ipv4, i);
+                               }
 
                        isis_tlvs_add_extended_ip_reach(lsp->tlvs, ipv4, metric,
-                                                       true, pcfg);
+                                                       true, pcfgs);
                }
        }
 }
@@ -938,14 +1008,24 @@ static void lsp_build_ext_reach_ipv6(struct isis_lsp *lsp,
                        metric = MAX_WIDE_PATH_METRIC;
 
                if (!src_p || !src_p->prefixlen) {
-                       struct sr_prefix_cfg *pcfg = NULL;
+                       struct sr_prefix_cfg *pcfgs[SR_ALGORITHM_COUNT] = {
+                               NULL};
 
                        if (area->srdb.enabled)
-                               pcfg = isis_sr_cfg_prefix_find(area, p);
+                               for (int i = 0; i < SR_ALGORITHM_COUNT; i++) {
+#ifndef FABRICD
+                                       if (flex_algo_id_valid(i) &&
+                                           !isis_flex_algo_elected_supported(
+                                                   i, area))
+                                               continue;
+#endif /* ifndef FABRICD */
+                                       pcfgs[i] = isis_sr_cfg_prefix_find(
+                                               area, p, i);
+                               }
 
                        isis_tlvs_add_ipv6_reach(lsp->tlvs,
                                                 isis_area_ipv6_topology(area),
-                                                p, metric, true, pcfg);
+                                                p, metric, true, pcfgs);
                } else if (isis_area_ipv6_dstsrc_enabled(area)) {
                        isis_tlvs_add_ipv6_dstsrc_reach(lsp->tlvs,
                                                        ISIS_MT_IPV6_DSTSRC,
@@ -1062,9 +1142,30 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
 
        /* Add Router Capability TLV. */
        if (area->isis->router_id != 0) {
-               struct isis_router_cap cap = {};
+               struct isis_router_cap *rcap;
+#ifndef FABRICD
+               struct isis_router_cap_fad *rcap_fad;
+               struct listnode *node;
+               struct flex_algo *fa;
+#endif /* ifndef FABRICD */
 
-               cap.router_id.s_addr = area->isis->router_id;
+               rcap = isis_tlvs_init_router_capability(lsp->tlvs);
+
+               rcap->router_id.s_addr = area->isis->router_id;
+
+#ifndef FABRICD
+               /* Set flex-algo definitions */
+               for (ALL_LIST_ELEMENTS_RO(area->flex_algos->flex_algos, node,
+                                         fa)) {
+                       if (!fa->advertise_definition)
+                               continue;
+                       lsp_debug("ISIS (%s):   Flex-Algo Definition %u",
+                                 area->area_tag, fa->algorithm);
+                       isis_tlvs_set_router_capability_fad(lsp->tlvs, fa,
+                                                           fa->algorithm,
+                                                           area->isis->sysid);
+               }
+#endif /* ifndef FABRICD */
 
                /* Add SR Sub-TLVs if SR is enabled. */
                if (area->srdb.enabled) {
@@ -1074,30 +1175,41 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
                        /* SRGB first */
                        range_size = srdb->config.srgb_upper_bound
                                     - srdb->config.srgb_lower_bound + 1;
-                       cap.srgb.flags = ISIS_SUBTLV_SRGB_FLAG_I
-                                        | ISIS_SUBTLV_SRGB_FLAG_V;
-                       cap.srgb.range_size = range_size;
-                       cap.srgb.lower_bound = srdb->config.srgb_lower_bound;
+                       rcap->srgb.flags = ISIS_SUBTLV_SRGB_FLAG_I |
+                                          ISIS_SUBTLV_SRGB_FLAG_V;
+                       rcap->srgb.range_size = range_size;
+                       rcap->srgb.lower_bound = srdb->config.srgb_lower_bound;
                        /* Then Algorithm */
-                       cap.algo[0] = SR_ALGORITHM_SPF;
-                       cap.algo[1] = SR_ALGORITHM_UNSET;
+                       rcap->algo[0] = SR_ALGORITHM_SPF;
+                       rcap->algo[1] = SR_ALGORITHM_UNSET;
+#ifndef FABRICD
+                       for (ALL_LIST_ELEMENTS_RO(area->flex_algos->flex_algos,
+                                                 node, fa)) {
+                               if (fa->advertise_definition)
+                                       rcap_fad = rcap->fads[fa->algorithm];
+                               else
+                                       rcap_fad = NULL;
+
+                               if (!isis_flex_algo_elected_supported_local_fad(
+                                           fa->algorithm, area, &rcap_fad)) {
+                                       fa->state = false;
+                                       continue;
+                               }
+                               fa->state = true;
+                               lsp_debug("ISIS (%s):   SR Algorithm %u",
+                                         area->area_tag, fa->algorithm);
+                               rcap->algo[fa->algorithm] = fa->algorithm;
+                       }
+#endif /* ifndef FABRICD */
                        /* SRLB */
-                       cap.srlb.flags = 0;
+                       rcap->srlb.flags = 0;
                        range_size = srdb->config.srlb_upper_bound
                                     - srdb->config.srlb_lower_bound + 1;
-                       cap.srlb.range_size = range_size;
-                       cap.srlb.lower_bound = srdb->config.srlb_lower_bound;
+                       rcap->srlb.range_size = range_size;
+                       rcap->srlb.lower_bound = srdb->config.srlb_lower_bound;
                        /* And finally MSD */
-                       cap.msd = srdb->config.msd;
-               } else {
-                       /* Disable SR Algorithm */
-                       cap.algo[0] = SR_ALGORITHM_UNSET;
-                       cap.algo[1] = SR_ALGORITHM_UNSET;
+                       rcap->msd = srdb->config.msd;
                }
-
-               isis_tlvs_set_router_capability(lsp->tlvs, &cap);
-               lsp_debug("ISIS (%s): Adding Router Capabilities information",
-                         area->area_tag);
        }
 
        /* IPv4 address and TE router ID TLVs.
@@ -1187,31 +1299,9 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
                        struct listnode *ipnode;
                        struct prefix_ipv4 *ipv4;
                        for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, ipnode,
-                                                 ipv4)) {
-                               if (area->oldmetric) {
-                                       lsp_debug(
-                                               "ISIS (%s): Adding old-style IP reachability for %pFX",
-                                               area->area_tag, ipv4);
-                                       isis_tlvs_add_oldstyle_ip_reach(
-                                               lsp->tlvs, ipv4, metric);
-                               }
-
-                               if (area->newmetric) {
-                                       struct sr_prefix_cfg *pcfg = NULL;
-
-                                       lsp_debug(
-                                               "ISIS (%s): Adding te-style IP reachability for %pFX",
-                                               area->area_tag, ipv4);
-
-                                       if (area->srdb.enabled)
-                                               pcfg = isis_sr_cfg_prefix_find(
-                                                       area, ipv4);
-
-                                       isis_tlvs_add_extended_ip_reach(
-                                               lsp->tlvs, ipv4, metric, false,
-                                               pcfg);
-                               }
-                       }
+                                                 ipv4))
+                               lsp_build_internal_reach_ipv4(lsp, area, ipv4,
+                                                             metric);
                }
 
                if (circuit->ipv6_router && circuit->ipv6_non_link->count > 0) {
@@ -1219,22 +1309,9 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
                        struct prefix_ipv6 *ipv6;
 
                        for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link,
-                                                 ipnode, ipv6)) {
-                               struct sr_prefix_cfg *pcfg = NULL;
-
-                               lsp_debug(
-                                       "ISIS (%s): Adding IPv6 reachability for %pFX",
-                                       area->area_tag, ipv6);
-
-                               if (area->srdb.enabled)
-                                       pcfg = isis_sr_cfg_prefix_find(area,
-                                                                      ipv6);
-
-                               isis_tlvs_add_ipv6_reach(
-                                       lsp->tlvs,
-                                       isis_area_ipv6_topology(area), ipv6,
-                                       metric, false, pcfg);
-                       }
+                                                 ipnode, ipv6))
+                               lsp_build_internal_reach_ipv6(lsp, area, ipv6,
+                                                             metric);
                }
 
                switch (circuit->circ_type) {