summaryrefslogtreecommitdiffstats
path: root/isisd/isis_sr.c
diff options
context:
space:
mode:
authorOlivier Dugeon <olivier.dugeon@orange.com>2020-10-23 21:03:55 +0200
committerGitHub <noreply@github.com>2020-10-23 21:03:55 +0200
commitacd043db007ce16417e812dda6e3c2ecfcc9e84b (patch)
tree9fccc7a5b18927e0776fef8b8b7ab057077bd1d9 /isisd/isis_sr.c
parentMerge pull request #6788 from mjstapp/thread_cancel_off (diff)
parenttests: extend the isisd SR topotest to test Anycast-SIDs as well (diff)
downloadfrr-acd043db007ce16417e812dda6e3c2ecfcc9e84b.tar.xz
frr-acd043db007ce16417e812dda6e3c2ecfcc9e84b.zip
Merge pull request #7184 from opensourcerouting/anycast-sids-v4
isisd: refactor Prefix-SID code + Anycast-SIDs (v2)
Diffstat (limited to 'isisd/isis_sr.c')
-rw-r--r--isisd/isis_sr.c1416
1 files changed, 143 insertions, 1273 deletions
diff --git a/isisd/isis_sr.c b/isisd/isis_sr.c
index 3f62f4dca..89fa2018b 100644
--- a/isisd/isis_sr.c
+++ b/isisd/isis_sr.c
@@ -31,6 +31,7 @@
#include "memory.h"
#include "prefix.h"
#include "table.h"
+#include "srcdest_table.h"
#include "vty.h"
#include "zclient.h"
#include "lib/lib_errors.h"
@@ -50,8 +51,6 @@
/* Local variables and functions */
DEFINE_MTYPE_STATIC(ISISD, ISIS_SR_INFO, "ISIS segment routing information")
-static void sr_prefix_uninstall(struct sr_prefix *srp);
-static void sr_prefix_reinstall(struct sr_prefix *srp, bool make_before_break);
static void sr_local_block_delete(struct isis_area *area);
static int sr_local_block_init(struct isis_area *area);
static void sr_adj_sid_update(struct sr_adjacency *sra,
@@ -61,53 +60,149 @@ static void sr_adj_sid_del(struct sr_adjacency *sra);
/* --- RB-Tree Management functions ----------------------------------------- */
/**
- * SR Prefix comparison for RB-Tree.
+ * Configured SR Prefix comparison for RB-Tree.
*
* @param a First SR prefix
* @param b Second SR prefix
*
* @return -1 (a < b), 0 (a == b) or +1 (a > b)
*/
-static inline int sr_prefix_sid_compare(const struct sr_prefix *a,
- const struct sr_prefix *b)
+static inline int sr_prefix_sid_cfg_compare(const struct sr_prefix_cfg *a,
+ const struct sr_prefix_cfg *b)
{
return prefix_cmp(&a->prefix, &b->prefix);
}
-DECLARE_RBTREE_UNIQ(srdb_node_prefix, struct sr_prefix, node_entry,
- sr_prefix_sid_compare)
-DECLARE_RBTREE_UNIQ(srdb_area_prefix, struct sr_prefix, area_entry,
- sr_prefix_sid_compare)
+DECLARE_RBTREE_UNIQ(srdb_prefix_cfg, struct sr_prefix_cfg, entry,
+ sr_prefix_sid_cfg_compare)
/**
- * Configured SR Prefix comparison for RB-Tree.
+ * Find SRGB associated to a System ID.
*
- * @param a First SR prefix
- * @param b Second SR prefix
+ * @param area IS-IS LSP database
+ * @param sysid System ID to lookup
*
- * @return -1 (a < b), 0 (a == b) or +1 (a > b)
+ * @return Pointer to SRGB if found, NULL otherwise
*/
-static inline int sr_prefix_sid_cfg_compare(const struct sr_prefix_cfg *a,
- const struct sr_prefix_cfg *b)
+struct isis_sr_block *isis_sr_find_srgb(struct lspdb_head *lspdb,
+ const uint8_t *sysid)
{
- return prefix_cmp(&a->prefix, &b->prefix);
+ struct isis_lsp *lsp;
+
+ lsp = isis_root_system_lsp(lspdb, sysid);
+ if (!lsp)
+ return NULL;
+
+ if (!lsp->tlvs->router_cap
+ || lsp->tlvs->router_cap->srgb.range_size == 0)
+ return NULL;
+
+ return &lsp->tlvs->router_cap->srgb;
}
-DECLARE_RBTREE_UNIQ(srdb_prefix_cfg, struct sr_prefix_cfg, entry,
- sr_prefix_sid_cfg_compare)
/**
- * SR Node comparison for RB-Tree.
+ * Compute input label for the given Prefix-SID.
*
- * @param a First SR node
- * @param b Second SR node
+ * @param area IS-IS area
+ * @param psid IS-IS Prefix-SID Sub-TLV
+ * @param local Indicates whether the Prefix-SID is local or not
*
- * @return -1 (a < b), 0 (a == b) or +1 (a > b)
+ * @return MPLS label or MPLS_INVALID_LABEL in case of SRGB overflow
*/
-static inline int sr_node_compare(const struct sr_node *a,
- const struct sr_node *b)
+mpls_label_t sr_prefix_in_label(struct isis_area *area,
+ struct isis_prefix_sid *psid, bool local)
{
- return memcmp(a->sysid, b->sysid, ISIS_SYS_ID_LEN);
+ /*
+ * No need to assign a label for local Prefix-SIDs unless the no-PHP
+ * flag is set.
+ */
+ if (local
+ && (!CHECK_FLAG(psid->flags, ISIS_PREFIX_SID_NO_PHP)
+ || CHECK_FLAG(psid->flags, ISIS_PREFIX_SID_EXPLICIT_NULL)))
+ return MPLS_INVALID_LABEL;
+
+ /* Return SID value as MPLS label if it is an Absolute SID */
+ if (CHECK_FLAG(psid->flags,
+ ISIS_PREFIX_SID_VALUE | ISIS_PREFIX_SID_LOCAL))
+ return psid->value;
+
+ /* Check that SID index falls inside the SRGB */
+ if (psid->value >= (area->srdb.config.srgb_upper_bound
+ - area->srdb.config.srgb_lower_bound + 1)) {
+ flog_warn(EC_ISIS_SID_OVERFLOW,
+ "%s: SID index %u falls outside local SRGB range",
+ __func__, psid->value);
+ return MPLS_INVALID_LABEL;
+ }
+
+ /* Return MPLS label as SID index + SRGB_lower_bound as per RFC 8667 */
+ return (area->srdb.config.srgb_lower_bound + psid->value);
+}
+
+/**
+ * Compute output label for the given Prefix-SID.
+ *
+ * @param lspdb IS-IS LSP database
+ * @param family Prefix-SID address family
+ * @param psid Prefix-SID Sub-TLV
+ * @param nh_sysid System ID of the nexthop node
+ * @param last_hop Indicates whether the nexthop node is the last hop
+ *
+ * @return MPLS label or MPLS_INVALID_LABEL in case of error
+ */
+mpls_label_t sr_prefix_out_label(struct lspdb_head *lspdb, int family,
+ struct isis_prefix_sid *psid,
+ const uint8_t *nh_sysid, bool last_hop)
+{
+ struct isis_sr_block *nh_srgb;
+
+ if (last_hop) {
+ if (!CHECK_FLAG(psid->flags, ISIS_PREFIX_SID_NO_PHP))
+ return MPLS_LABEL_IMPLICIT_NULL;
+
+ if (CHECK_FLAG(psid->flags, ISIS_PREFIX_SID_EXPLICIT_NULL)) {
+ if (family == AF_INET)
+ return MPLS_LABEL_IPV4_EXPLICIT_NULL;
+ else
+ return MPLS_LABEL_IPV6_EXPLICIT_NULL;
+ }
+ /* Fallthrough */
+ }
+
+ /* Return SID value as MPLS label if it is an Absolute SID */
+ if (CHECK_FLAG(psid->flags,
+ ISIS_PREFIX_SID_VALUE | ISIS_PREFIX_SID_LOCAL)) {
+ /*
+ * V/L SIDs have local significance, so only adjacent routers
+ * can use them (RFC8667 section #2.1.1.1)
+ */
+ if (!last_hop)
+ return MPLS_INVALID_LABEL;
+ return psid->value;
+ }
+
+ /* Check that SID index falls inside the SRGB */
+ nh_srgb = isis_sr_find_srgb(lspdb, nh_sysid);
+ if (!nh_srgb)
+ return MPLS_INVALID_LABEL;
+
+ /*
+ * Check if the nexthop can handle SR-MPLS encapsulated IPv4 or
+ * IPv6 packets.
+ */
+ if ((family == AF_INET && !IS_SR_IPV4(nh_srgb))
+ || (family == AF_INET6 && !IS_SR_IPV6(nh_srgb)))
+ return MPLS_INVALID_LABEL;
+
+ if (psid->value >= nh_srgb->range_size) {
+ flog_warn(EC_ISIS_SID_OVERFLOW,
+ "%s: SID index %u falls outside remote SRGB range",
+ __func__, psid->value);
+ return MPLS_INVALID_LABEL;
+ }
+
+ /* Return MPLS label as SID index + SRGB_lower_bound as per RFC 8667 */
+ return (nh_srgb->lower_bound + psid->value);
}
-DECLARE_RBTREE_UNIQ(srdb_node, struct sr_node, entry, sr_node_compare)
/* --- Functions used for Yang model and CLI to configure Segment Routing --- */
@@ -162,8 +257,6 @@ int isis_sr_cfg_srgb_update(struct isis_area *area, uint32_t lower_bound,
srdb->config.srgb_upper_bound = upper_bound;
if (srdb->enabled) {
- struct sr_prefix *srp;
-
/* then request new SRGB if SR is enabled. */
if (isis_zebra_request_label_range(
srdb->config.srgb_lower_bound,
@@ -179,14 +272,6 @@ int isis_sr_cfg_srgb_update(struct isis_area *area, uint32_t lower_bound,
srdb->config.srgb_lower_bound,
srdb->config.srgb_upper_bound);
- /* Reinstall local Prefix-SIDs to update their input labels. */
- for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) {
- frr_each (srdb_area_prefix,
- &area->srdb.prefix_sids[level - 1], srp) {
- sr_prefix_reinstall(srp, false);
- }
- }
-
lsp_regenerate_schedule(area, area->is_type, 0);
} else if (srdb->config.enabled) {
/* Try to enable SR again using the new SRGB. */
@@ -278,7 +363,7 @@ struct sr_prefix_cfg *isis_sr_cfg_prefix_add(struct isis_area *area,
/* Set the N-flag when appropriate. */
ifp = if_lookup_prefix(prefix, VRF_DEFAULT);
- if (ifp && sr_prefix_is_node_sid(ifp, prefix))
+ if (ifp && sr_prefix_is_node_sid(ifp, prefix) && !pcfg->n_flag_clear)
pcfg->node_sid = true;
/* Save prefix-sid configuration. */
@@ -364,897 +449,6 @@ void isis_sr_prefix_cfg2subtlv(const struct sr_prefix_cfg *pcfg, bool external,
}
}
-/* --- Segment Routing Prefix Management functions -------------------------- */
-
-/**
- * Add Segment Routing Prefix to a given Segment Routing Node.
- *
- * @param area IS-IS area
- * @param srn Segment Routing Node
- * @param prefix Prefix to be added
- * @param local True if prefix is locally configured, false otherwise
- * @param psid Prefix-SID sub-TLVs
- *
- * @return New Segment Routing Prefix structure
- */
-static struct sr_prefix *sr_prefix_add(struct isis_area *area,
- struct sr_node *srn,
- union prefixconstptr prefix, bool local,
- const struct isis_prefix_sid *psid)
-{
- struct sr_prefix *srp;
-
- srp = XCALLOC(MTYPE_ISIS_SR_INFO, sizeof(*srp));
- prefix_copy(&srp->prefix, prefix.p);
- srp->sid = *psid;
- srp->input_label = MPLS_INVALID_LABEL;
- if (local) {
- srp->type = ISIS_SR_PREFIX_LOCAL;
- isis_sr_nexthop_reset(&srp->u.local.info);
- } else {
- srp->type = ISIS_SR_PREFIX_REMOTE;
- srp->u.remote.rinfo = NULL;
- }
- srp->srn = srn;
- srdb_node_prefix_add(&srn->prefix_sids, srp);
- /* TODO: this might fail if we have Anycast SIDs in the IS-IS area. */
- srdb_area_prefix_add(&area->srdb.prefix_sids[srn->level - 1], srp);
-
- sr_debug(" |- Added new SR Prefix-SID %pFX %s %u to SR Node %s",
- &srp->prefix, IS_SID_VALUE(srp->sid.flags) ? "label" : "index",
- srp->sid.value, sysid_print(srn->sysid));
-
- return srp;
-}
-
-/**
- * Remove given Segment Prefix from given Segment Routing Node.
- * Prefix-SID is un-installed first.
- *
- * @param area IS-IS area
- * @param srn Segment Routing Node
- * @param srp Segment Routing Prefix
- */
-static void sr_prefix_del(struct isis_area *area, struct sr_node *srn,
- struct sr_prefix *srp)
-{
- sr_debug(" |- Delete SR Prefix-SID %pFX %s %u to SR Node %s",
- &srp->prefix, IS_SID_VALUE(srp->sid.flags) ? "label" : "index",
- srp->sid.value, sysid_print(srn->sysid));
-
- sr_prefix_uninstall(srp);
- srdb_node_prefix_del(&srn->prefix_sids, srp);
- srdb_area_prefix_del(&area->srdb.prefix_sids[srn->level - 1], srp);
- XFREE(MTYPE_ISIS_SR_INFO, srp);
-}
-
-/**
- * Find Segment Routing Prefix by Area.
- *
- * @param area IS-IS area
- * @param level IS-IS level
- * @param prefix Prefix to lookup
- *
- * @return Segment Routing Prefix structure if found, NULL otherwise
- */
-static struct sr_prefix *sr_prefix_find_by_area(struct isis_area *area,
- int level,
- union prefixconstptr prefix)
-{
- struct sr_prefix srp = {};
-
- prefix_copy(&srp.prefix, prefix.p);
- return srdb_area_prefix_find(&area->srdb.prefix_sids[level - 1], &srp);
-}
-
-/**
- * Find Segment Routing Prefix by Segment Routing Node.
- *
- * @param srn Segment Routing Node
- * @param prefix Prefix to lookup
- *
- * @return Segment Routing Prefix structure if found, NULL otherwise
- */
-static struct sr_prefix *sr_prefix_find_by_node(struct sr_node *srn,
- union prefixconstptr prefix)
-{
- struct sr_prefix srp = {};
-
- prefix_copy(&srp.prefix, prefix.p);
- return srdb_node_prefix_find(&srn->prefix_sids, &srp);
-}
-
-/* --- Segment Routing Node Management functions ---------------------------- */
-
-/**
- * Add Segment Routing Node to the Segment Routing Data Base.
- *
- * @param area IS-IS area
- * @param level IS-IS level
- * @param sysid Node System ID
- * @param cap Segment Routing Capability sub-TLVs
- *
- * @return New Segment Routing Node structure
- */
-static struct sr_node *sr_node_add(struct isis_area *area, int level,
- const uint8_t *sysid)
-{
- struct sr_node *srn;
-
- srn = XCALLOC(MTYPE_ISIS_SR_INFO, sizeof(*srn));
- srn->level = level;
- memcpy(srn->sysid, sysid, ISIS_SYS_ID_LEN);
- srn->area = area;
- srdb_node_prefix_init(&srn->prefix_sids);
- srdb_node_add(&area->srdb.sr_nodes[level - 1], srn);
-
- sr_debug(" |- Added new SR Node %s", sysid_print(srn->sysid));
-
- return srn;
-}
-
-static void sr_node_del(struct isis_area *area, int level, struct sr_node *srn)
-/**
- * Remove Segment Routing Node from the Segment Routing Data Base.
- * All Prefix-SID attached to this Segment Routing Node are removed first.
- *
- * @param area IS-IS area
- * @param level IS-IS level
- * @param srn Segment Routing Node to be deleted
- */
-{
-
- sr_debug(" |- Delete SR Node %s", sysid_print(srn->sysid));
-
- /* Remove and uninstall Prefix-SIDs. */
- while (srdb_node_prefix_count(&srn->prefix_sids) > 0) {
- struct sr_prefix *srp;
-
- srp = srdb_node_prefix_first(&srn->prefix_sids);
- sr_prefix_del(area, srn, srp);
- }
-
- srdb_node_del(&area->srdb.sr_nodes[level - 1], srn);
- XFREE(MTYPE_ISIS_SR_INFO, srn);
-}
-
-/**
- * Find Segment Routing Node in the Segment Routing Data Base per system ID.
- *
- * @param area IS-IS area
- * @param level IS-IS level
- * @param sysid Node System ID to lookup
- *
- * @return Segment Routing Node structure if found, NULL otherwise
- */
-static struct sr_node *sr_node_find(struct isis_area *area, int level,
- const uint8_t *sysid)
-{
- struct sr_node srn = {};
-
- memcpy(srn.sysid, sysid, ISIS_SYS_ID_LEN);
- return srdb_node_find(&area->srdb.sr_nodes[level - 1], &srn);
-}
-
-/**
- * Update Segment Routing Node following an SRGB update. This function
- * is called when a neighbor SR Node has updated its SRGB.
- *
- * @param area IS-IS area
- * @param level IS-IS level
- * @param sysid Segment Routing Node system ID
- */
-static void sr_node_srgb_update(struct isis_area *area, int level,
- uint8_t *sysid)
-{
- struct sr_prefix *srp;
-
- sr_debug("ISIS-Sr (%s): Update neighbors SR Node with new SRGB",
- area->area_tag);
-
- frr_each (srdb_area_prefix, &area->srdb.prefix_sids[level - 1], srp) {
- struct listnode *node;
- struct isis_nexthop *nh;
-
- if (srp->type == ISIS_SR_PREFIX_LOCAL)
- continue;
-
- if (srp->u.remote.rinfo == NULL)
- continue;
-
- for (ALL_LIST_ELEMENTS_RO(srp->u.remote.rinfo->nexthops, node,
- nh)) {
- if (memcmp(nh->sysid, sysid, ISIS_SYS_ID_LEN) != 0)
- continue;
-
- /*
- * The Prefix-SID input label hasn't changed. We could
- * re-install all Prefix-SID with "Make Before Break"
- * option. Zebra layer will update output label(s) by
- * adding new entry before removing the old one(s).
- */
- sr_prefix_reinstall(srp, true);
- break;
- }
- }
-}
-
-/* --- Segment Routing Nexthop information Management functions ------------- */
-
-/**
- * Update Segment Routing Nexthop.
- *
- * @param srnh Segment Routing next hop
- * @param label Output MPLS label
- */
-void isis_sr_nexthop_update(struct sr_nexthop_info *srnh, mpls_label_t label)
-{
- srnh->label = label;
- if (srnh->uptime == 0)
- srnh->uptime = time(NULL);
-}
-
-/**
- * Reset Segment Routing Nexthop.
- *
- * @param srnh Segment Routing Nexthop
- */
-void isis_sr_nexthop_reset(struct sr_nexthop_info *srnh)
-{
- srnh->label = MPLS_INVALID_LABEL;
- srnh->uptime = 0;
-}
-
-/* --- Segment Routing Prefix-SID Management functions to configure LFIB ---- */
-
-/**
- * Lookup IS-IS route in the Shortest Path Tree.
- *
- * @param area IS-IS area
- * @param tree_id Shortest Path Tree identifier
- * @param srp Segment Routing Prefix to lookup
- *
- * @return Route Information for this prefix if found, NULL otherwise
- */
-static struct isis_route_info *sr_prefix_lookup_route(struct isis_area *area,
- enum spf_tree_id tree_id,
- struct sr_prefix *srp)
-{
- struct route_node *rn;
- int level = srp->srn->level;
-
- rn = route_node_lookup(area->spftree[tree_id][level - 1]->route_table,
- &srp->prefix);
- if (rn) {
- route_unlock_node(rn);
- if (rn->info)
- return rn->info;
- }
-
- return NULL;
-}
-
-/**
- * Compute input label for the given Prefix-SID.
- *
- * @param srp Segment Routing Prefix
- *
- * @return MPLS label or MPLS_INVALID_LABEL in case of SRGB overflow
- */
-static mpls_label_t sr_prefix_in_label(const struct sr_prefix *srp)
-{
- const struct sr_node *srn = srp->srn;
- struct isis_area *area = srn->area;
-
- /* Return SID value as MPLS label if it is an Absolute SID */
- if (CHECK_FLAG(srp->sid.flags,
- ISIS_PREFIX_SID_VALUE | ISIS_PREFIX_SID_LOCAL))
- return srp->sid.value;
-
- /* Check that SID index falls inside the SRGB */
- if (srp->sid.value >= (area->srdb.config.srgb_upper_bound
- - area->srdb.config.srgb_lower_bound + 1)) {
- flog_warn(EC_ISIS_SID_OVERFLOW,
- "%s: SID index %u falls outside local SRGB range",
- __func__, srp->sid.value);
- return MPLS_INVALID_LABEL;
- }
-
- /* Return MPLS label as SID index + SRGB_lower_bound as per RFC 8667 */
- return (area->srdb.config.srgb_lower_bound + srp->sid.value);
-}
-
-/**
- * Compute output label for the given Prefix-SID.
- *
- * @param srp Segment Routing Prefix
- * @param srn_nexthop Segment Routing nexthop node
- * @param sysid System ID of the SR node which advertised the Prefix-SID
- *
- * @return MPLS label or MPLS_INVALID_LABEL in case of error
- */
-static mpls_label_t sr_prefix_out_label(const struct sr_prefix *srp,
- const struct sr_node *srn_nexthop,
- const uint8_t *sysid)
-{
- const struct sr_node *srn = srp->srn;
-
- /* Check if the nexthop SR Node is the last hop? */
- if (memcmp(sysid, srn->sysid, ISIS_SYS_ID_LEN) == 0) {
- /* SR-Node doesn't request NO-PHP. Return Implicit NULL label */
- if (!CHECK_FLAG(srp->sid.flags, ISIS_PREFIX_SID_NO_PHP))
- return MPLS_LABEL_IMPLICIT_NULL;
-
- /* SR-Node requests Implicit NULL Label */
- if (CHECK_FLAG(srp->sid.flags, ISIS_PREFIX_SID_EXPLICIT_NULL)) {
- if (srp->prefix.family == AF_INET)
- return MPLS_LABEL_IPV4_EXPLICIT_NULL;
- else
- return MPLS_LABEL_IPV6_EXPLICIT_NULL;
- }
- /* Fallthrough */
- }
-
- /* Return SID value as MPLS label if it is an Absolute SID */
- if (CHECK_FLAG(srp->sid.flags,
- ISIS_PREFIX_SID_VALUE | ISIS_PREFIX_SID_LOCAL)) {
- /*
- * V/L SIDs have local significance, so only adjacent routers
- * can use them (RFC8667 section #2.1.1.1)
- */
- if (srp->srn != srn_nexthop)
- return MPLS_INVALID_LABEL;
- return srp->sid.value;
- }
-
- /* Check that SID index falls inside the SRGB */
- if (srp->sid.value >= srn_nexthop->cap.srgb.range_size) {
- flog_warn(EC_ISIS_SID_OVERFLOW,
- "%s: SID index %u falls outside remote SRGB range",
- __func__, srp->sid.value);
- return MPLS_INVALID_LABEL;
- }
-
- /* Return MPLS label as SID index + SRGB_lower_bound as per RFC 8667 */
- return (srn_nexthop->cap.srgb.lower_bound + srp->sid.value);
-}
-
-/**
- * Process local Prefix-SID and install it if possible. Input label is
- * computed before installing it in LFIB.
- *
- * @param srp Segment Routing Prefix
- *
- * @return 0 on success, -1 otherwise
- */
-static int sr_prefix_install_local(struct sr_prefix *srp)
-{
- mpls_label_t input_label;
- const struct sr_node *srn = srp->srn;
-
- /*
- * No need to install Label for local Prefix-SID unless the
- * no-PHP option is configured.
- */
- if (!CHECK_FLAG(srp->sid.flags, ISIS_PREFIX_SID_NO_PHP)
- || CHECK_FLAG(srp->sid.flags, ISIS_PREFIX_SID_EXPLICIT_NULL))
- return -1;
-
- sr_debug(" |- Installing Prefix-SID %pFX %s %u (%s) with nexthop self",
- &srp->prefix, IS_SID_VALUE(srp->sid.flags) ? "label" : "index",
- srp->sid.value, circuit_t2string(srn->level));
-
- /* Compute input label and check that is valid. */
- input_label = sr_prefix_in_label(srp);
- if (input_label == MPLS_INVALID_LABEL)
- return -1;
-
- /* Update internal state. */
- srp->input_label = input_label;
- isis_sr_nexthop_update(&srp->u.local.info, MPLS_LABEL_IMPLICIT_NULL);
-
- /* Install Prefix-SID in the forwarding plane. */
- isis_zebra_send_prefix_sid(ZEBRA_MPLS_LABELS_REPLACE, srp);
-
- return 0;
-}
-
-/**
- * Process remote Prefix-SID and install it if possible. Input and Output
- * labels are computed before installing them in LFIB.
- *
- * @param srp Segment Routing Prefix
- *
- * @return 0 on success, -1 otherwise
- */
-static int sr_prefix_install_remote(struct sr_prefix *srp)
-{
- const struct sr_node *srn = srp->srn;
- struct isis_area *area = srn->area;
- enum spf_tree_id tree_id;
- struct listnode *node;
- struct isis_nexthop *nexthop;
- mpls_label_t input_label;
- size_t nexthop_num = 0;
-
- /* Lookup to associated IS-IS route. */
- tree_id = (srp->prefix.family == AF_INET) ? SPFTREE_IPV4 : SPFTREE_IPV6;
- srp->u.remote.rinfo = sr_prefix_lookup_route(area, tree_id, srp);
- if (!srp->u.remote.rinfo)
- /* SPF hasn't converged for this route yet. */
- return -1;
-
- /* Compute input label and check that is valid. */
- input_label = sr_prefix_in_label(srp);
- if (input_label == MPLS_INVALID_LABEL)
- return -1;
-
- sr_debug(" |- Installing Prefix-SID %pFX %s %u (%s)", &srp->prefix,
- IS_SID_VALUE(srp->sid.flags) ? "label" : "index",
- srp->sid.value, circuit_t2string(srn->level));
-
- /* Process all SPF nexthops */
- for (ALL_LIST_ELEMENTS_RO(srp->u.remote.rinfo->nexthops, node,
- nexthop)) {
- struct sr_node *srn_nexthop;
- mpls_label_t output_label;
-
- /* Check if the nexthop advertised a SRGB. */
- srn_nexthop = sr_node_find(area, srn->level, nexthop->sysid);
- if (!srn_nexthop)
- goto next;
-
- /*
- * Check if the nexthop can handle SR-MPLS encapsulated IPv4 or
- * IPv6 packets.
- */
- if ((nexthop->family == AF_INET
- && !IS_SR_IPV4(srn_nexthop->cap.srgb))
- || (nexthop->family == AF_INET6
- && !IS_SR_IPV6(srn_nexthop->cap.srgb)))
- goto next;
-
- /* Compute output label and check if it is valid */
- output_label =
- sr_prefix_out_label(srp, srn_nexthop, nexthop->sysid);
- if (output_label == MPLS_INVALID_LABEL)
- goto next;
-
- if (IS_DEBUG_SR) {
- static char buf[INET6_ADDRSTRLEN];
-
- inet_ntop(nexthop->family, &nexthop->ip, buf,
- sizeof(buf));
- zlog_debug(" |- nexthop %s label %u", buf,
- output_label);
- }
-
- isis_sr_nexthop_update(&nexthop->sr, output_label);
- nexthop_num++;
- continue;
- next:
- isis_sr_nexthop_reset(&nexthop->sr);
- }
-
- /* Check that we found at least one valid nexthop */
- if (nexthop_num == 0) {
- sr_debug(" |- no valid nexthops");
- return -1;
- }
-
- /* Update internal state. */
- srp->input_label = input_label;
-
- /* Install Prefix-SID in the forwarding plane. */
- isis_zebra_send_prefix_sid(ZEBRA_MPLS_LABELS_REPLACE, srp);
-
- return 0;
-}
-
-/**
- * Process local or remote Prefix-SID and install it if possible.
- *
- * @param srp Segment Routing Prefix
- */
-static void sr_prefix_install(struct sr_prefix *srp)
-{
- const struct sr_node *srn = srp->srn;
- struct isis_area *area = srn->area;
- int ret;
-
- sr_debug("ISIS-Sr (%s): Install Prefix-SID %pFX %s %u", area->area_tag,
- &srp->prefix, IS_SID_VALUE(srp->sid.flags) ? "label" : "index",
- srp->sid.value);
-
- /* L1 routes are preferred over the L2 ones. */
- if (area->is_type == IS_LEVEL_1_AND_2) {
- struct sr_prefix *srp_l1, *srp_l2;
-
- switch (srn->level) {
- case ISIS_LEVEL1:
- srp_l2 = sr_prefix_find_by_area(area, ISIS_LEVEL2,
- &srp->prefix);
- if (srp_l2)
- sr_prefix_uninstall(srp_l2);
- break;
- case ISIS_LEVEL2:
- srp_l1 = sr_prefix_find_by_area(area, ISIS_LEVEL1,
- &srp->prefix);
- if (srp_l1)
- return;
- break;
- default:
- break;
- }
- }
-
- /* Install corresponding LFIB entry */
- if (srp->type == ISIS_SR_PREFIX_LOCAL)
- ret = sr_prefix_install_local(srp);
- else
- ret = sr_prefix_install_remote(srp);
- if (ret != 0)
- sr_prefix_uninstall(srp);
-}
-
-/**
- * Uninstall local or remote Prefix-SID.
- *
- * @param srp Segment Routing Prefix
- */
-static void sr_prefix_uninstall(struct sr_prefix *srp)
-{
- struct listnode *node;
- struct isis_nexthop *nexthop;
-
- /* Check that Input Label is valid */
- if (srp->input_label == MPLS_INVALID_LABEL)
- return;
-
- sr_debug("ISIS-Sr: Un-install Prefix-SID %pFX %s %u", &srp->prefix,
- IS_SID_VALUE(srp->sid.flags) ? "label" : "index",
- srp->sid.value);
-
- /* Uninstall Prefix-SID from the forwarding plane. */
- isis_zebra_send_prefix_sid(ZEBRA_MPLS_LABELS_DELETE, srp);
-
- /* Reset internal state. */
- srp->input_label = MPLS_INVALID_LABEL;
- switch (srp->type) {
- case ISIS_SR_PREFIX_LOCAL:
- isis_sr_nexthop_reset(&srp->u.local.info);
- break;
- case ISIS_SR_PREFIX_REMOTE:
- if (srp->u.remote.rinfo) {
- for (ALL_LIST_ELEMENTS_RO(srp->u.remote.rinfo->nexthops,
- node, nexthop))
- isis_sr_nexthop_reset(&nexthop->sr);
- }
- break;
- }
-}
-
-/**
- * Reinstall local or remote Prefix-SID.
- *
- * @param srp Segment Routing Prefix
- */
-static inline void sr_prefix_reinstall(struct sr_prefix *srp,
- bool make_before_break)
-{
- /*
- * Make Before Break can be used only when we know for sure that
- * the Prefix-SID input label hasn't changed. Otherwise we need to
- * uninstall the Prefix-SID first using the old input label before
- * reinstalling it.
- */
- if (!make_before_break)
- sr_prefix_uninstall(srp);
-
- /* New input label is computed in sr_prefix_install() function */
- sr_prefix_install(srp);
-}
-
-/* --- IS-IS LSP Parse functions -------------------------------------------- */
-
-/**
- * Compare Router Capabilities. Only Flags, SRGB and Algorithm are used for the
- * comparison. MSD and SRLB modification must not trigger and SR-Prefix update.
- *
- * @param r1 First Router Capabilities to compare
- * @param r2 Second Router Capabilities to compare
- * @return 0 if r1 and r2 are equal or -1 otherwise
- */
-static int router_cap_cmp(const struct isis_router_cap *r1,
- const struct isis_router_cap *r2)
-{
- if (r1->flags == r2->flags
- && r1->srgb.lower_bound == r2->srgb.lower_bound
- && r1->srgb.range_size == r2->srgb.range_size
- && r1->algo[0] == r2->algo[0])
- return 0;
- else
- return -1;
-}
-
-/**
- * Parse all SR-related information from the given Router Capabilities TLV.
- *
- * @param area IS-IS area
- * @param level IS-IS level
- * @param sysid System ID of the LSP
- * @param router_cap Router Capability subTLVs
- *
- * @return Segment Routing Node structure for this System ID
- */
-static struct sr_node *
-parse_router_cap_tlv(struct isis_area *area, int level, const uint8_t *sysid,
- const struct isis_router_cap *router_cap)
-{
- struct sr_node *srn;
-
- if (!router_cap || router_cap->srgb.range_size == 0)
- return NULL;
-
- sr_debug("ISIS-Sr (%s): Parse Router Capability TLV", area->area_tag);
-
- srn = sr_node_find(area, level, sysid);
- if (srn) {
- if (router_cap_cmp(&srn->cap, router_cap) != 0) {
- srn->state = SRDB_STATE_MODIFIED;
- } else
- srn->state = SRDB_STATE_UNCHANGED;
- sr_debug(" |- Found %s SR Node %s",
- srn->state == SRDB_STATE_MODIFIED ? "Modified"
- : "Unchanged",
- sysid_print(srn->sysid));
- } else {
- srn = sr_node_add(area, level, sysid);
- srn->state = SRDB_STATE_NEW;
- }
-
- /*
- * Update Router Capabilities in any case as SRLB or MSD
- * modification are not take into account for comparison.
- */
- srn->cap = *router_cap;
-
- return srn;
-}
-
-/**
- * Parse list of Prefix-SID Sub-TLVs.
- *
- * @param srn Segment Routing Node
- * @param prefix Prefix to be parsed
- * @param local True if prefix comes from own LSP, false otherwise
- * @param prefix_sids Prefix SID subTLVs
- */
-static void parse_prefix_sid_subtlvs(struct sr_node *srn,
- union prefixconstptr prefix, bool local,
- struct isis_item_list *prefix_sids)
-{
- struct isis_area *area = srn->area;
- struct isis_item *i;
-
- sr_debug("ISIS-Sr (%s): Parse Prefix SID TLV", area->area_tag);
-
- /* Parse list of Prefix SID subTLVs */
- for (i = prefix_sids->head; i; i = i->next) {
- struct isis_prefix_sid *psid = (struct isis_prefix_sid *)i;
- struct sr_prefix *srp;
-
- /* Only SPF algorithm is supported right now */
- if (psid->algorithm != SR_ALGORITHM_SPF)
- continue;
-
- /* Compute corresponding Segment Routing Prefix */
- srp = sr_prefix_find_by_node(srn, prefix);
- if (srp) {
- if (srp->sid.flags != psid->flags
- || srp->sid.algorithm != psid->algorithm
- || srp->sid.value != psid->value) {
- srp->sid = *psid;
- srp->state = SRDB_STATE_MODIFIED;
- } else if (srp->state == SRDB_STATE_VALIDATED)
- srp->state = SRDB_STATE_UNCHANGED;
- sr_debug(" |- Found %s Prefix-SID %pFX",
- srp->state == SRDB_STATE_MODIFIED
- ? "Modified"
- : "Unchanged",
- &srp->prefix);
-
- } else {
- srp = sr_prefix_add(area, srn, prefix, local, psid);
- srp->state = SRDB_STATE_NEW;
- }
- /*
- * Stop the Prefix-SID iteration since we only support the SPF
- * algorithm for now.
- */
- break;
- }
-}
-
-/**
- * Parse all SR-related information from the given LSP.
- *
- * @param area IS-IS area
- * @param level IS-IS level
- * @param srn Segment Routing Node
- * @param lsp IS-IS LSP
- */
-static void parse_lsp(struct isis_area *area, int level, struct sr_node **srn,
- struct isis_lsp *lsp)
-{
- struct isis_item_list *items;
- struct isis_item *i;
- bool local = lsp->own_lsp;
-
- /* Check LSP sequence number */
- if (lsp->hdr.seqno == 0) {
- zlog_warn("%s: lsp with 0 seq_num - ignore", __func__);
- return;
- }
-
- sr_debug("ISIS-Sr (%s): Parse LSP from node %s", area->area_tag,
- sysid_print(lsp->hdr.lsp_id));
-
- /* Parse the Router Capability TLV. */
- if (*srn == NULL) {
- *srn = parse_router_cap_tlv(area, level, lsp->hdr.lsp_id,
- lsp->tlvs->router_cap);
- if (!*srn)
- return;
- }
-
- /* Parse the Extended IP Reachability TLV. */
- items = &lsp->tlvs->extended_ip_reach;
- for (i = items->head; i; i = i->next) {
- struct isis_extended_ip_reach *ir;
-
- ir = (struct isis_extended_ip_reach *)i;
- if (!ir->subtlvs)
- continue;
-
- parse_prefix_sid_subtlvs(*srn, &ir->prefix, local,
- &ir->subtlvs->prefix_sids);
- }
-
- /* Parse Multi Topology Reachable IPv6 Prefixes TLV. */
- items = isis_lookup_mt_items(&lsp->tlvs->mt_ipv6_reach,
- ISIS_MT_IPV6_UNICAST);
- for (i = items ? items->head : NULL; i; i = i->next) {
- struct isis_ipv6_reach *ir;
-
- ir = (struct isis_ipv6_reach *)i;
- if (!ir->subtlvs)
- continue;
-
- parse_prefix_sid_subtlvs(*srn, &ir->prefix, local,
- &ir->subtlvs->prefix_sids);
- }
-}
-
-/**
- * Parse all SR-related information from the entire LSPDB.
- *
- * @param area IS-IS area
- */
-static void parse_lspdb(struct isis_area *area)
-{
- struct isis_lsp *lsp;
-
- sr_debug("ISIS-Sr (%s): Parse LSP Data Base", area->area_tag);
-
- /* Process all LSP from Level 1 & 2 */
- for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) {
- frr_each (lspdb, &area->lspdb[level - 1], lsp) {
- struct isis_lsp *frag;
- struct listnode *node;
- struct sr_node *srn = NULL;
-
- /* Skip Pseudo ID LSP and LSP without TLVs */
- if (LSP_PSEUDO_ID(lsp->hdr.lsp_id))
- continue;
- if (!lsp->tlvs)
- continue;
-
- /* Parse LSP, then fragment */
- parse_lsp(area, level, &srn, lsp);
- for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag))
- parse_lsp(area, level, &srn, frag);
- }
- }
-}
-
-/**
- * Process any new/deleted/modified Prefix-SID in the LSPDB.
- *
- * @param srn Segment Routing Node
- * @param srp Segment Routing Prefix
- */
-static void process_prefix_changes(struct sr_node *srn, struct sr_prefix *srp)
-{
- struct isis_area *area = srn->area;
-
- /* Install/reinstall/uninstall Prefix-SID if necessary. */
- switch (srp->state) {
- case SRDB_STATE_NEW:
- sr_debug("ISIS-Sr (%s): Created Prefix-SID %pFX for SR node %s",
- area->area_tag, &srp->prefix, sysid_print(srn->sysid));
- sr_prefix_install(srp);
- break;
- case SRDB_STATE_MODIFIED:
- sr_debug(
- "ISIS-Sr (%s): Modified Prefix-SID %pFX for SR node %s",
- area->area_tag, &srp->prefix, sysid_print(srn->sysid));
- sr_prefix_reinstall(srp, false);
- break;
- case SRDB_STATE_UNCHANGED:
- break;
- default:
- sr_debug("ISIS-Sr (%s): Removed Prefix-SID %pFX for SR node %s",
- area->area_tag, &srp->prefix, sysid_print(srn->sysid));
- sr_prefix_del(area, srn, srp);
- return;
- }
-
- /* Validate SRDB State for next LSPDB parsing */
- srp->state = SRDB_STATE_VALIDATED;
-}
-
-/**
- * Process any new/deleted/modified SRGB in the LSPDB.
- *
- * @param area IS-IS area
- * @param level IS-IS level
- * @param srn Segment Routing Node
- */
-static void process_node_changes(struct isis_area *area, int level,
- struct sr_node *srn)
-{
- struct sr_prefix *srp;
- uint8_t sysid[ISIS_SYS_ID_LEN];
- bool adjacent;
-
- memcpy(sysid, srn->sysid, sizeof(sysid));
-
- /*
- * If an neighbor router's SRGB was changed or created, then reinstall
- * all Prefix-SIDs from all nodes that use this neighbor as nexthop.
- */
- adjacent = !!isis_adj_find(area, level, sysid);
- switch (srn->state) {
- case SRDB_STATE_NEW:
- case SRDB_STATE_MODIFIED:
- sr_debug("ISIS-Sr (%s): Create/Update SR node %s",
- area->area_tag, sysid_print(srn->sysid));
- if (adjacent)
- sr_node_srgb_update(area, level, sysid);
- break;
- case SRDB_STATE_UNCHANGED:
- break;
- default:
- /* SR capabilities have been removed. Delete SR-Node */
- sr_debug("ISIS-Sr (%s): Remove SR node %s", area->area_tag,
- sysid_print(srn->sysid));
-
- sr_node_del(area, level, srn);
- /* and Update remaining Prefix-SID from all remaining SR Node */
- if (adjacent)
- sr_node_srgb_update(area, level, sysid);
- return;
- }
-
- /* Validate SRDB State for next LSPDB parsing */
- srn->state = SRDB_STATE_VALIDATED;
-
- /* Finally, process all Prefix-SID of this SR Node */
- frr_each_safe (srdb_node_prefix, &srn->prefix_sids, srp)
- process_prefix_changes(srn, srp);
-}
-
/**
* Delete all backup Adj-SIDs.
*
@@ -1272,89 +466,6 @@ void isis_area_delete_backup_adj_sids(struct isis_area *area, int level)
sr_adj_sid_del(sra);
}
-/**
- * Parse and process all SR-related Sub-TLVs after running the SPF algorithm.
- *
- * @param area IS-IS area
- */
-void isis_area_verify_sr(struct isis_area *area)
-{
- struct sr_node *srn;
-
- if (!area->srdb.enabled)
- return;
-
- /* Parse LSPDB to detect new/deleted/modified SR (sub-)TLVs. */
- parse_lspdb(area);
-
- /* Process possible SR-related changes in the LDPSB. */
- for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) {
- frr_each_safe (srdb_node, &area->srdb.sr_nodes[level - 1], srn)
- process_node_changes(area, level, srn);
- }
-}
-
-/**
- * Once a route is updated in the SPT, reinstall or uninstall its corresponding
- * Prefix-SID (if any).
- *
- * @param area IS-IS area
- * @param prefix Prefix to be updated
- * @param route_info New Route Information
- *
- * @return 0
- */
-static int sr_route_update(struct isis_area *area, struct prefix *prefix,
- struct isis_route_info *route_info)
-{
- struct sr_prefix *srp;
-
- if (!area->srdb.enabled)
- return 0;
-
- sr_debug("ISIS-Sr (%s): Update route for prefix %pFX", area->area_tag,
- prefix);
-
- /* Lookup to Segment Routing Prefix for this prefix */
- switch (area->is_type) {
- case IS_LEVEL_1:
- srp = sr_prefix_find_by_area(area, ISIS_LEVEL1, prefix);
- break;
- case IS_LEVEL_2:
- srp = sr_prefix_find_by_area(area, ISIS_LEVEL2, prefix);
- break;
- case IS_LEVEL_1_AND_2:
- srp = sr_prefix_find_by_area(area, ISIS_LEVEL1, prefix);
- if (!srp)
- srp = sr_prefix_find_by_area(area, ISIS_LEVEL2, prefix);
- break;
- default:
- flog_err(EC_LIB_DEVELOPMENT, "%s: unknown area level",
- __func__);
- exit(1);
- }
-
- /* Skip NULL or local Segment Routing Prefix */
- if (!srp || srp->type == ISIS_SR_PREFIX_LOCAL)
- return 0;
-
- /* Install or unintall Prefix-SID if route is Active or not */
- if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE)) {
- /*
- * The Prefix-SID input label hasn't changed. We could use the
- * "Make Before Break" option. Zebra layer will update output
- * label by adding new label(s) before removing old one(s).
- */
- sr_prefix_reinstall(srp, true);
- srp->u.remote.rinfo = route_info;
- } else {
- sr_prefix_uninstall(srp);
- srp->u.remote.rinfo = NULL;
- }
-
- return 0;
-}
-
/* --- Segment Routing Local Block management functions --------------------- */
/**
@@ -1588,7 +699,7 @@ void sr_adj_sid_add_single(struct isis_adjacency *adj, int family, bool backup,
struct mpls_label_stack *label_stack;
label_stack = vadj->label_stack;
- adjinfo2nexthop(family, sra->backup_nexthops, adj,
+ adjinfo2nexthop(family, sra->backup_nexthops, adj, NULL,
label_stack);
}
}
@@ -1838,7 +949,7 @@ static int sr_if_new_hook(struct interface *ifp)
continue;
if (sr_prefix_is_node_sid(ifp, &pcfg->prefix)
- && !pcfg->node_sid) {
+ && !pcfg->n_flag_clear) {
pcfg->node_sid = true;
lsp_regenerate_schedule(area, area->is_type, 0);
}
@@ -1847,8 +958,6 @@ static int sr_if_new_hook(struct interface *ifp)
return 0;
}
-/* --- Segment Routing Show information functions --------------------------- */
-
/**
* Show LFIB operation in human readable format.
*
@@ -1856,13 +965,11 @@ static int sr_if_new_hook(struct interface *ifp)
* @param size Size of the buffer
* @param label_in Input Label
* @param label_out Output Label
- * @param label_stack Output Label Stack (TI-LFA)
*
* @return String containing LFIB operation in human readable format
*/
-static char *sr_op2str(char *buf, size_t size, mpls_label_t label_in,
- mpls_label_t label_out,
- const struct mpls_label_stack *label_stack)
+char *sr_op2str(char *buf, size_t size, mpls_label_t label_in,
+ mpls_label_t label_out)
{
if (size < 24)
return NULL;
@@ -1872,16 +979,6 @@ static char *sr_op2str(char *buf, size_t size, mpls_label_t label_in,
return buf;
}
- if (label_stack) {
- char buf_labels[256];
-
- mpls_label2str(label_stack->num_labels, &label_stack->label[0],
- buf_labels, sizeof(buf_labels), 1);
-
- snprintf(buf, size, "Swap(%u, %s)", label_in, buf_labels);
- return buf;
- }
-
switch (label_out) {
case MPLS_LABEL_IMPLICIT_NULL:
snprintf(buf, size, "Pop(%u)", label_in);
@@ -1901,215 +998,6 @@ static char *sr_op2str(char *buf, size_t size, mpls_label_t label_in,
}
/**
- * Show Local Prefix-SID.
- *
- * @param vty VTY output
- * @param tt Table format
- * @param area IS-IS area
- * @param srp Segment Routing Prefix
- */
-static void show_prefix_sid_local(struct vty *vty, struct ttable *tt,
- const struct isis_area *area,
- const struct sr_prefix *srp)
-{
- const struct sr_nexthop_info *srnh = &srp->u.local.info;
- char buf_prefix[BUFSIZ];
- char buf_oper[BUFSIZ];
- char buf_iface[BUFSIZ];
- char buf_uptime[BUFSIZ];
-
- if (srnh->label != MPLS_INVALID_LABEL) {
- struct interface *ifp;
- ifp = if_lookup_prefix(&srp->prefix, VRF_DEFAULT);
- if (ifp)
- strlcpy(buf_iface, ifp->name, sizeof(buf_iface));
- else
- snprintf(buf_iface, sizeof(buf_iface), "-");
- log_uptime(srnh->uptime, buf_uptime, sizeof(buf_uptime));
- } else {
- snprintf(buf_iface, sizeof(buf_iface), "-");
- snprintf(buf_uptime, sizeof(buf_uptime), "-");
- }
- sr_op2str(buf_oper, sizeof(buf_oper), srp->input_label,
- MPLS_LABEL_IMPLICIT_NULL, NULL);
-
- ttable_add_row(tt, "%s|%u|%s|-|%s|%s",
- prefix2str(&srp->prefix, buf_prefix, sizeof(buf_prefix)),
- srp->sid.value, buf_oper, buf_iface, buf_uptime);
-}
-
-/**
- * Show Remote Prefix-SID.
- *
- * @param vty VTY output
- * @param tt Table format
- * @param area IS-IS area
- * @param srp Segment Routing Prefix
- */
-static void show_prefix_sid_remote(struct vty *vty, struct ttable *tt,
- const struct isis_area *area,
- const struct sr_prefix *srp, bool backup)
-{
- struct isis_nexthop *nexthop;
- struct listnode *node;
- char buf_prefix[BUFSIZ];
- char buf_oper[BUFSIZ];
- char buf_nhop[BUFSIZ];
- char buf_iface[BUFSIZ];
- char buf_uptime[BUFSIZ];
- bool first = true;
- struct isis_route_info *rinfo;
-
- (void)prefix2str(&srp->prefix, buf_prefix, sizeof(buf_prefix));
-
- rinfo = srp->u.remote.rinfo;
- if (rinfo && backup)
- rinfo = rinfo->backup;
- if (!rinfo) {
- ttable_add_row(tt, "%s|%u|%s|-|-|-", buf_prefix, srp->sid.value,
- sr_op2str(buf_oper, sizeof(buf_oper),
- srp->input_label,
- MPLS_LABEL_IMPLICIT_NULL, NULL));
- return;
- }
-
- for (ALL_LIST_ELEMENTS_RO(rinfo->nexthops, node, nexthop)) {
- struct interface *ifp;
-
- inet_ntop(nexthop->family, &nexthop->ip, buf_nhop,
- sizeof(buf_nhop));
- ifp = if_lookup_by_index(nexthop->ifindex, VRF_DEFAULT);
- if (ifp)
- strlcpy(buf_iface, ifp->name, sizeof(buf_iface));
- else
- snprintf(buf_iface, sizeof(buf_iface), "ifindex %u",
- nexthop->ifindex);
- if (nexthop->sr.label == MPLS_INVALID_LABEL)
- snprintf(buf_uptime, sizeof(buf_uptime), "-");
- else
- log_uptime(nexthop->sr.uptime, buf_uptime,
- sizeof(buf_uptime));
- sr_op2str(buf_oper, sizeof(buf_oper), srp->input_label,
- nexthop->sr.label, nexthop->label_stack);
-
- if (first)
- ttable_add_row(tt, "%s|%u|%s|%s|%s|%s", buf_prefix,
- srp->sid.value, buf_oper, buf_nhop,
- buf_iface, buf_uptime);
- else
- ttable_add_row(tt, "|||%s|%s|%s|%s", buf_oper, buf_nhop,
- buf_iface, buf_uptime);
- first = false;
- }
-}
-
-/**
- * Show Prefix-SIDs.
- *
- * @param vty VTY output
- * @param area IS-IS area
- * @param level IS-IS level
- */
-static void show_prefix_sids(struct vty *vty, struct isis_area *area, int level,
- bool backup)
-{
- struct sr_prefix *srp;
- struct ttable *tt;
-
- if (srdb_area_prefix_count(&area->srdb.prefix_sids[level - 1]) == 0)
- return;
-
- vty_out(vty, " IS-IS %s Prefix-SIDs:\n\n", circuit_t2string(level));
-
- /* Prepare table. */
- tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
- ttable_add_row(tt, "Prefix|SID|Label Op.|Nexthop|Interface|Uptime");
- tt->style.cell.rpad = 2;
- tt->style.corner = '+';
- ttable_restyle(tt);
- ttable_rowseps(tt, 0, BOTTOM, true, '-');
-
- /* Process all Prefix-SID from the SRDB */
- frr_each (srdb_area_prefix, &area->srdb.prefix_sids[level - 1], srp) {
- switch (srp->type) {
- case ISIS_SR_PREFIX_LOCAL:
- show_prefix_sid_local(vty, tt, area, srp);
- break;
- case ISIS_SR_PREFIX_REMOTE:
- show_prefix_sid_remote(vty, tt, area, srp, backup);
- break;
- }
- }
-
- /* Dump the generated table. */
- if (tt->nrows > 1) {
- char *table;
-
- table = ttable_dump(tt, "\n");
- vty_out(vty, "%s\n", table);
- XFREE(MTYPE_TMP, table);
- }
- ttable_del(tt);
-}
-
-/**
- * Declaration of new show commands.
- */
-DEFUN(show_sr_prefix_sids, show_sr_prefix_sids_cmd,
- "show isis [vrf <NAME|all>] segment-routing prefix-sids [backup]",
- SHOW_STR PROTO_HELP VRF_CMD_HELP_STR
- "All VRFs\n"
- "Segment-Routing\n"
- "Segment-Routing Prefix-SIDs\n"
- "Show backup Prefix-SIDs\n")
-{
- struct listnode *node, *inode;
- struct isis_area *area;
- struct isis *isis = NULL;
- const char *vrf_name = VRF_DEFAULT_NAME;
- bool all_vrf = false;
- bool backup = false;
- int idx = 0;
-
- ISIS_FIND_VRF_ARGS(argv, argc, idx, vrf_name, all_vrf);
- if (argv_find(argv, argc, "backup", &idx))
- backup = true;
-
- if (vrf_name) {
- if (all_vrf) {
- for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) {
- for (ALL_LIST_ELEMENTS_RO(isis->area_list, node,
- area)) {
- vty_out(vty, "Area %s:\n",
- area->area_tag ? area->area_tag
- : "null");
- for (int level = ISIS_LEVEL1;
- level <= ISIS_LEVELS; level++)
- show_prefix_sids(vty, area,
- level, backup);
- }
- }
- return 0;
- }
- isis = isis_lookup_by_vrfname(vrf_name);
- if (isis != NULL) {
- for (ALL_LIST_ELEMENTS_RO(isis->area_list, node,
- area)) {
- vty_out(vty, "Area %s:\n",
- area->area_tag ? area->area_tag
- : "null");
- for (int level = ISIS_LEVEL1;
- level <= ISIS_LEVELS; level++)
- show_prefix_sids(vty, area, level,
- backup);
- }
- }
- }
-
- return CMD_SUCCESS;
-}
-
-/**
* Show Segment Routing Node.
*
* @param vty VTY output
@@ -2118,13 +1006,10 @@ DEFUN(show_sr_prefix_sids, show_sr_prefix_sids_cmd,
*/
static void show_node(struct vty *vty, struct isis_area *area, int level)
{
- struct sr_node *srn;
+ struct isis_lsp *lsp;
struct ttable *tt;
- if (srdb_area_prefix_count(&area->srdb.prefix_sids[level - 1]) == 0)
- return;
-
- vty_out(vty, " IS-IS %s SR-Node:\n\n", circuit_t2string(level));
+ vty_out(vty, " IS-IS %s SR-Nodes:\n\n", circuit_t2string(level));
/* Prepare table. */
tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
@@ -2134,19 +1019,23 @@ static void show_node(struct vty *vty, struct isis_area *area, int level)
ttable_restyle(tt);
ttable_rowseps(tt, 0, BOTTOM, true, '-');
- /* Process all SR-Node from the SRDB */
- frr_each (srdb_node, &area->srdb.sr_nodes[level - 1], srn) {
+ frr_each (lspdb, &area->lspdb[level - 1], lsp) {
+ struct isis_router_cap *cap;
+
+ if (!lsp->tlvs)
+ continue;
+ cap = lsp->tlvs->router_cap;
+ if (!cap)
+ continue;
+
ttable_add_row(
tt, "%s|%u - %u|%u - %u|%s|%u",
- sysid_print(srn->sysid),
- srn->cap.srgb.lower_bound,
- srn->cap.srgb.lower_bound + srn->cap.srgb.range_size
- - 1,
- srn->cap.srlb.lower_bound,
- srn->cap.srlb.lower_bound + srn->cap.srlb.range_size
- - 1,
- srn->cap.algo[0] == SR_ALGORITHM_SPF ? "SPF" : "S-SPF",
- srn->cap.msd);
+ sysid_print(lsp->hdr.lsp_id), cap->srgb.lower_bound,
+ cap->srgb.lower_bound + cap->srgb.range_size - 1,
+ cap->srlb.lower_bound,
+ cap->srlb.lower_bound + cap->srlb.range_size - 1,
+ cap->algo[0] == SR_ALGORITHM_SPF ? "SPF" : "S-SPF",
+ cap->msd);
}
/* Dump the generated table. */
@@ -2184,7 +1073,6 @@ DEFUN(show_sr_node, show_sr_node_cmd,
return CMD_SUCCESS;
}
-
/* --- IS-IS Segment Routing Management function ---------------------------- */
/**
@@ -2290,16 +1178,6 @@ void isis_sr_stop(struct isis_area *area)
for (ALL_LIST_ELEMENTS(area->srdb.adj_sids, node, nnode, sra))
sr_adj_sid_del(sra);
- /* Uninstall all Prefix-SIDs from all SR Node. */
- for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) {
- while (srdb_node_count(&srdb->sr_nodes[level - 1]) > 0) {
- struct sr_node *srn;
-
- srn = srdb_node_first(&srdb->sr_nodes[level - 1]);
- sr_node_del(area, level, srn);
- }
- }
-
/* Release SRGB if active. */
if (srdb->srgb_active) {
isis_zebra_release_label_range(srdb->config.srgb_lower_bound,
@@ -2332,11 +1210,6 @@ void isis_sr_area_init(struct isis_area *area)
memset(srdb, 0, sizeof(*srdb));
srdb->adj_sids = list_new();
- for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) {
- srdb_node_init(&srdb->sr_nodes[level - 1]);
- srdb_area_prefix_init(&srdb->prefix_sids[level - 1]);
- }
-
/* Pull defaults from the YANG module. */
#ifndef FABRICD
srdb->config.enabled = yang_get_default_bool("%s/enabled", ISIS_SR);
@@ -2386,14 +1259,12 @@ void isis_sr_area_term(struct isis_area *area)
*/
void isis_sr_init(void)
{
- install_element(VIEW_NODE, &show_sr_prefix_sids_cmd);
install_element(VIEW_NODE, &show_sr_node_cmd);
/* Register hooks. */
hook_register(isis_adj_state_change_hook, sr_adj_state_change);
hook_register(isis_adj_ip_enabled_hook, sr_adj_ip_enabled);
hook_register(isis_adj_ip_disabled_hook, sr_adj_ip_disabled);
- hook_register(isis_route_update_hook, sr_route_update);
hook_register(isis_if_new_hook, sr_if_new_hook);
}
@@ -2406,6 +1277,5 @@ void isis_sr_term(void)
hook_unregister(isis_adj_state_change_hook, sr_adj_state_change);
hook_unregister(isis_adj_ip_enabled_hook, sr_adj_ip_enabled);
hook_unregister(isis_adj_ip_disabled_hook, sr_adj_ip_disabled);
- hook_unregister(isis_route_update_hook, sr_route_update);
hook_unregister(isis_if_new_hook, sr_if_new_hook);
}