isisd: add support for Anycast-SIDs

Add the "n-flag-clear" option to the "segment-routing prefix"
command. The only thing that option does is to clear the node
flag of the Prefix-SID, even if it corresponds to a local loopback
address. No changes are necessary other than that in order to fully
support Anycast-SIDs.  isisd already supports multiple routers
advertising the same route with the same Prefix-SID after the recent
refactoring. Clearing the node flag for such anycast routes isn't
strictly required, but failure to do so can lead to problems like
TI-LFA picking the wrong Prefix-SID when calculating repair paths.

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
Renato Westphal 2020-09-20 02:42:32 -03:00
parent 4c75f7c773
commit 01983712cc
8 changed files with 54 additions and 9 deletions

View File

@ -515,14 +515,16 @@ Known limitations:
MPLS dataplane. E.g. for Linux kernel, since version 4.13 the maximum value MPLS dataplane. E.g. for Linux kernel, since version 4.13 the maximum value
is 32. is 32.
.. index:: [no] segment-routing prefix <A.B.C.D/M|X:X::X:X/M> <absolute (16-1048575)|index (0-65535)> [no-php-flag|explicit-null] .. index:: [no] segment-routing prefix <A.B.C.D/M|X:X::X:X/M> <absolute (16-1048575)|index (0-65535)> [no-php-flag|explicit-null] [n-flag-clear]
.. clicmd:: [no] segment-routing prefix <A.B.C.D/M|X:X::X:X/M> <absolute (16-1048575)|index (0-65535) [no-php-flag|explicit-null] .. clicmd:: [no] segment-routing prefix <A.B.C.D/M|X:X::X:X/M> <absolute (16-1048575)|index (0-65535) [no-php-flag|explicit-null] [n-flag-clear]
Set the Segment Routing index or absolute label value for the specified Set the Segment Routing index or absolute label value for the specified
prefix. The 'no-php-flag' means NO Penultimate Hop Popping that allows SR prefix. The 'no-php-flag' means NO Penultimate Hop Popping that allows SR
node to request to its neighbor to not pop the label. The 'explicit-null' node to request to its neighbor to not pop the label. The 'explicit-null'
flag allows SR node to request to its neighbor to send IP packet with the flag allows SR node to request to its neighbor to send IP packet with the
EXPLICIT-NULL label. EXPLICIT-NULL label. The 'n-flag-clear' option can be used to explicitly
clear the Node flag that is set by default for Prefix-SIDs associated to
loopback addresses. This option is necessary to configure Anycast-SIDs.
.. index:: show isis segment-routing prefix-sids .. index:: show isis segment-routing prefix-sids
.. clicmd:: show isis segment-routing prefix-sids .. clicmd:: show isis segment-routing prefix-sids

View File

