isisd,yang: add algorithm-prefix-sid configuration tree

Add the ability to configure a Segment-Routing prefix SID for a given
algorithm. For example:

> segment-routing prefix 10.10.10.10/32 algorithm 128 index 100

Signed-off-by: Hiroki Shirokura <hiroki.shirokura@linecorp.com>
Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
This commit is contained in:
Hiroki Shirokura 2021-12-12 11:56:44 +00:00 committed by Louis Scalbert
parent d4f58e0b84
commit cc4926c128
5 changed files with 380 additions and 0 deletions

View file

@ -1769,6 +1769,44 @@ void cli_show_isis_prefix_sid(struct vty *vty, const struct lyd_node *dnode,
vty_out(vty, "\n");
}
/*
* XPath:
* /frr-isisd:isis/instance/segment-routing/algorithm-prefix-sids/algorithm-prefix-sid
*/
void cli_show_isis_prefix_sid_algorithm(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults)
{
const char *prefix;
const char *lh_behavior;
const char *sid_value_type;
const char *sid_value;
bool n_flag_clear;
uint32_t algorithm;
prefix = yang_dnode_get_string(dnode, "./prefix");
sid_value_type = yang_dnode_get_string(dnode, "./sid-value-type");
sid_value = yang_dnode_get_string(dnode, "./sid-value");
algorithm = yang_dnode_get_uint32(dnode, "./algo");
lh_behavior = yang_dnode_get_string(dnode, "./last-hop-behavior");
n_flag_clear = yang_dnode_get_bool(dnode, "./n-flag-clear");
vty_out(vty, " segment-routing prefix %s", prefix);
vty_out(vty, " algorithm %u", algorithm);
if (strmatch(sid_value_type, "absolute"))
vty_out(vty, " absolute");
else
vty_out(vty, " index");
vty_out(vty, " %s", sid_value);
if (strmatch(lh_behavior, "no-php"))
vty_out(vty, " no-php-flag");
else if (strmatch(lh_behavior, "explicit-null"))
vty_out(vty, " explicit-null");
if (n_flag_clear)
vty_out(vty, " n-flag-clear");
vty_out(vty, "\n");
}
/*
* XPath: /frr-isisd:isis/instance/fast-reroute/level-{1,2}/lfa/priority-limit

View file

@ -688,6 +688,40 @@ const struct frr_yang_module_info frr_isisd_info = {
.modify = isis_instance_segment_routing_prefix_sid_map_prefix_sid_n_flag_clear_modify,
}
},
{
.xpath = "/frr-isisd:isis/instance/segment-routing/algorithm-prefix-sids/algorithm-prefix-sid",
.cbs = {
.create = isis_instance_segment_routing_algorithm_prefix_sid_create,
.destroy = isis_instance_segment_routing_algorithm_prefix_sid_destroy,
.pre_validate = isis_instance_segment_routing_algorithm_prefix_sid_pre_validate,
.apply_finish = isis_instance_segment_routing_algorithm_prefix_sid_apply_finish,
.cli_show = cli_show_isis_prefix_sid_algorithm,
},
},
{
.xpath = "/frr-isisd:isis/instance/segment-routing/algorithm-prefix-sids/algorithm-prefix-sid/sid-value-type",
.cbs = {
.modify = isis_instance_segment_routing_algorithm_prefix_sid_sid_value_type_modify,
},
},
{
.xpath = "/frr-isisd:isis/instance/segment-routing/algorithm-prefix-sids/algorithm-prefix-sid/sid-value",
.cbs = {
.modify = isis_instance_segment_routing_algorithm_prefix_sid_sid_value_modify,
},
},
{
.xpath = "/frr-isisd:isis/instance/segment-routing/algorithm-prefix-sids/algorithm-prefix-sid/last-hop-behavior",
.cbs = {
.modify = isis_instance_segment_routing_algorithm_prefix_sid_last_hop_behavior_modify,
},
},
{
.xpath = "/frr-isisd:isis/instance/segment-routing/algorithm-prefix-sids/algorithm-prefix-sid/n-flag-clear",
.cbs = {
.modify = isis_instance_segment_routing_algorithm_prefix_sid_n_flag_clear_modify,
},
},
{
.xpath = "/frr-isisd:isis/instance/mpls/ldp-sync",
.cbs = {

View file

@ -249,6 +249,22 @@ int isis_instance_segment_routing_prefix_sid_map_prefix_sid_last_hop_behavior_mo
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_segment_routing_algorithm_prefix_sid_create(
struct nb_cb_create_args *args);
int isis_instance_segment_routing_algorithm_prefix_sid_destroy(
struct nb_cb_destroy_args *args);
int isis_instance_segment_routing_algorithm_prefix_sid_pre_validate(
struct nb_cb_pre_validate_args *args);
void isis_instance_segment_routing_algorithm_prefix_sid_apply_finish(
struct nb_cb_apply_finish_args *args);
int isis_instance_segment_routing_algorithm_prefix_sid_sid_value_type_modify(
struct nb_cb_modify_args *args);
int isis_instance_segment_routing_algorithm_prefix_sid_sid_value_modify(
struct nb_cb_modify_args *args);
int isis_instance_segment_routing_algorithm_prefix_sid_last_hop_behavior_modify(
struct nb_cb_modify_args *args);
int isis_instance_segment_routing_algorithm_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_create(struct nb_cb_create_args *args);
int isis_instance_mpls_ldp_sync_holddown_modify(struct nb_cb_modify_args *args);
@ -538,6 +554,9 @@ void cli_show_isis_node_msd(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
void cli_show_isis_prefix_sid(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
void cli_show_isis_prefix_sid_algorithm(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults);
void cli_show_isis_frr_lfa_priority_limit(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults);

View file

@ -2466,6 +2466,214 @@ int isis_instance_segment_routing_prefix_sid_map_prefix_sid_n_flag_clear_modify(
return NB_OK;
}
/*
* XPath:
* /frr-isisd:isis/instance/segment-routing/algorithm-prefix-sids/algorithm-prefix-sid
*/
int isis_instance_segment_routing_algorithm_prefix_sid_create(
struct nb_cb_create_args *args)
{
struct isis_area *area;
struct prefix prefix;
struct sr_prefix_cfg *pcfg;
uint32_t algorithm;
if (args->event != NB_EV_APPLY)
return NB_OK;
area = nb_running_get_entry(args->dnode, NULL, true);
yang_dnode_get_prefix(&prefix, args->dnode, "./prefix");
algorithm = yang_dnode_get_uint32(args->dnode, "./algo");
pcfg = isis_sr_cfg_prefix_add(area, &prefix, algorithm);
pcfg->algorithm = algorithm;
nb_running_set_entry(args->dnode, pcfg);
return NB_OK;
}
int isis_instance_segment_routing_algorithm_prefix_sid_destroy(
struct nb_cb_destroy_args *args)
{
struct sr_prefix_cfg *pcfg;
struct isis_area *area;
if (args->event != NB_EV_APPLY)
return NB_OK;
pcfg = nb_running_unset_entry(args->dnode);
area = pcfg->area;
isis_sr_cfg_prefix_del(pcfg);
lsp_regenerate_schedule(area, area->is_type, 0);
return NB_OK;
}
int isis_instance_segment_routing_algorithm_prefix_sid_pre_validate(
struct nb_cb_pre_validate_args *args)
{
const struct lyd_node *area_dnode;
struct isis_area *area;
struct prefix prefix;
uint32_t srgb_lbound;
uint32_t srgb_ubound;
uint32_t srgb_range;
uint32_t sid;
enum sr_sid_value_type sid_type;
struct isis_prefix_sid psid = {};
yang_dnode_get_prefix(&prefix, args->dnode, "./prefix");
srgb_lbound = yang_dnode_get_uint32(
args->dnode, "../../label-blocks/srgb/lower-bound");
srgb_ubound = yang_dnode_get_uint32(
args->dnode, "../../label-blocks/srgb/upper-bound");
sid = yang_dnode_get_uint32(args->dnode, "./sid-value");
sid_type = yang_dnode_get_enum(args->dnode, "./sid-value-type");
/* Check for invalid indexes/labels. */
srgb_range = srgb_ubound - srgb_lbound + 1;
psid.value = sid;
switch (sid_type) {
case SR_SID_VALUE_TYPE_INDEX:
if (sid >= srgb_range) {
snprintf(args->errmsg, args->errmsg_len,
"SID index %u falls outside local SRGB range",
sid);
return NB_ERR_VALIDATION;
}
break;
case SR_SID_VALUE_TYPE_ABSOLUTE:
if (!IS_MPLS_UNRESERVED_LABEL(sid)) {
snprintf(args->errmsg, args->errmsg_len,
"Invalid absolute SID %u", sid);
return NB_ERR_VALIDATION;
}
SET_FLAG(psid.flags, ISIS_PREFIX_SID_VALUE);
SET_FLAG(psid.flags, ISIS_PREFIX_SID_LOCAL);
break;
}
/* Check for Prefix-SID collisions. */
area_dnode = yang_dnode_get_parent(args->dnode, "instance");
area = nb_running_get_entry(area_dnode, NULL, false);
if (!area)
return NB_OK;
for (int tree = SPFTREE_IPV4; tree < SPFTREE_COUNT; tree++) {
for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
struct isis_spftree *spftree;
struct isis_vertex *vertex_psid;
if (!(area->is_type & level))
continue;
spftree = area->spftree[tree][level - 1];
if (!spftree)
continue;
vertex_psid =
isis_spf_prefix_sid_lookup(spftree, &psid);
if (vertex_psid &&
!prefix_same(&vertex_psid->N.ip.p.dest, &prefix)) {
snprintfrr(
args->errmsg, args->errmsg_len,
"Prefix-SID collision detected, SID %s %u is already in use by prefix %pFX (L%u)",
CHECK_FLAG(psid.flags,
ISIS_PREFIX_SID_VALUE)
? "label"
: "index",
psid.value, &vertex_psid->N.ip.p.dest,
level);
return NB_ERR_VALIDATION;
}
}
}
return NB_OK;
}
void isis_instance_segment_routing_algorithm_prefix_sid_apply_finish(
struct nb_cb_apply_finish_args *args)
{
struct sr_prefix_cfg *pcfg;
struct isis_area *area;
pcfg = nb_running_get_entry(args->dnode, NULL, true);
area = pcfg->area;
lsp_regenerate_schedule(area, area->is_type, 0);
}
/*
* XPath:
* /frr-isisd:isis/instance/segment-routing/algorithm-prefix-sids/algorithm-prefix-sid/sid-value-type
*/
int isis_instance_segment_routing_algorithm_prefix_sid_sid_value_type_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->sid_type = yang_dnode_get_enum(args->dnode, NULL);
return NB_OK;
}
/*
* XPath:
* /frr-isisd:isis/instance/segment-routing/algorithm-prefix-sids/algorithm-prefix-sid/sid-value
*/
int isis_instance_segment_routing_algorithm_prefix_sid_sid_value_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->sid = yang_dnode_get_uint32(args->dnode, NULL);
return NB_OK;
}
/*
* XPath:
* /frr-isisd:isis/instance/segment-routing/algorithm-prefix-sid-map/algorithm-prefix-sid/last-hop-behavior
*/
int isis_instance_segment_routing_algorithm_prefix_sid_last_hop_behavior_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->last_hop_behavior = yang_dnode_get_enum(args->dnode, NULL);
return NB_OK;
}
/*
* XPath:
* /frr-isisd:isis/instance/segment-routing/algorithm-prefix-sids/algorithm-prefix-sid/n-flag-clear
*/
int isis_instance_segment_routing_algorithm_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
*/

