]> git.proxmox.com Git - mirror_frr.git/blobdiff - isisd/isis_te.c
Merge pull request #12933 from Orange-OpenSource/link_state
[mirror_frr.git] / isisd / isis_te.c
index 71f18256290d5e196fb7b0eff0875b9fe1a6bc76..90b53c540ef58281c82a69b99772984854b28c08 100644 (file)
@@ -164,6 +164,154 @@ void isis_mpls_te_term(struct isis_area *area)
        XFREE(MTYPE_ISIS_MPLS_TE, area->mta);
 }
 
+static void isis_link_params_update_asla(struct isis_circuit *circuit,
+                                        struct interface *ifp)
+{
+       struct isis_asla_subtlvs *asla;
+       struct listnode *node, *nnode;
+       struct isis_ext_subtlvs *ext = circuit->ext;
+       int i;
+
+       if (!HAS_LINK_PARAMS(ifp)) {
+               list_delete_all_node(ext->aslas);
+               return;
+       }
+
+#ifndef FABRICD
+       /* RFC 8919 Application Specific Link-Attributes
+        * is required by flex-algo application ISIS_SABM_FLAG_X
+        */
+       if (list_isempty(circuit->area->flex_algos->flex_algos))
+               isis_tlvs_free_asla(ext, ISIS_SABM_FLAG_X);
+       else
+               isis_tlvs_find_alloc_asla(ext, ISIS_SABM_FLAG_X);
+#endif /* ifndef FABRICD */
+
+       if (list_isempty(ext->aslas))
+               return;
+
+       for (ALL_LIST_ELEMENTS(ext->aslas, node, nnode, asla)) {
+               asla->legacy = circuit->area->asla_legacy_flag;
+               RESET_SUBTLV(asla);
+
+               if (asla->legacy)
+                       continue;
+
+               /* Fulfill ASLA subTLVs from interface link parameters */
+               if (IS_PARAM_SET(ifp->link_params, LP_ADM_GRP)) {
+                       asla->admin_group = ifp->link_params->admin_grp;
+                       SET_SUBTLV(asla, EXT_ADM_GRP);
+               } else
+                       UNSET_SUBTLV(asla, EXT_ADM_GRP);
+
+               if (IS_PARAM_SET(ifp->link_params, LP_EXTEND_ADM_GRP)) {
+                       admin_group_copy(&asla->ext_admin_group,
+                                        &ifp->link_params->ext_admin_grp);
+                       SET_SUBTLV(asla, EXT_EXTEND_ADM_GRP);
+               } else
+                       UNSET_SUBTLV(asla, EXT_EXTEND_ADM_GRP);
+
+               /* Send admin-group zero for better compatibility
+                * https://www.rfc-editor.org/rfc/rfc7308#section-2.3.2
+                */
+               if (circuit->area->admin_group_send_zero &&
+                   !IS_SUBTLV(asla, EXT_ADM_GRP) &&
+                   !IS_SUBTLV(asla, EXT_EXTEND_ADM_GRP)) {
+                       asla->admin_group = 0;
+                       SET_SUBTLV(asla, EXT_ADM_GRP);
+                       admin_group_clear(&asla->ext_admin_group);
+                       admin_group_allow_explicit_zero(&asla->ext_admin_group);
+                       SET_SUBTLV(asla, EXT_EXTEND_ADM_GRP);
+               }
+
+               if (IS_PARAM_SET(ifp->link_params, LP_TE_METRIC)) {
+                       asla->te_metric = ifp->link_params->te_metric;
+                       SET_SUBTLV(asla, EXT_TE_METRIC);
+               } else
+                       UNSET_SUBTLV(asla, EXT_TE_METRIC);
+
+               if (IS_PARAM_SET(ifp->link_params, LP_DELAY)) {
+                       asla->delay = ifp->link_params->av_delay;
+                       SET_SUBTLV(asla, EXT_DELAY);
+               } else
+                       UNSET_SUBTLV(asla, EXT_DELAY);
+
+               if (IS_PARAM_SET(ifp->link_params, LP_MM_DELAY)) {
+                       asla->min_delay = ifp->link_params->min_delay;
+                       asla->max_delay = ifp->link_params->max_delay;
+                       SET_SUBTLV(asla, EXT_MM_DELAY);
+               } else {
+                       UNSET_SUBTLV(asla, EXT_MM_DELAY);
+               }
+
+               if (asla->standard_apps == ISIS_SABM_FLAG_X)
+                       /* Flex-Algo ASLA does not need the following TE
+                        * sub-TLVs
+                        */
+                       continue;
+
+               if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW)) {
+                       asla->max_bw = ifp->link_params->max_bw;
+                       SET_SUBTLV(asla, EXT_MAX_BW);
+               } else
+                       UNSET_SUBTLV(asla, EXT_MAX_BW);
+
+               if (IS_PARAM_SET(ifp->link_params, LP_MAX_RSV_BW)) {
+                       asla->max_rsv_bw = ifp->link_params->max_rsv_bw;
+                       SET_SUBTLV(asla, EXT_MAX_RSV_BW);
+               } else
+                       UNSET_SUBTLV(asla, EXT_MAX_RSV_BW);
+
+               if (IS_PARAM_SET(ifp->link_params, LP_UNRSV_BW)) {
+                       for (i = 0; i < MAX_CLASS_TYPE; i++)
+                               asla->unrsv_bw[i] =
+                                       ifp->link_params->unrsv_bw[i];
+                       SET_SUBTLV(asla, EXT_UNRSV_BW);
+               } else
+                       UNSET_SUBTLV(asla, EXT_UNRSV_BW);
+
+               if (IS_PARAM_SET(ifp->link_params, LP_DELAY_VAR)) {
+                       asla->delay_var = ifp->link_params->delay_var;
+                       SET_SUBTLV(asla, EXT_DELAY_VAR);
+               } else
+                       UNSET_SUBTLV(asla, EXT_DELAY_VAR);
+
+               if (IS_PARAM_SET(ifp->link_params, LP_PKT_LOSS)) {
+                       asla->pkt_loss = ifp->link_params->pkt_loss;
+                       SET_SUBTLV(asla, EXT_PKT_LOSS);
+               } else
+                       UNSET_SUBTLV(asla, EXT_PKT_LOSS);
+
+               if (IS_PARAM_SET(ifp->link_params, LP_RES_BW)) {
+                       asla->res_bw = ifp->link_params->res_bw;
+                       SET_SUBTLV(asla, EXT_RES_BW);
+               } else
+                       UNSET_SUBTLV(asla, EXT_RES_BW);
+
+               if (IS_PARAM_SET(ifp->link_params, LP_AVA_BW)) {
+                       asla->ava_bw = ifp->link_params->ava_bw;
+                       SET_SUBTLV(asla, EXT_AVA_BW);
+               } else
+                       UNSET_SUBTLV(asla, EXT_AVA_BW);
+
+               if (IS_PARAM_SET(ifp->link_params, LP_USE_BW)) {
+                       asla->use_bw = ifp->link_params->use_bw;
+                       SET_SUBTLV(asla, EXT_USE_BW);
+               } else
+                       UNSET_SUBTLV(asla, EXT_USE_BW);
+       }
+
+
+       for (ALL_LIST_ELEMENTS(ext->aslas, node, nnode, asla)) {
+               if (!asla->legacy && NO_SUBTLV(asla) &&
+                   admin_group_nb_words(&asla->ext_admin_group) == 0)
+                       /* remove ASLA without info from the list of ASLAs to
+                        * not send void ASLA
+                        */
+                       isis_tlvs_del_asla_flex_algo(ext, asla);
+       }
+}
+
 /* Main initialization / update function of the MPLS TE Circuit context */
 /* Call when interface TE Link parameters are modified */
 void isis_link_params_update(struct isis_circuit *circuit,
@@ -210,6 +358,19 @@ void isis_link_params_update(struct isis_circuit *circuit,
                } else
                        UNSET_SUBTLV(ext, EXT_EXTEND_ADM_GRP);
 
+               /* Send admin-group zero for better compatibility
+                * https://www.rfc-editor.org/rfc/rfc7308#section-2.3.2
+                */
+               if (circuit->area->admin_group_send_zero &&
+                   !IS_SUBTLV(ext, EXT_ADM_GRP) &&
+                   !IS_SUBTLV(ext, EXT_EXTEND_ADM_GRP)) {
+                       ext->adm_group = 0;
+                       SET_SUBTLV(ext, EXT_ADM_GRP);
+                       admin_group_clear(&ext->ext_admin_group);
+                       admin_group_allow_explicit_zero(&ext->ext_admin_group);
+                       SET_SUBTLV(ext, EXT_EXTEND_ADM_GRP);
+               }
+
                /* If known, register local IPv4 addr from ip_addr list */
                if (listcount(circuit->ip_addrs) != 0) {
                        addr = (struct prefix_ipv4 *)listgetdata(
@@ -331,6 +492,8 @@ void isis_link_params_update(struct isis_circuit *circuit,
                        ext->status = 0;
        }
 
+       isis_link_params_update_asla(circuit, ifp);
+
        return;
 }
 
@@ -503,7 +666,12 @@ int isis_mpls_te_update(struct interface *ifp)
        isis_link_params_update(circuit, ifp);
 
        /* ... and LSP */
-       if (circuit->area && IS_MPLS_TE(circuit->area->mta))
+       if (circuit->area &&
+           (IS_MPLS_TE(circuit->area->mta)
+#ifndef FABRICD
+            || !list_isempty(circuit->area->flex_algos->flex_algos)
+#endif /* ifndef FABRICD */
+                    ))
                lsp_regenerate_schedule(circuit->area, circuit->is_type, 0);
 
        rc = 0;
@@ -611,7 +779,7 @@ static struct ls_vertex *lsp_to_vertex(struct ls_ted *ted, struct isis_lsp *lsp)
                                lnode.srgb.flag = cap->srgb.flags;
                                lnode.srgb.lower_bound = cap->srgb.lower_bound;
                                lnode.srgb.range_size = cap->srgb.range_size;
-                               for (int i = 0; i < SR_ALGORITHM_COUNT; i++)
+                               for (int i = 0; i < LIB_LS_SR_ALGO_COUNT; i++)
                                        lnode.algo[i] = cap->algo[i];
                        }
 
@@ -905,7 +1073,7 @@ static int lsp_to_edge_cb(const uint8_t *id, uint32_t metric, bool old_metric,
        struct ls_edge *edge, *dst;
        struct ls_attributes *attr;
 
-       te_debug("  |- Process Extended IS for %s", sysid_print(id));
+       te_debug("  |- Process Extended IS for %pSY", id);
 
        /* Check parameters */
        if (old_metric || !args || !tlvs)
@@ -1092,7 +1260,7 @@ static int lsp_to_subnet_cb(const struct prefix *prefix, uint32_t metric,
                prefix_copy(&p, prefix);
        else {
                /* Remove old subnet if any before prefix adjustment */
-               subnet = ls_find_subnet(args->ted, *prefix);
+               subnet = ls_find_subnet(args->ted, prefix);
                if (subnet) {
                        if (args->export) {
                                subnet->status = DELETE;
@@ -1107,10 +1275,10 @@ static int lsp_to_subnet_cb(const struct prefix *prefix, uint32_t metric,
        }
 
        /* Search existing Subnet in TED ... */
-       subnet = ls_find_subnet(args->ted, p);
+       subnet = ls_find_subnet(args->ted, &p);
        /* ... and create a new Subnet if not found */
        if (!subnet) {
-               ls_pref = ls_prefix_new(vertex->node->adv, p);
+               ls_pref = ls_prefix_new(vertex->node->adv, &p);
                subnet = ls_subnet_add(args->ted, ls_pref);
                /* Stop processing if we are unable to create a new subnet */
                if (!subnet)
@@ -1195,14 +1363,14 @@ static void isis_te_parse_lsp(struct mpls_te_area *mta, struct isis_lsp *lsp)
 
        ted = mta->ted;
 
-       te_debug("ISIS-TE(%s): Parse LSP %s", lsp->area->area_tag,
-                sysid_print(lsp->hdr.lsp_id));
+       te_debug("ISIS-TE(%s): Parse LSP %pSY", lsp->area->area_tag,
+                lsp->hdr.lsp_id);
 
        /* First parse LSP to obtain the corresponding Vertex */
        vertex = lsp_to_vertex(ted, lsp);
        if (!vertex) {
-               zlog_warn("Unable to build Vertex from LSP %s. Abort!",
-                         sysid_print(lsp->hdr.lsp_id));
+               zlog_warn("Unable to build Vertex from LSP %pSY. Abort!",
+                         lsp->hdr.lsp_id);
                return;
        }
 
@@ -1266,8 +1434,8 @@ static void isis_te_delete_lsp(struct mpls_te_area *mta, struct isis_lsp *lsp)
        if (!IS_MPLS_TE(mta) || !mta->ted || !lsp)
                return;
 
-       te_debug("ISIS-TE(%s): Delete Link State TED objects from LSP %s",
-                lsp->area->area_tag, sysid_print(lsp->hdr.lsp_id));
+       te_debug("ISIS-TE(%s): Delete Link State TED objects from LSP %pSY",
+                lsp->area->area_tag, lsp->hdr.lsp_id);
 
        /* Compute Link State Node ID from IS-IS sysID ... */
        if (lsp->level == ISIS_LEVEL1)
@@ -1851,7 +2019,7 @@ static int show_ted(struct vty *vty, struct cmd_token *argv[], int argc,
                                return CMD_WARNING_CONFIG_FAILED;
                        }
                        /* Get the Subnet from the Link State Database */
-                       subnet = ls_find_subnet(ted, pref);
+                       subnet = ls_find_subnet(ted, &pref);
                        if (!subnet) {
                                vty_out(vty, "No subnet found for ID %pFX\n",
                                        &pref);
@@ -1864,7 +2032,7 @@ static int show_ted(struct vty *vty, struct cmd_token *argv[], int argc,
                                return CMD_WARNING_CONFIG_FAILED;
                        }
                        /* Get the Subnet from the Link State Database */
-                       subnet = ls_find_subnet(ted, pref);
+                       subnet = ls_find_subnet(ted, &pref);
                        if (!subnet) {
                                vty_out(vty, "No subnet found for ID %pFX\n",
                                        &pref);