summaryrefslogtreecommitdiff
path: root/isisd/isis_ldp_sync.c
diff options
context:
space:
mode:
authorIgor Ryzhov <iryzhov@nfware.com>2021-04-29 01:59:56 +0300
committerIgor Ryzhov <iryzhov@nfware.com>2021-04-29 17:05:21 +0300
commitec62fbaa07998df71a0bfce4a0383556bb604521 (patch)
tree830da6519ffef5e5c44ebf07ff32485bd8d9c3c8 /isisd/isis_ldp_sync.c
parentbcf220815632500f9646cb0b4c13f498afa4edf6 (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.c315
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;