diff options
| author | Renato Westphal <renato@opensourcerouting.org> | 2020-11-25 23:39:09 -0300 | 
|---|---|---|
| committer | Renato Westphal <renato@opensourcerouting.org> | 2021-01-08 22:22:11 -0300 | 
| commit | 16fe8cffa1f73b6af767867742435b08217eef9d (patch) | |
| tree | b68b7a46b537fda13bbd6260f7dd142be5d64a86 /isisd/isis_nb_config.c | |
| parent | 381200be9d2698fefc33258dd23163877b02fbca (diff) | |
isisd: implement Remote LFA
Remote LFA (RFC 7490) is an extension to the base LFA mechanism
that uses dynamically determined tunnels to extend the IP-FRR
protection coverage.
RLFA is similar to TI-LFA in that it computes a post-convergence
SPT (with the protected interface pruned from the network topology)
and the P/Q spaces based on that SPT. There are a few differences
however:
* RLFAs can push at most one label, so the P/Q spaces need to
  intersect otherwise the destination can't be protected (the
  protection coverage is topology dependent).
* isisd needs to interface with ldpd to obtain the labels it needs to
  create a tunnel to the PQ node. That interaction needs to be done
  asynchronously to prevent blocking the daemon for too long. With
  TI-LFA all required labels are already available in the LSPDB.
RLFA and TI-LFA have more similarities than differences though,
and thanks to that both features share a lot of code.
Limitations:
* Only RLFA link protection is implemented. The algorithm used
  to find node-protecting RLFAs (RFC 8102) is too CPU intensive and
  doesn't always work. Most vendors implement RLFA link protection
  only.
* RFC 7490 says it should be a local matter whether the repair path
  selection policy favors LFA repairs over RLFA repairs. It might be
  desirable, for instance, to prefer RLFAs that satisfy the downstream
  condition over LFAs that don't. In this implementation, however,
  RLFAs are only computed for destinations that can't be protected
  by local LFAs.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Diffstat (limited to 'isisd/isis_nb_config.c')
