]> git.puffer.fish Git - mirror/frr.git/commitdiff
isisd, ospfd: IGPs detect LDP down via zapi client close message 7686/head
authorKaren Schoener <karen@voltanet.io>
Tue, 8 Dec 2020 14:44:27 +0000 (09:44 -0500)
committerKaren Schoener <karen@volta.io>
Wed, 9 Dec 2020 13:41:42 +0000 (08:41 -0500)
When ldp-sync is configured, IGPs take action if the LDP process goes down.

Currently, IGPs detect the LDP process is down if they do not receive a
periodic 'hello' message from LDP within 1 second.

Intermittently, this heartbeat mechanism causes false topotest failures.
When the failure occurs, LDP is busy receiving messages from zebra for a
few seconds.  During this time, LDP does not send the expected periodic
message.

With this change, IGPs detect LDP down via zapi client close message.

Signed-off-by: Karen Schoener <karen@voltanet.io>
isisd/isis_ldp_sync.c
isisd/isis_ldp_sync.h
isisd/isis_zebra.c
ospfd/ospf_ldp_sync.c
ospfd/ospf_ldp_sync.h
ospfd/ospf_zebra.c

index 3b1faffe53304af78026f7512ed3bded9b1faf3d..c9d29871aedafbbf08d709914e9e0795c07fba55 100644 (file)
@@ -293,7 +293,7 @@ void isis_ldp_sync_ldp_fail(struct isis_circuit *circuit)
 
        ldp_sync_info = circuit->ldp_sync_info;
 
-       /* LDP failed to send hello:
+       /* LDP client close detected:
         *  stop holddown timer
         *  set cost of interface to LSInfinity so traffic will use different
         *  interface until LDP restarts and has learned all labels from peer
@@ -521,6 +521,44 @@ void isis_ldp_sync_holddown_timer_add(struct isis_circuit *circuit)
                         &ldp_sync_info->t_holddown);
 }
 
+/*
+ * LDP-SYNC handle client close routine
+ */
+void isis_ldp_sync_handle_client_close(struct zapi_client_close_info *info)
+{
+       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 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;
+
+       /* Check if the LDP main client session closed */
+       if (info->proto != ZEBRA_ROUTE_LDP || info->session_id == 0)
+               return;
+
+       /* Handle the zebra notification that the LDP client session closed.
+        *  set cost to LSInfinity
+        *  send request to LDP for LDP-SYNC state for each interface
+        */
+       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;
+                       isis_ldp_sync_if_start(circuit, true);
+               }
+       }
+}
+
 /*
  * LDP-SYNC hello timer routines
  */
index 61ac946078db0fe54c2628ae38eb2825cd4c24d8..1b6058c5c9cfd3610606d3667a774aa66716e3dc 100644 (file)
@@ -20,6 +20,8 @@
 #ifndef _ZEBRA_ISIS_LDP_SYNC_H
 #define _ZEBRA_ISIS_LDP_SYNC_H
 
+#include "zclient.h"
+
 /* Macro to log debug message */
 #define ils_debug(...)                                                         \
        do {                                                                   \
@@ -36,6 +38,8 @@ extern void isis_ldp_sync_if_start(struct isis_circuit *circuit,
 extern void isis_ldp_sync_if_remove(struct isis_circuit *circuit, bool remove);
 extern void isis_ldp_sync_if_complete(struct isis_circuit *circuit);
 extern void isis_ldp_sync_holddown_timer_add(struct isis_circuit *circuit);
+extern void
+isis_ldp_sync_handle_client_close(struct zapi_client_close_info *info);
 extern void isis_ldp_sync_hello_timer_add(void);
 extern void isis_ldp_sync_ldp_fail(struct isis_circuit *circuit);
 extern int isis_ldp_sync_state_update(struct ldp_igp_sync_if_state state);
index 1b4b0c8f2fe8ef1d7d31e607b30e92a474fc48cd..d51a4db939a1d5855a3f65a1c6f5ea5b8f2fbf34 100644 (file)
@@ -699,6 +699,20 @@ stream_failure:
        return ret;
 }
 
+static int isis_zebra_client_close_notify(ZAPI_CALLBACK_ARGS)
+{
+       int ret = 0;
+
+       struct zapi_client_close_info info;
+
+       if (zapi_client_close_notify_decode(zclient->ibuf, &info) < 0)
+               return -1;
+
+       isis_ldp_sync_handle_client_close(&info);
+
+       return ret;
+}
+
 void isis_zebra_init(struct thread_master *master, int instance)
 {
        /* Initialize asynchronous zclient. */
@@ -727,6 +741,8 @@ void isis_zebra_init(struct thread_master *master, int instance)
        zclient_sync->privs = &isisd_privs;
 
        zclient->opaque_msg_handler = isis_opaque_msg_handler;
+
+       zclient->zebra_client_close_notify = isis_zebra_client_close_notify;
 }
 
 void isis_zebra_stop(void)
index 68792ebcc2e7a1ffddd41bce0f13e83737f2a63a..bca15304b14f076665b098f0ae6a73513a38e565 100644 (file)
@@ -253,6 +253,33 @@ void ospf_ldp_sync_if_complete(struct interface *ifp)
        }
 }
 