View file

@ -1751,6 +1751,87 @@ module frr-isisd {
}
}
}
container algorithm-prefix-sids {
description
"Algorithm SID Table";
list algorithm-prefix-sid {
key "prefix algo";
description
"Assign prefix SID for algorithm to an
interface, ISISPHPFlag will be rejected
if set to disable, ISISEXPLICITNULLFlag
will override the value of ISISPHPFlag";
leaf algo {
type uint32 {
range "128..255";
}
description
"Algorithm";
}
leaf prefix {
type inet:ip-prefix;
mandatory true;
description
"Connected prefix sid.";
}
leaf sid-value-type {
type enumeration {
enum "index" {
value 0;
description
"The value will be interpreted as an index.";
}
enum "absolute" {
value 1;
description
"The value will become interpreted as an absolute
value.";
}
}
default "index";
description
"This leaf defines how value must be interpreted.";
}
leaf sid-value {
type uint32 {
range "0..1048575";
}
mandatory true;
description
"Value associated with prefix. The value must be
interpreted in the context of sid-value-type.";
}
leaf last-hop-behavior {
type enumeration {
enum "explicit-null" {
value 0;
description
"Use explicit-null for the SID.";
}
enum "no-php" {
value 1;
description
"Do not use Penultimate Hop Popping (PHP)
for the SID.";
}
enum "php" {
value 2;
description
"Use PHP for the SID.";
}
}
default "php";
description
"Configure last hop behavior.";
}
leaf n-flag-clear {
type boolean;
default "false";
description
"Not a node SID";
}
}
}
}
container mpls {