]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: Adding zapi client close notification 7683/head
authorKaren Schoener <karen@voltanet.io>
Mon, 7 Dec 2020 23:01:01 +0000 (18:01 -0500)
committerKaren Schoener <karen@volta.io>
Mon, 7 Dec 2020 23:22:36 +0000 (18:22 -0500)
When zebra detects a client close, send a zapi client close
notification.

Signed-off-by: Karen Schoener <karen@voltanet.io>
lib/log.c
lib/zclient.c
lib/zclient.h
zebra/zapi_msg.c
zebra/zapi_msg.h
zebra/zserv.c

index 7b37ba7f27e9e2716f5cffd9a816f1eb4637c839..03ed23a04bcecf2bf221d450d6e604260a995f7b 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -456,7 +456,8 @@ static const struct zebra_desc_table command_types[] = {
        DESC_ENTRY(ZEBRA_NHG_ADD),
        DESC_ENTRY(ZEBRA_NHG_DEL),
        DESC_ENTRY(ZEBRA_NHG_NOTIFY_OWNER),
-       DESC_ENTRY(ZEBRA_ROUTE_NOTIFY_REQUEST)};
+       DESC_ENTRY(ZEBRA_ROUTE_NOTIFY_REQUEST),
+       DESC_ENTRY(ZEBRA_CLIENT_CLOSE_NOTIFY)};
 #undef DESC_ENTRY
 
 static const struct zebra_desc_table unknown = {0, "unknown", '?'};
index 053014f86dab12b26995fa34f799c3a8221fed49..ba94b7fb9991439b35494311ec7637e31282c4e4 100644 (file)
@@ -3528,6 +3528,23 @@ stream_failure:
        return -1;
 }
 
+/* Utility to decode client close notify info */
+int zapi_client_close_notify_decode(struct stream *s,
+                                   struct zapi_client_close_info *info)
+{
+       memset(info, 0, sizeof(*info));
+
+       STREAM_GETC(s, info->proto);
+       STREAM_GETW(s, info->instance);
+       STREAM_GETL(s, info->session_id);
+
+       return 0;
+
+stream_failure:
+
+       return -1;
+}
+
 /* Zebra client message read function. */
 static int zclient_read(struct thread *thread)
 {
@@ -3868,6 +3885,12 @@ static int zclient_read(struct thread *thread)
                if (zclient->sr_policy_notify_status)
                        (*zclient->sr_policy_notify_status)(command, zclient,
                                                            length, vrf_id);
+               break;
+       case ZEBRA_CLIENT_CLOSE_NOTIFY:
+               if (zclient->zebra_client_close_notify)
+                       (*zclient->zebra_client_close_notify)(command, zclient,
+                                                             length, vrf_id);
+               break;
        default:
                break;
        }
index ae94237b767e1c6fc25b17315494610791dc2a2e..33c1e732ee0263ec9aa50a66e828c59fcaef025d 100644 (file)
@@ -220,6 +220,7 @@ typedef enum {
        ZEBRA_OPAQUE_UNREGISTER,
        ZEBRA_NEIGH_DISCOVER,
        ZEBRA_ROUTE_NOTIFY_REQUEST,
+       ZEBRA_CLIENT_CLOSE_NOTIFY,
 } zebra_message_types_t;
 
 enum zebra_error_types {
@@ -377,6 +378,7 @@ struct zclient {
        int (*opaque_register_handler)(ZAPI_CALLBACK_ARGS);
        int (*opaque_unregister_handler)(ZAPI_CALLBACK_ARGS);
        int (*sr_policy_notify_status)(ZAPI_CALLBACK_ARGS);
+       int (*zebra_client_close_notify)(ZAPI_CALLBACK_ARGS);
 };
 
 /* Zebra API message flag. */
@@ -1097,6 +1099,17 @@ zclient_send_neigh_discovery_req(struct zclient *zclient,
                                 const struct interface *ifp,
                                 const struct prefix *p);
 
+struct zapi_client_close_info {
+       /* Client session tuple */
+       uint8_t proto;
+       uint16_t instance;
+       uint32_t session_id;
+};
+
+/* Decode incoming client close notify */
+extern int zapi_client_close_notify_decode(struct stream *s,
+                                          struct zapi_client_close_info *info);
+
 #ifdef __cplusplus
 }
 #endif
index f7c123231e134b76ee491a06de35ebdd71bb9111..c6210d14ac24a17ad33573863a22d65db093aa13 100644 (file)
@@ -2522,6 +2522,22 @@ int zsend_sr_policy_notify_status(uint32_t color, struct ipaddr *endpoint,
        return zserv_send_message(client, s);
 }
 
+/* Send client close notify to client */
+int zsend_client_close_notify(struct zserv *client, struct zserv *closed_client)
+{
+       struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+
+       zclient_create_header(s, ZEBRA_CLIENT_CLOSE_NOTIFY, VRF_DEFAULT);
+
+       stream_putc(s, closed_client->proto);
+       stream_putw(s, closed_client->instance);
+       stream_putl(s, closed_client->session_id);
+
+       stream_putw_at(s, 0, stream_get_endp(s));
+
+       return zserv_send_message(client, s);
+}
+
 /* Send response to a table manager connect request to client */
 static void zread_table_manager_connect(struct zserv *client,
                                        struct stream *msg, vrf_id_t vrf_id)
index efc52059b665bb059cba8f376e51dd58d7339872..9822d7202279ed31f6349fcb8c58db319cdd3eb6 100644 (file)
@@ -105,6 +105,9 @@ extern int zsend_sr_policy_notify_status(uint32_t color,
                                         struct ipaddr *endpoint, char *name,
                                         int status);
 
+extern int zsend_client_close_notify(struct zserv *client,
+                                    struct zserv *closed_client);
+
 #ifdef __cplusplus
 }
 #endif
index 4b5791530d0868ea774f6dddcae5a60c6853422a..c7b9433257da986654638cbe0435690b0c9b06c6 100644 (file)
@@ -1300,6 +1300,21 @@ DEFUN (show_zebra_client_summary,
        return CMD_SUCCESS;
 }
 
+static int zserv_client_close_cb(struct zserv *closed_client)
+{
+       struct listnode *node, *nnode;
+       struct zserv *client = NULL;
+
+       for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
+               if (client->proto == closed_client->proto)
+                       continue;
+
+               zsend_client_close_notify(client, closed_client);
+       }
+
+       return 0;
+}
+
 void zserv_init(void)
 {
        /* Client list init. */
@@ -1312,4 +1327,6 @@ void zserv_init(void)
 
        install_element(ENABLE_NODE, &show_zebra_client_cmd);
        install_element(ENABLE_NODE, &show_zebra_client_summary_cmd);
+
+       hook_register(zserv_client_close, zserv_client_close_cb);
 }