+void ospf_ldp_sync_handle_client_close(struct zapi_client_close_info *info)
+{
+       struct ospf *ospf;
+       struct vrf *vrf;
+       struct interface *ifp;
+
+       /* if ospf is not enabled or LDP-SYNC is not configured ignore */
+       ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
+       if (ospf == NULL
+           || !CHECK_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
+               return;
+
+       /* Check if the LDP main client session closed */
+       if (info->proto != ZEBRA_ROUTE_LDP || info->session_id == 0)
+               return;
+
+       /* Handle the zebra notification that the LDP client session closed.
+        *  set cost to LSInfinity
+        *  send request to LDP for LDP-SYNC state for each interface
+        */
+       zlog_err("ldp_sync: LDP down");
+
+       vrf = vrf_lookup_by_id(ospf->vrf_id);
+       FOR_ALL_INTERFACES (vrf, ifp)
+               ospf_ldp_sync_if_start(ifp, true);
+}
+
 void ospf_ldp_sync_ldp_fail(struct interface *ifp)
 {
        struct ospf_if_params *params;
@@ -264,7 +291,7 @@ void ospf_ldp_sync_ldp_fail(struct interface *ifp)
        params = IF_DEF_PARAMS(ifp);
        ldp_sync_info = params->ldp_sync_info;
 
-       /* LDP failed to send hello:
+       /* LDP client close detected:
         *  stop holddown timer
         *  set cost of interface to LSInfinity so traffic will use different
         *  interface until LDP has learned all labels from peer
index d4efa55311d83e7447a505289f301ac5f5ba2bd2..418ca4e5b67b7b2b70a3d5cd4b77dbe1a2fbec77 100644 (file)
@@ -50,6 +50,8 @@ extern void ospf_ldp_sync_if_write_config(struct vty *vty,
 extern int ospf_ldp_sync_state_update(struct ldp_igp_sync_if_state state);
 extern int ospf_ldp_sync_announce_update(struct ldp_igp_sync_announce announce);
 extern int ospf_ldp_sync_hello_update(struct ldp_igp_sync_hello hello);
+extern void
+ospf_ldp_sync_handle_client_close(struct zapi_client_close_info *info);
 extern void ospf_ldp_sync_state_req_msg(struct interface *ifp);
 extern void ospf_ldp_sync_init(void);
 extern void ospf_ldp_sync_gbl_exit(struct ospf *ospf, bool remove);
index e7dbdbd9af3348591c2e911bc5db11c7df98f133..93d4ee0ec7f704475c3b7508ebf768775c1a739a 100644 (file)
@@ -1986,6 +1986,20 @@ stream_failure:
        return ret;
 }
 
+static int ospf_zebra_client_close_notify(ZAPI_CALLBACK_ARGS)
+{
+       int ret = 0;
+
+       struct zapi_client_close_info info;
+
+       if (zapi_client_close_notify_decode(zclient->ibuf, &info) < 0)
+               return -1;
+
+       ospf_ldp_sync_handle_client_close(&info);
+
+       return ret;
+}
+
 void ospf_zebra_init(struct thread_master *master, unsigned short instance)
 {
        /* Allocate zebra structure. */
@@ -2021,6 +2035,8 @@ void ospf_zebra_init(struct thread_master *master, unsigned short instance)
        prefix_list_delete_hook(ospf_prefix_list_update);
 
        zclient->opaque_msg_handler = ospf_opaque_msg_handler;
+
+       zclient->zebra_client_close_notify = ospf_zebra_client_close_notify;
 }
 
 void ospf_zebra_send_arp(const struct interface *ifp, const struct prefix *p)