| -rw-r--r-- | isisd/isis_nb_config.c | 200 | 
1 files changed, 121 insertions, 79 deletions
diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c index e3222e23c9..3ec23df43d 100644 --- a/isisd/isis_nb_config.c +++ b/isisd/isis_nb_config.c @@ -28,6 +28,7 @@  #include "log.h"  #include "bfd.h"  #include "filter.h" +#include "plist.h"  #include "spf_backoff.h"  #include "lib_errors.h"  #include "vrf.h" @@ -1548,14 +1549,18 @@ int isis_instance_fast_reroute_level_1_lfa_tiebreaker_type_modify(  int isis_instance_fast_reroute_level_1_remote_lfa_prefix_list_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->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; +	const char *plist_name; + +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	area = nb_running_get_entry(args->dnode, NULL, true); +	plist_name = yang_dnode_get_string(args->dnode, NULL); + +	area->rlfa_plist_name[0] = XSTRDUP(MTYPE_ISIS_PLIST_NAME, plist_name); +	area->rlfa_plist[0] = prefix_list_lookup(AFI_IP, plist_name); +	lsp_regenerate_schedule(area, area->is_type, 0);  	return NB_OK;  } @@ -1563,14 +1568,16 @@ int isis_instance_fast_reroute_level_1_remote_lfa_prefix_list_modify(  int isis_instance_fast_reroute_level_1_remote_lfa_prefix_list_destroy(  	struct nb_cb_destroy_args *args)  { -	switch (args->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); + +	XFREE(MTYPE_ISIS_PLIST_NAME, area->rlfa_plist_name[0]); +	area->rlfa_plist[0] = NULL; +	lsp_regenerate_schedule(area, area->is_type, 0);  	return NB_OK;  } @@ -1691,14 +1698,18 @@ int isis_instance_fast_reroute_level_2_lfa_tiebreaker_type_modify(  int isis_instance_fast_reroute_level_2_remote_lfa_prefix_list_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->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; +	const char *plist_name; + +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	area = nb_running_get_entry(args->dnode, NULL, true); +	plist_name = yang_dnode_get_string(args->dnode, NULL); + +	area->rlfa_plist_name[1] = XSTRDUP(MTYPE_ISIS_PLIST_NAME, plist_name); +	area->rlfa_plist[1] = prefix_list_lookup(AFI_IP, plist_name); +	lsp_regenerate_schedule(area, area->is_type, 0);  	return NB_OK;  } @@ -1706,14 +1717,16 @@ int isis_instance_fast_reroute_level_2_remote_lfa_prefix_list_modify(  int isis_instance_fast_reroute_level_2_remote_lfa_prefix_list_destroy(  	struct nb_cb_destroy_args *args)  { -	switch (args->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); + +	XFREE(MTYPE_ISIS_PLIST_NAME, area->rlfa_plist_name[1]); +	area->rlfa_plist[1] = NULL; +	lsp_regenerate_schedule(area, area->is_type, 0);  	return NB_OK;  } @@ -3510,15 +3523,24 @@ int lib_interface_isis_fast_reroute_level_1_lfa_exclude_interface_destroy(  int lib_interface_isis_fast_reroute_level_1_remote_lfa_enable_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->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 isis_circuit *circuit; + +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	circuit = nb_running_get_entry(args->dnode, NULL, true); +	circuit->rlfa_protection[0] = yang_dnode_get_bool(args->dnode, NULL); +	if (circuit->rlfa_protection[0]) +		circuit->area->rlfa_protected_links[0]++; +	else { +		assert(circuit->area->rlfa_protected_links[0] > 0); +		circuit->area->rlfa_protected_links[0]--;  	} +	area = circuit->area; +	lsp_regenerate_schedule(area, area->is_type, 0); +  	return NB_OK;  } @@ -3529,14 +3551,17 @@ int lib_interface_isis_fast_reroute_level_1_remote_lfa_enable_modify(  int lib_interface_isis_fast_reroute_level_1_remote_lfa_maximum_metric_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->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 isis_circuit *circuit; + +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	circuit = nb_running_get_entry(args->dnode, NULL, true); +	circuit->rlfa_max_metric[0] = yang_dnode_get_uint32(args->dnode, NULL); + +	area = circuit->area; +	lsp_regenerate_schedule(area, area->is_type, 0);  	return NB_OK;  } @@ -3544,19 +3569,21 @@ int lib_interface_isis_fast_reroute_level_1_remote_lfa_maximum_metric_modify(  int lib_interface_isis_fast_reroute_level_1_remote_lfa_maximum_metric_destroy(  	struct nb_cb_destroy_args *args)  { -	switch (args->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 isis_circuit *circuit; + +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	circuit = nb_running_get_entry(args->dnode, NULL, true); +	circuit->rlfa_max_metric[0] = 0; + +	area = circuit->area; +	lsp_regenerate_schedule(area, area->is_type, 0);  	return NB_OK;  } -  /*   * XPath:   * /frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-1/ti-lfa/enable @@ -3687,15 +3714,24 @@ int lib_interface_isis_fast_reroute_level_2_lfa_exclude_interface_destroy(  int lib_interface_isis_fast_reroute_level_2_remote_lfa_enable_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->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 isis_circuit *circuit; + +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	circuit = nb_running_get_entry(args->dnode, NULL, true); +	circuit->rlfa_protection[1] = yang_dnode_get_bool(args->dnode, NULL); +	if (circuit->rlfa_protection[1]) +		circuit->area->rlfa_protected_links[1]++; +	else { +		assert(circuit->area->rlfa_protected_links[1] > 0); +		circuit->area->rlfa_protected_links[1]--;  	} +	area = circuit->area; +	lsp_regenerate_schedule(area, area->is_type, 0); +  	return NB_OK;  } @@ -3706,14 +3742,17 @@ int lib_interface_isis_fast_reroute_level_2_remote_lfa_enable_modify(  int lib_interface_isis_fast_reroute_level_2_remote_lfa_maximum_metric_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->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 isis_circuit *circuit; + +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	circuit = nb_running_get_entry(args->dnode, NULL, true); +	circuit->rlfa_max_metric[1] = yang_dnode_get_uint32(args->dnode, NULL); + +	area = circuit->area; +	lsp_regenerate_schedule(area, area->is_type, 0);  	return NB_OK;  } @@ -3721,14 +3760,17 @@ int lib_interface_isis_fast_reroute_level_2_remote_lfa_maximum_metric_modify(  int lib_interface_isis_fast_reroute_level_2_remote_lfa_maximum_metric_destroy(  	struct nb_cb_destroy_args *args)  { -	switch (args->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 isis_circuit *circuit; + +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	circuit = nb_running_get_entry(args->dnode, NULL, true); +	circuit->rlfa_max_metric[1] = 0; + +	area = circuit->area; +	lsp_regenerate_schedule(area, area->is_type, 0);  	return NB_OK;  }  | 
