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
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
/* 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;
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)
client->proto = proto;
client->instance = instance;
+ client->session_id = session_id;
/* Graceful restart processing for client connect */
zebra_gr_client_reconnect(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");
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) {
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,
/* 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
*/
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.
*