diff options
author | Renato Westphal <renato@opensourcerouting.org> | 2019-08-04 03:02:37 +0200 |
---|---|---|
committer | Olivier Dugeon <olivier.dugeon@orange.com> | 2020-04-30 12:15:47 +0200 |
commit | 26f6acafc369f1c126870b4282d5e252cc830f26 (patch) | |
tree | a61a225ed9eddcd972abf6216e533606e559789c /isisd/isis_nb_config.c | |
parent | isisd: add segment-routing CLI commands (diff) | |
download | frr-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.c | 262 |
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; } |