summaryrefslogtreecommitdiffstats
path: root/isisd/isis_nb_config.c
diff options
context:
space:
mode:
authorRenato Westphal <renato@opensourcerouting.org>2019-08-04 03:02:37 +0200
committerOlivier Dugeon <olivier.dugeon@orange.com>2020-04-30 12:15:47 +0200
commit26f6acafc369f1c126870b4282d5e252cc830f26 (patch)
treea61a225ed9eddcd972abf6216e533606e559789c /isisd/isis_nb_config.c
parentisisd: add segment-routing CLI commands (diff)
downloadfrr-26f6acafc369f1c126870b4282d5e252cc830f26.tar.xz
frr-26f6acafc369f1c126870b4282d5e252cc830f26.zip
isisd: add support for segment routing
This is an implementation of the IS-IS SR draft [1] for FRR. The following features are supported: * IPv4 and IPv6 Prefix-SIDs; * IPv4 and IPv6 Adj-SIDs and LAN-Adj-SIDs; * Index and absolute labels; * The no-php and explicit-null Prefix-SID flags; * Full integration with the Label Manager. Known limitations: * No support for Anycast-SIDs; * No support for the SID/Label Binding TLV (required for LDP interop). * No support for persistent Adj-SIDs; * No support for multiple SRGBs. [1] draft-ietf-isis-segment-routing-extensions-25 Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com> Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Diffstat (limited to 'isisd/isis_nb_config.c')
-rw-r--r--isisd/isis_nb_config.c262
1 files changed, 178 insertions, 84 deletions
diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c
index f97202c9a..ec3b7baa3 100644
--- a/isisd/isis_nb_config.c
+++ b/isisd/isis_nb_config.c
@@ -1405,35 +1405,78 @@ int isis_instance_mpls_te_router_address_destroy(
/*
* XPath: /frr-isisd:isis/instance/segment-routing/enabled
*/
-int isis_instance_segment_routing_enabled_modify(enum nb_event event,
- const struct lyd_node *dnode,
- union nb_resource *resource)
+int isis_instance_segment_routing_enabled_modify(
+ struct nb_cb_modify_args *args)
{
- switch (event) {
- case NB_EV_VALIDATE:
- case NB_EV_PREPARE:
- case NB_EV_ABORT:
- case NB_EV_APPLY:
- /* TODO: implement me. */
- break;
+ struct isis_area *area;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ area = nb_running_get_entry(args->dnode, NULL, true);
+ area->srdb.config.enabled = yang_dnode_get_bool(args->dnode, NULL);
+
+ if (area->srdb.config.enabled) {
+ if (IS_DEBUG_ISIS(DEBUG_EVENTS))
+ zlog_debug("SR: Segment Routing: OFF -> ON");
+
+ if (isis_sr_start(area) == 0)
+ area->srdb.enabled = true;
+ } else {
+ if (IS_DEBUG_ISIS(DEBUG_EVENTS))
+ zlog_debug("SR: Segment Routing: ON -> OFF");
+
+ isis_sr_stop(area);
+ area->srdb.enabled = false;
}
return NB_OK;
}
/*
+ * XPath: /frr-isisd:isis/instance/segment-routing/srgb
+ */
+void isis_instance_segment_routing_srgb_apply_finish(
+ struct nb_cb_apply_finish_args *args)
+{
+ struct isis_area *area;
+ uint32_t lower_bound, upper_bound;
+ int ret;
+
+ area = nb_running_get_entry(args->dnode, NULL, true);
+ lower_bound = yang_dnode_get_uint32(args->dnode, "./lower-bound");
+ upper_bound = yang_dnode_get_uint32(args->dnode, "./upper-bound");
+
+ ret = isis_sr_cfg_srgb_update(area, lower_bound, upper_bound);
+ if (area->srdb.config.enabled) {
+ if (ret == 0)
+ area->srdb.enabled = true;
+ else {
+ isis_sr_stop(area);
+ area->srdb.enabled = false;
+ }
+ }
+}
+
+/*
* XPath: /frr-isisd:isis/instance/segment-routing/srgb/lower-bound
*/
int isis_instance_segment_routing_srgb_lower_bound_modify(
- enum nb_event event, const struct lyd_node *dnode,
- union nb_resource *resource)
+ struct nb_cb_modify_args *args)
{
- switch (event) {
+ uint32_t lower_bound = yang_dnode_get_uint32(args->dnode, NULL);
+
+ switch (args->event) {
case NB_EV_VALIDATE:
+ if (!IS_MPLS_UNRESERVED_LABEL(lower_bound)) {
+ zlog_warn("Invalid SRGB lower bound: %" PRIu32,
+ lower_bound);
+ return NB_ERR_VALIDATION;
+ }
+ break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
- /* TODO: implement me. */
break;
}
@@ -1444,15 +1487,21 @@ int isis_instance_segment_routing_srgb_lower_bound_modify(
* XPath: /frr-isisd:isis/instance/segment-routing/srgb/upper-bound
*/
int isis_instance_segment_routing_srgb_upper_bound_modify(
- enum nb_event event, const struct lyd_node *dnode,
- union nb_resource *resource)
+ struct nb_cb_modify_args *args)
{
- switch (event) {
+ uint32_t upper_bound = yang_dnode_get_uint32(args->dnode, NULL);
+
+ switch (args->event) {
case NB_EV_VALIDATE:
+ if (!IS_MPLS_UNRESERVED_LABEL(upper_bound)) {
+ zlog_warn("Invalid SRGB upper bound: %" PRIu32,
+ upper_bound);
+ return NB_ERR_VALIDATION;
+ }
+ break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
- /* TODO: implement me. */
break;
}
@@ -1463,32 +1512,31 @@ int isis_instance_segment_routing_srgb_upper_bound_modify(
* XPath: /frr-isisd:isis/instance/segment-routing/msd/node-msd
*/
int isis_instance_segment_routing_msd_node_msd_modify(
- enum nb_event event, const struct lyd_node *dnode,
- union nb_resource *resource)
+ struct nb_cb_modify_args *args)
{
- switch (event) {
- case NB_EV_VALIDATE:
- case NB_EV_PREPARE:
- case NB_EV_ABORT:
- case NB_EV_APPLY:
- /* TODO: implement me. */
- break;
- }
+ struct isis_area *area;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ area = nb_running_get_entry(args->dnode, NULL, true);
+ area->srdb.config.msd = yang_dnode_get_uint8(args->dnode, NULL);
+ isis_sr_cfg_msd_update(area);
return NB_OK;
}
int isis_instance_segment_routing_msd_node_msd_destroy(
- enum nb_event event, const struct lyd_node *dnode)
+ struct nb_cb_destroy_args *args)
{
- switch (event) {
- case NB_EV_VALIDATE:
- case NB_EV_PREPARE:
- case NB_EV_ABORT:
- case NB_EV_APPLY:
- /* TODO: implement me. */
- break;
- }
+ struct isis_area *area;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ area = nb_running_get_entry(args->dnode, NULL, true);
+ area->srdb.config.msd = 0;
+ isis_sr_cfg_msd_update(area);
return NB_OK;
}
@@ -1497,52 +1545,102 @@ int isis_instance_segment_routing_msd_node_msd_destroy(
* XPath: /frr-isisd:isis/instance/segment-routing/prefix-sid-map/prefix-sid
*/
int isis_instance_segment_routing_prefix_sid_map_prefix_sid_create(
- enum nb_event event, const struct lyd_node *dnode,
- union nb_resource *resource)
+ struct nb_cb_create_args *args)
{
- switch (event) {
- case NB_EV_VALIDATE:
- case NB_EV_PREPARE:
- case NB_EV_ABORT:
- case NB_EV_APPLY:
- /* TODO: implement me. */
- break;
- }
+ struct isis_area *area;
+ struct prefix prefix;
+ struct sr_prefix_cfg *pcfg;
+
+ 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");
+
+ pcfg = isis_sr_cfg_prefix_add(area, &prefix);
+ nb_running_set_entry(args->dnode, pcfg);
return NB_OK;
}
int isis_instance_segment_routing_prefix_sid_map_prefix_sid_destroy(
- enum nb_event event, const struct lyd_node *dnode)
+ struct nb_cb_destroy_args *args)
{
- switch (event) {
- case NB_EV_VALIDATE:
- case NB_EV_PREPARE:
- case NB_EV_ABORT:
- case NB_EV_APPLY:
- /* TODO: implement me. */
+ 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_prefix_sid_map_prefix_sid_pre_validate(
+ struct nb_cb_pre_validate_args *args)
+{
+ uint32_t srgb_lbound;
+ uint32_t srgb_ubound;
+ uint32_t srgb_range;
+ uint32_t sid;
+ enum sr_sid_value_type sid_type;
+
+ srgb_lbound = yang_dnode_get_uint32(args->dnode,
+ "../../srgb/lower-bound");
+ srgb_ubound = yang_dnode_get_uint32(args->dnode,
+ "../../srgb/upper-bound");
+ sid = yang_dnode_get_uint32(args->dnode, "./sid-value");
+ sid_type = yang_dnode_get_enum(args->dnode, "./sid-value-type");
+
+ srgb_range = srgb_ubound - srgb_lbound + 1;
+ switch (sid_type) {
+ case SR_SID_VALUE_TYPE_INDEX:
+ if (sid >= srgb_range) {
+ zlog_warn("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)) {
+ zlog_warn("Invalid absolute SID %u", sid);
+ return NB_ERR_VALIDATION;
+ }
break;
}
return NB_OK;
}
+void isis_instance_segment_routing_prefix_sid_map_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/prefix-sid-map/prefix-sid/sid-value-type
*/
int isis_instance_segment_routing_prefix_sid_map_prefix_sid_sid_value_type_modify(
- enum nb_event event, const struct lyd_node *dnode,
- union nb_resource *resource)
+ struct nb_cb_modify_args *args)
{
- switch (event) {
- case NB_EV_VALIDATE:
- case NB_EV_PREPARE:
- case NB_EV_ABORT:
- case NB_EV_APPLY:
- /* TODO: implement me. */
- break;
- }
+ 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;
}
@@ -1552,17 +1650,15 @@ int isis_instance_segment_routing_prefix_sid_map_prefix_sid_sid_value_type_modif
* /frr-isisd:isis/instance/segment-routing/prefix-sid-map/prefix-sid/sid-value
*/
int isis_instance_segment_routing_prefix_sid_map_prefix_sid_sid_value_modify(
- enum nb_event event, const struct lyd_node *dnode,
- union nb_resource *resource)
+ struct nb_cb_modify_args *args)
{
- switch (event) {
- case NB_EV_VALIDATE:
- case NB_EV_PREPARE:
- case NB_EV_ABORT:
- case NB_EV_APPLY:
- /* TODO: implement me. */
- break;
- }
+ 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;
}
@@ -1572,17 +1668,15 @@ int isis_instance_segment_routing_prefix_sid_map_prefix_sid_sid_value_modify(
* /frr-isisd:isis/instance/segment-routing/prefix-sid-map/prefix-sid/last-hop-behavior
*/
int isis_instance_segment_routing_prefix_sid_map_prefix_sid_last_hop_behavior_modify(
- enum nb_event event, const struct lyd_node *dnode,
- union nb_resource *resource)
+ struct nb_cb_modify_args *args)
{
- switch (event) {
- case NB_EV_VALIDATE:
- case NB_EV_PREPARE:
- case NB_EV_ABORT:
- case NB_EV_APPLY:
- /* TODO: implement me. */
- break;
- }
+ 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;
}