diff options
| author | Igor Ryzhov <iryzhov@nfware.com> | 2021-04-29 01:59:56 +0300 | 
|---|---|---|
| committer | Igor Ryzhov <iryzhov@nfware.com> | 2021-04-29 17:05:21 +0300 | 
| commit | ec62fbaa07998df71a0bfce4a0383556bb604521 (patch) | |
| tree | 830da6519ffef5e5c44ebf07ff32485bd8d9c3c8 /isisd/isis_ldp_sync.c | |
| parent | bcf220815632500f9646cb0b4c13f498afa4edf6 (diff) | |
isisd: fix ldp-sync configuration
YANG model and CLI commands allow user to configure LDP-sync per area.
But the actual implementation is incorrect - all commands are changing
the config for the whole VRF instead of a single area. This commit fixes
this issue by actually implementing per area configuration.
Fixes #8578.
Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
Diffstat (limited to 'isisd/isis_ldp_sync.c')
| -rw-r--r-- | isisd/isis_ldp_sync.c | 315 | 
1 files changed, 126 insertions, 189 deletions
diff --git a/isisd/isis_ldp_sync.c b/isisd/isis_ldp_sync.c index 585f769806..62d8b8334a 100644 --- a/isisd/isis_ldp_sync.c +++ b/isisd/isis_ldp_sync.c @@ -65,28 +65,20 @@ int isis_ldp_sync_state_update(struct ldp_igp_sync_if_state state)  	struct interface *ifp;  	struct isis_circuit *circuit = NULL;  	struct isis_area *area; -	struct listnode *node; -	struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); - -	/* if isis is not enabled or LDP-SYNC is not configured ignore */ -	if (!isis || -	    !CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) -		return 0;  	/* lookup circuit */  	ifp = if_lookup_by_index(state.ifindex, VRF_DEFAULT);  	if (ifp == NULL)  		return 0; -	for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { -		circuit = circuit_lookup_by_ifp(ifp, area->circuit_list); -		if (circuit != NULL) -			break; -	} +	circuit = ifp->info; +	if (circuit == NULL) +		return 0;  	/* if isis is not enabled or LDP-SYNC is not configured ignore */ -	if (circuit == NULL || -	    !CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) +	area = circuit->area; +	if (area == NULL +	    || !CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))  		return 0;  	/* received ldp-sync interface state from LDP */ @@ -103,15 +95,12 @@ int isis_ldp_sync_state_update(struct ldp_igp_sync_if_state state)  int isis_ldp_sync_announce_update(struct ldp_igp_sync_announce announce)  {  	struct isis_area *area; -	struct listnode *node; -	struct vrf *vrf; -	struct interface *ifp; +	struct listnode *anode, *cnode;  	struct isis_circuit *circuit;  	struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); -	/* if isis is not enabled or LDP-SYNC is not configured ignore */ -	if (!isis || -	    !CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) +	/* if isis is not enabled ignore */ +	if (!isis)  		return 0;  	if (announce.proto != ZEBRA_ROUTE_LDP) @@ -123,15 +112,12 @@ int isis_ldp_sync_announce_update(struct ldp_igp_sync_announce announce)  	 *  set cost to LSInfinity  	 *  send request to LDP for LDP-SYNC state for each interface  	 */ -	vrf = vrf_lookup_by_id(VRF_DEFAULT); -	FOR_ALL_INTERFACES (vrf, ifp) { -		for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { -			circuit = circuit_lookup_by_ifp(ifp, -				area->circuit_list); -			if (circuit == NULL) -				continue; +	for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { +		if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) +			continue; + +		for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit))  			isis_ldp_sync_if_start(circuit, true); -		}  	}  	return 0; @@ -157,32 +143,6 @@ void isis_ldp_sync_state_req_msg(struct isis_circuit *circuit)  /*   * LDP-SYNC general interface routines   */ -void isis_ldp_sync_if_init(struct isis_circuit *circuit, struct isis *isis) -{ -	struct ldp_sync_info *ldp_sync_info; -	struct interface *ifp = circuit->interface; - -	/* called when ISIS is configured on an interface -	 *  if LDP-IGP Sync is configured globally set state -	 *  and if ptop interface LDP LDP-SYNC is enabled -	 */ -	ils_debug("ldp_sync: init if %s ", ifp->name); -	if (circuit->ldp_sync_info == NULL) -		circuit->ldp_sync_info = ldp_sync_info_create(); -	ldp_sync_info = circuit->ldp_sync_info; - -	/* specifed on interface overrides global config. */ -	if (!CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN)) -		ldp_sync_info->holddown = isis->ldp_sync_cmd.holddown; - -	if (!CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG)) -		ldp_sync_info->enabled = LDP_IGP_SYNC_ENABLED; - -	if ((circuit->circ_type == CIRCUIT_T_P2P || if_is_pointopoint(ifp)) && -	    ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED) -		ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP; -} -  void isis_ldp_sync_if_start(struct isis_circuit *circuit,  	bool send_state_req)  { @@ -251,49 +211,17 @@ void isis_ldp_sync_ldp_fail(struct isis_circuit *circuit)  	}  } -void isis_ldp_sync_if_remove(struct isis_circuit *circuit, bool remove) -{ -	struct ldp_sync_info *ldp_sync_info; - -	if (circuit->ldp_sync_info == NULL) -		return; - -	ldp_sync_info = circuit->ldp_sync_info; - -	/* Stop LDP-SYNC on this interface: -	 *  if holddown timer is running stop it -	 *  delete ldp instance on interface -	 *  restore metric -	 */ -	ils_debug("ldp_sync: remove if %s", circuit->interface -		  ? circuit->interface->name : ""); - -	THREAD_OFF(ldp_sync_info->t_holddown); -	ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED; -	isis_ldp_sync_set_if_metric(circuit, true); -	if (remove) { -		/* ISIS instance being removed free ldp-sync info */ -		ldp_sync_info_free((struct ldp_sync_info **)&(ldp_sync_info)); -		circuit->ldp_sync_info = NULL; -	} -} -  static int isis_ldp_sync_adj_state_change(struct isis_adjacency *adj)  {  	struct isis_circuit *circuit = adj->circuit; -	struct ldp_sync_info *ldp_sync_info; -	struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); +	struct ldp_sync_info *ldp_sync_info = circuit->ldp_sync_info; +	struct isis_area *area = circuit->area; -	if (!isis || -	    !CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE) || -	    circuit->interface->vrf_id != VRF_DEFAULT || -	    if_is_loopback(circuit->interface)) +	if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE) +	    || circuit->interface->vrf_id != VRF_DEFAULT +	    || if_is_loopback(circuit->interface))  		return 0; -	if (circuit->ldp_sync_info == NULL) -		isis_ldp_sync_if_init(circuit, isis); -	ldp_sync_info = circuit->ldp_sync_info; -  	if (ldp_sync_info->enabled != LDP_IGP_SYNC_ENABLED)  		return 0; @@ -329,16 +257,15 @@ bool isis_ldp_sync_if_metric_config(struct isis_circuit *circuit, int level,  				    int metric)  {  	struct ldp_sync_info *ldp_sync_info = circuit->ldp_sync_info; -	struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); +	struct isis_area *area = circuit->area;  	/* configured interface metric has been changed:  	 *   if LDP-IGP Sync is running and metric has been set to LSInfinity  	 *   change saved value so when ldp-sync completes proper metric is  	 *   restored  	 */ -	if (isis && -	    CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE) && -	    ldp_sync_info != NULL) { +	if (area && CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE) +	    && ldp_sync_info != NULL) {  		if (CHECK_FLAG(ldp_sync_info->flags,  			       LDP_SYNC_FLAG_SET_METRIC)) { @@ -471,15 +398,12 @@ void isis_ldp_sync_holddown_timer_add(struct isis_circuit *circuit)  void isis_ldp_sync_handle_client_close(struct zapi_client_close_info *info)  {  	struct isis_area *area; -	struct listnode *node; +	struct listnode *anode, *cnode;  	struct isis_circuit *circuit; -	struct interface *ifp; -	struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);  	struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); -	/* if isis is not enabled or LDP-SYNC is not configured ignore */ -	if (!isis -	    || !CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) +	/* if isis is not enabled ignore */ +	if (!isis)  		return;  	/* Check if the LDP main client session closed */ @@ -492,14 +416,12 @@ void isis_ldp_sync_handle_client_close(struct zapi_client_close_info *info)  	 */  	zlog_err("ldp_sync: LDP down"); -	FOR_ALL_INTERFACES (vrf, ifp) { -		for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { -			circuit = -				circuit_lookup_by_ifp(ifp, area->circuit_list); -			if (circuit == NULL) -				continue; +	for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { +		if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) +			continue; + +		for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit))  			isis_ldp_sync_ldp_fail(circuit); -		}  	}  } @@ -507,110 +429,130 @@ void isis_ldp_sync_handle_client_close(struct zapi_client_close_info *info)   * LDP-SYNC routes used by set commands.   */ -void isis_if_set_ldp_sync_enable(struct isis_circuit *circuit) +void isis_area_ldp_sync_enable(struct isis_area *area)  { -	struct ldp_sync_info *ldp_sync_info; -	struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); +	struct isis_circuit *circuit; +	struct listnode *node; + +	if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) { +		SET_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE); + +		for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) +			isis_if_ldp_sync_enable(circuit); +	} +} + +void isis_area_ldp_sync_disable(struct isis_area *area) +{ +	struct isis_circuit *circuit; +	struct listnode *node; + +	if (CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) { +		for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) +			isis_if_ldp_sync_disable(circuit); + +		UNSET_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE); + +		UNSET_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN); +		area->ldp_sync_cmd.holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT; +	} +} + +void isis_area_ldp_sync_set_holddown(struct isis_area *area, uint16_t holddown) +{ +	struct isis_circuit *circuit; +	struct listnode *node; + +	if (holddown == LDP_IGP_SYNC_HOLDDOWN_DEFAULT) +		UNSET_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN); +	else +		SET_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN); + +	area->ldp_sync_cmd.holddown = holddown; + +	for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) +		isis_if_set_ldp_sync_holddown(circuit); +} + +void isis_if_ldp_sync_enable(struct isis_circuit *circuit) +{ +	struct ldp_sync_info *ldp_sync_info = circuit->ldp_sync_info; +	struct isis_area *area = circuit->area;  	/* called when setting LDP-SYNC at the global level:  	 *  specifed on interface overrides global config  	 *  if ptop link send msg to LDP indicating ldp-sync enabled   	 */ -	if (!isis || if_is_loopback(circuit->interface)) +	if (if_is_loopback(circuit->interface))  		return; -	if (CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) { -		if (circuit->ldp_sync_info == NULL) -			isis_ldp_sync_if_init(circuit, isis); -		ldp_sync_info = circuit->ldp_sync_info; +	ils_debug("ldp_sync: enable if %s", circuit->interface->name); -		/* config on interface, overrides global config. */ -		if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG)) -			if (ldp_sync_info->enabled != LDP_IGP_SYNC_ENABLED) -			    return; +	if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) +		return; -		ldp_sync_info->enabled = LDP_IGP_SYNC_ENABLED; -		ils_debug("ldp_sync: enable if %s", circuit->interface->name); +	/* config on interface, overrides global config. */ +	if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG)) +		if (ldp_sync_info->enabled != LDP_IGP_SYNC_ENABLED) +			return; -		/* send message to LDP if ptop link */ -		if (circuit->circ_type == CIRCUIT_T_P2P || -		    if_is_pointopoint(circuit->interface)) { -			ldp_sync_info->state = -				LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP; -			isis_ldp_sync_state_req_msg(circuit); -		} else { -			ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED; -			zlog_debug("ldp_sync: Sync only runs on P2P links %s", -				   circuit->interface->name); -		} -	} else -		/* delete LDP sync even if configured on an interface */ -		isis_ldp_sync_if_remove(circuit, false); +	if (!CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN)) +		ldp_sync_info->holddown = area->ldp_sync_cmd.holddown; + +	if (circuit->circ_type == CIRCUIT_T_P2P +	    || if_is_pointopoint(circuit->interface)) { +		ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP; +		isis_ldp_sync_state_req_msg(circuit); +	} else { +		ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED; +		ils_debug("ldp_sync: Sync only runs on P2P links %s", +			  circuit->interface->name); +	} +} + +void isis_if_ldp_sync_disable(struct isis_circuit *circuit) +{ +	struct ldp_sync_info *ldp_sync_info = circuit->ldp_sync_info; +	struct isis_area *area = circuit->area; + +	/* Stop LDP-SYNC on this interface: +	 *  if holddown timer is running stop it +	 *  delete ldp instance on interface +	 *  restore metric +	 */ +	if (if_is_loopback(circuit->interface)) +		return; + +	ils_debug("ldp_sync: remove if %s", circuit->interface->name); + +	if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) +		return; + +	THREAD_OFF(ldp_sync_info->t_holddown); +	ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED; +	isis_ldp_sync_set_if_metric(circuit, true);  }  void isis_if_set_ldp_sync_holddown(struct isis_circuit *circuit)  { -	struct ldp_sync_info *ldp_sync_info; -	struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); +	struct ldp_sync_info *ldp_sync_info = circuit->ldp_sync_info; +	struct isis_area *area = circuit->area;  	/* called when setting LDP-SYNC at the global level:  	 *  specifed on interface overrides global config.  	 */ -	if (!isis || if_is_loopback(circuit->interface)) +	if (if_is_loopback(circuit->interface))  		return; -	if (circuit->ldp_sync_info == NULL) -		isis_ldp_sync_if_init(circuit, isis); -	ldp_sync_info = circuit->ldp_sync_info; -  	/* config on interface, overrides global config. */  	if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN))  		return; -	if (CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN)) -		ldp_sync_info->holddown = isis->ldp_sync_cmd.holddown; +	if (CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN)) +		ldp_sync_info->holddown = area->ldp_sync_cmd.holddown;  	else  		ldp_sync_info->holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;  } -void isis_ldp_sync_gbl_exit(bool remove) -{ -	struct isis_area *area; -	struct listnode *node; -	struct isis_circuit *circuit; -	struct interface *ifp; -	struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); -	struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); - -	/* if you delete LDP-SYNC at a gobal level is clears all LDP-SYNC -	 * configuration, even interface configuration -	 */ -	if (isis && -	    CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) { -		/* register with opaque client to recv LDP-IGP Sync msgs */ -		zclient_unregister_opaque(zclient, -					  LDP_IGP_SYNC_IF_STATE_UPDATE); -		zclient_unregister_opaque(zclient, -					  LDP_IGP_SYNC_ANNOUNCE_UPDATE); - -		/* disable LDP-SYNC globally */ -		UNSET_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE); -		UNSET_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN); -		isis->ldp_sync_cmd.holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT; - -		/* remove LDP-SYNC on all ISIS interfaces */ -		FOR_ALL_INTERFACES (vrf, ifp) { -			for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, -						  area)) { -				circuit = circuit_lookup_by_ifp(ifp, -					area->circuit_list); -				if (circuit == NULL) -					continue; -				isis_ldp_sync_if_remove(circuit, remove); -			} -		} -	} -} -  /*   * LDP-SYNC routines used by show commands.   */ @@ -693,11 +635,6 @@ DEFUN (show_isis_mpls_ldp_interface,  		return CMD_SUCCESS;  	} -	if (!CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) { -		vty_out(vty, "LDP-sync is disabled\n"); -		return CMD_SUCCESS; -	} -  	if (argv_find(argv, argc, "INTERFACE", &idx_intf))  		ifname = argv[idx_intf]->arg;  | 
