]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib,zebra: add a session id for zapi sessions
authorMark Stapp <mjs@voltanet.io>
Tue, 14 Apr 2020 14:45:09 +0000 (10:45 -0400)
committerMark Stapp <mjs@voltanet.io>
Thu, 16 Apr 2020 16:07:54 +0000 (12:07 -0400)
Distinguish zapi sessions, for daemons who use more than one,
by adding a session id. The tuple of proto + instance is not
adequate to support clients who use multiple zapi sessions.
Include the id in the client show output if it's present. Add
a bit of info about this to the developer doc.

Signed-off-by: Mark Stapp <mjs@voltanet.io>
doc/developer/zebra.rst
lib/zclient.c
lib/zclient.h
zebra/zapi_msg.c
zebra/zserv.c
zebra/zserv.h

index e3526d184371a47ed91df0538d3f2d1232e3af19..e2f887ef2844b858a4326ae13a05a22424b21406 100644 (file)
@@ -9,13 +9,20 @@ Zebra
 Overview of the Zebra Protocol
 ==============================
 
-The Zebra protocol is used by protocol daemons to communicate with the
-**zebra** daemon.
-
-Each protocol daemon may request and send information to and from the **zebra**
-daemon such as interface states, routing state, nexthop-validation, and so on.
-Protocol daemons may also install routes with **zebra**. The **zebra** daemon
-manages which routes are installed into the forwarding table with the kernel.
+The Zebra protocol (or ``ZAPI``) is used by protocol daemons to
+communicate with the **zebra** daemon.
+
+Each protocol daemon may request and send information to and from the
+**zebra** daemon such as interface states, routing state,
+nexthop-validation, and so on.  Protocol daemons may also install
+routes with **zebra**. The **zebra** daemon manages which routes are
+installed into the forwarding table with the kernel. Some daemons use
+more than one ZAPI connection. This is supported: each ZAPI session is
+identified by a tuple of: ``{protocol, instance, session_id}``. LDPD
+is an example: it uses a second, synchronous ZAPI session to manage
+label blocks. The default value for ``session_id`` is zero; daemons
+who use multiple ZAPI sessions must assign unique values to the
+sessions' ids.
 
 The Zebra protocol is a streaming protocol, with a common header. Version 0
 lacks a version field and is implicitly versioned. Version 1 and all subsequent
index 5402e9c3c560a2a41f39c4c3bc14c2ca8f52ab5e..be2c4e54a0def72d47a1fcfdabfd0dd923a8f0ce 100644 (file)
@@ -388,6 +388,7 @@ int zclient_send_hello(struct zclient *zclient)
                zclient_create_header(s, ZEBRA_HELLO, VRF_DEFAULT);
                stream_putc(s, zclient->redist_default);
                stream_putw(s, zclient->instance);
+               stream_putl(s, zclient->session_id);
                if (zclient->receive_notify)
                        stream_putc(s, 1);
                else
index 214226cf5f1b9f86f350ea35d0f95e01aabccb31..6e8066381fc2b3d3f6e30210d1e56381260499e1 100644 (file)
@@ -258,6 +258,9 @@ struct zclient {
        /* Is this a synchronous client? */
        bool synchronous;
 
+       /* Session id (optional) to support clients with multiple sessions */
+       uint32_t session_id;
+
        /* Socket to zebra daemon. */
        int sock;
 
index a58df826984180487ceb648ec4e4ee3759bb933f..d6f23de487d5a217a0b3606a9180cae601f083b7 100644 (file)
@@ -1931,9 +1931,11 @@ static void zread_hello(ZAPI_HANDLER_ARGS)
        unsigned short instance;
        uint8_t notify;
        uint8_t synchronous;
+       uint32_t session_id;
 
        STREAM_GETC(msg, proto);
        STREAM_GETW(msg, instance);
+       STREAM_GETL(msg, session_id);
        STREAM_GETC(msg, notify);
        STREAM_GETC(msg, synchronous);
        if (notify)
@@ -1953,6 +1955,7 @@ static void zread_hello(ZAPI_HANDLER_ARGS)
 
                client->proto = proto;
                client->instance = instance;
+               client->session_id = session_id;
 
                /* Graceful restart processing for client connect */
                zebra_gr_client_reconnect(client);
index 740e7c43c77bf77f3c6e0d8567bbb23623898b87..8a1ed115a7f99fd37377c67773896f9b1aa3dc9b 100644 (file)
@@ -889,6 +889,8 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client)
        vty_out(vty, "Client: %s", zebra_route_string(client->proto));
        if (client->instance)
                vty_out(vty, " Instance: %u", client->instance);
+       if (client->session_id)
+               vty_out(vty, " [%u]", client->session_id);
        vty_out(vty, "\n");
 
        vty_out(vty, "------------------------ \n");
@@ -995,11 +997,16 @@ static void zebra_show_stale_client_detail(struct vty *vty,
        time_t uptime;
        struct client_gr_info *info = NULL;
        struct zserv *s = NULL;
-
-       if (client->instance)
-               vty_out(vty, " Instance: %d", client->instance);
+       bool first_p = true;
 
        TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) {
+               if (first_p) {
+                       if (client->instance)
+                               vty_out(vty, " Instance: %u", client->instance);
+                       if (client->session_id)
+                               vty_out(vty, " [%u]", client->session_id);
+                       first_p = false;
+               }
                vty_out(vty, "VRF : %s\n", vrf_id_to_name(info->vrf_id));
                vty_out(vty, "Capabilities : ");
                switch (info->capabilities) {
@@ -1070,19 +1077,26 @@ static void zebra_show_client_brief(struct vty *vty, struct zserv *client)
                client->v6_route_del_cnt);
 }
 
-struct zserv *zserv_find_client(uint8_t proto, unsigned short instance)
+struct zserv *zserv_find_client_session(uint8_t proto, unsigned short instance,
+                                       uint32_t session_id)
 {
        struct listnode *node, *nnode;
        struct zserv *client;
 
        for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
-               if (client->proto == proto && client->instance == instance)
+               if (client->proto == proto && client->instance == instance &&
+                   client->session_id == session_id)
                        return client;
        }
 
        return NULL;
 }
 
+struct zserv *zserv_find_client(uint8_t proto, unsigned short instance)
+{
+       return zserv_find_client_session(proto, instance, 0);
+}
+
 /* This command is for debugging purpose. */
 DEFUN (show_zebra_client,
        show_zebra_client_cmd,
index 08df664d562d33ac8a376406f0a6babb8b86163b..5506c4299de77cc6d3734e089f3af63e6962ff3e 100644 (file)
@@ -134,9 +134,10 @@ struct zserv {
        /* Indicates if client is synchronous. */
        bool synchronous;
 
-       /* client's protocol */
+       /* client's protocol and session info */
        uint8_t proto;
        uint16_t instance;
+       uint32_t session_id;
 
        /*
         * Interested for MLAG Updates, and also stores the client
@@ -286,6 +287,24 @@ extern int zserv_send_message(struct zserv *client, struct stream *msg);
  */
 extern struct zserv *zserv_find_client(uint8_t proto, unsigned short instance);
 
+/*
+ * Retrieve a client by its protocol, instance number, and session id.
+ *
+ * proto
+ *    protocol number
+ *
+ * instance
+ *    instance number
+ *
+ * session_id
+ *    session id
+ *
+ * Returns:
+ *    The Zebra API client.
+ */
+struct zserv *zserv_find_client_session(uint8_t proto, unsigned short instance,
+                                       uint32_t session_id);
+
 /*
  * Close a client.
  *