@ -1628,7 +1628,7 @@ DEFPY_YANG (isis_sr_prefix_sid,
"segment-routing prefix\ "segment-routing prefix\
<A.B.C.D/M|X:X::X:X/M>$prefix\ <A.B.C.D/M|X:X::X:X/M>$prefix\
<absolute$sid_type (16-1048575)$sid_value|index$sid_type (0-65535)$sid_value>\ <absolute$sid_type (16-1048575)$sid_value|index$sid_type (0-65535)$sid_value>\
[<no-php-flag|explicit-null>$lh_behavior]", [<no-php-flag|explicit-null>$lh_behavior] [n-flag-clear$n_flag_clear]",
SR_STR SR_STR
"Prefix SID\n" "Prefix SID\n"
"IPv4 Prefix\n" "IPv4 Prefix\n"
@ -1638,7 +1638,8 @@ DEFPY_YANG (isis_sr_prefix_sid,
"Specify the index of Prefix Segement ID\n" "Specify the index of Prefix Segement ID\n"
"The Prefix Segment ID index\n" "The Prefix Segment ID index\n"
"Don't request Penultimate Hop Popping (PHP)\n" "Don't request Penultimate Hop Popping (PHP)\n"
"Upstream neighbor must replace prefix-sid with explicit null label\n") "Upstream neighbor must replace prefix-sid with explicit null label\n"
"Not a node SID\n")
{ {
nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
nb_cli_enqueue_change(vty, "./sid-value-type", NB_OP_MODIFY, sid_type); nb_cli_enqueue_change(vty, "./sid-value-type", NB_OP_MODIFY, sid_type);
@ -1656,6 +1657,8 @@ DEFPY_YANG (isis_sr_prefix_sid,
} else } else
nb_cli_enqueue_change(vty, "./last-hop-behavior", NB_OP_MODIFY, nb_cli_enqueue_change(vty, "./last-hop-behavior", NB_OP_MODIFY,
NULL); NULL);
nb_cli_enqueue_change(vty, "./n-flag-clear", NB_OP_MODIFY,
n_flag_clear ? "true" : "false");
return nb_cli_apply_changes( return nb_cli_apply_changes(
vty, "./segment-routing/prefix-sid-map/prefix-sid[prefix='%s']", vty, "./segment-routing/prefix-sid-map/prefix-sid[prefix='%s']",
@ -1665,7 +1668,8 @@ DEFPY_YANG (isis_sr_prefix_sid,
DEFPY_YANG (no_isis_sr_prefix_sid, DEFPY_YANG (no_isis_sr_prefix_sid,
no_isis_sr_prefix_sid_cmd, no_isis_sr_prefix_sid_cmd,
"no segment-routing prefix <A.B.C.D/M|X:X::X:X/M>$prefix\ "no segment-routing prefix <A.B.C.D/M|X:X::X:X/M>$prefix\
[<absolute$sid_type (16-1048575)|index (0-65535)> [<no-php-flag|explicit-null>]]", [<absolute$sid_type (16-1048575)|index (0-65535)> [<no-php-flag|explicit-null>]]\
[n-flag-clear]",
NO_STR NO_STR
SR_STR SR_STR
"Prefix SID\n" "Prefix SID\n"
@ -1676,7 +1680,8 @@ DEFPY_YANG (no_isis_sr_prefix_sid,
"Specify the index of Prefix Segement ID\n" "Specify the index of Prefix Segement ID\n"
"The Prefix Segment ID index\n" "The Prefix Segment ID index\n"
"Don't request Penultimate Hop Popping (PHP)\n" "Don't request Penultimate Hop Popping (PHP)\n"
"Upstream neighbor must replace prefix-sid with explicit null label\n") "Upstream neighbor must replace prefix-sid with explicit null label\n"
"Not a node SID\n")
{ {
nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
@ -1692,11 +1697,13 @@ void cli_show_isis_prefix_sid(struct vty *vty, struct lyd_node *dnode,
const char *lh_behavior; const char *lh_behavior;
const char *sid_value_type; const char *sid_value_type;
const char *sid_value; const char *sid_value;
bool n_flag_clear;
prefix = yang_dnode_get_string(dnode, "./prefix"); prefix = yang_dnode_get_string(dnode, "./prefix");
lh_behavior = yang_dnode_get_string(dnode, "./last-hop-behavior"); lh_behavior = yang_dnode_get_string(dnode, "./last-hop-behavior");
sid_value_type = yang_dnode_get_string(dnode, "./sid-value-type"); sid_value_type = yang_dnode_get_string(dnode, "./sid-value-type");
sid_value = yang_dnode_get_string(dnode, "./sid-value"); sid_value = yang_dnode_get_string(dnode, "./sid-value");
n_flag_clear = yang_dnode_get_bool(dnode, "./n-flag-clear");
vty_out(vty, " segment-routing prefix %s", prefix); vty_out(vty, " segment-routing prefix %s", prefix);
if (strmatch(sid_value_type, "absolute")) if (strmatch(sid_value_type, "absolute"))
@ -1708,6 +1715,8 @@ void cli_show_isis_prefix_sid(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, " no-php-flag"); vty_out(vty, " no-php-flag");
else if (strmatch(lh_behavior, "explicit-null")) else if (strmatch(lh_behavior, "explicit-null"))
vty_out(vty, " explicit-null"); vty_out(vty, " explicit-null");
if (n_flag_clear)
vty_out(vty, " n-flag-clear");
vty_out(vty, "\n"); vty_out(vty, "\n");
} }

View File

@ -537,6 +537,12 @@ const struct frr_yang_module_info frr_isisd_info = {
.modify = isis_instance_segment_routing_prefix_sid_map_prefix_sid_last_hop_behavior_modify, .modify = isis_instance_segment_routing_prefix_sid_map_prefix_sid_last_hop_behavior_modify,
}, },
}, },
{
.xpath = "/frr-isisd:isis/instance/segment-routing/prefix-sid-map/prefix-sid/n-flag-clear",
.cbs = {
.modify = isis_instance_segment_routing_prefix_sid_map_prefix_sid_n_flag_clear_modify,
}
},
{ {
.xpath = "/frr-isisd:isis/instance/mpls/ldp-sync", .xpath = "/frr-isisd:isis/instance/mpls/ldp-sync",
.cbs = { .cbs = {

View File

@ -206,6 +206,8 @@ int isis_instance_segment_routing_prefix_sid_map_prefix_sid_sid_value_modify(
struct nb_cb_modify_args *args); struct nb_cb_modify_args *args);
int isis_instance_segment_routing_prefix_sid_map_prefix_sid_last_hop_behavior_modify( int isis_instance_segment_routing_prefix_sid_map_prefix_sid_last_hop_behavior_modify(
struct nb_cb_modify_args *args); struct nb_cb_modify_args *args);
int isis_instance_segment_routing_prefix_sid_map_prefix_sid_n_flag_clear_modify(
struct nb_cb_modify_args *args);
int isis_instance_mpls_ldp_sync_destroy(struct nb_cb_destroy_args *args); int isis_instance_mpls_ldp_sync_destroy(struct nb_cb_destroy_args *args);
int isis_instance_mpls_ldp_sync_create(struct nb_cb_create_args *args); int isis_instance_mpls_ldp_sync_create(struct nb_cb_create_args *args);
int isis_instance_mpls_ldp_sync_holddown_modify(struct nb_cb_modify_args *args); int isis_instance_mpls_ldp_sync_holddown_modify(struct nb_cb_modify_args *args);

View File

@ -1837,6 +1837,23 @@ int isis_instance_segment_routing_prefix_sid_map_prefix_sid_last_hop_behavior_mo
return NB_OK; return NB_OK;
} }
/*
* XPath: /frr-isisd:isis/instance/segment-routing/prefix-sid-map/prefix-sid/n-flag-clear
*/
int isis_instance_segment_routing_prefix_sid_map_prefix_sid_n_flag_clear_modify(
struct nb_cb_modify_args *args)
{
struct sr_prefix_cfg *pcfg;
if (args->event != NB_EV_APPLY)
return NB_OK;
pcfg = nb_running_get_entry(args->dnode, NULL, true);
pcfg->n_flag_clear = yang_dnode_get_bool(args->dnode, NULL);
return NB_OK;
}
/* /*
* XPath: /frr-isisd:isis/instance/mpls/ldp-sync * XPath: /frr-isisd:isis/instance/mpls/ldp-sync
*/ */

View File

@ -363,7 +363,7 @@ struct sr_prefix_cfg *isis_sr_cfg_prefix_add(struct isis_area *area,
/* Set the N-flag when appropriate. */ /* Set the N-flag when appropriate. */
ifp = if_lookup_prefix(prefix, VRF_DEFAULT); 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; pcfg->node_sid = true;
/* Save prefix-sid configuration. */ /* Save prefix-sid configuration. */
@ -949,7 +949,7 @@ static int sr_if_new_hook(struct interface *ifp)
continue; continue;
if (sr_prefix_is_node_sid(ifp, &pcfg->prefix) if (sr_prefix_is_node_sid(ifp, &pcfg->prefix)
&& !pcfg->node_sid) { && !pcfg->n_flag_clear) {
pcfg->node_sid = true; pcfg->node_sid = true;
lsp_regenerate_schedule(area, area->is_type, 0); lsp_regenerate_schedule(area, area->is_type, 0);
} }

View File

@ -152,6 +152,9 @@ struct sr_prefix_cfg {
/* SID last hop behavior. */ /* SID last hop behavior. */
enum sr_last_hop_behavior last_hop_behavior; enum sr_last_hop_behavior last_hop_behavior;
/* Indicates whether the node flag must be explicitly unset. */
bool n_flag_clear;
/* Does this Prefix-SID refer to a loopback address (Node-SID)? */ /* Does this Prefix-SID refer to a loopback address (Node-SID)? */
bool node_sid; bool node_sid;

View File

@ -1381,6 +1381,12 @@ module frr-isisd {
description description
"Configure last hop behavior."; "Configure last hop behavior.";
} }
leaf n-flag-clear {
type boolean;
default "false";
description
"Not a node SID";
}
} }
} }
} }