]> git.puffer.fish Git - mirror/frr.git/commitdiff
lib: add OPAQUE zapi message
authorMark Stapp <mjs@voltanet.io>
Mon, 6 Apr 2020 20:10:13 +0000 (16:10 -0400)
committerMark Stapp <mjs@voltanet.io>
Tue, 2 Jun 2020 12:20:54 +0000 (08:20 -0400)
Add a zapi message type designed to carry opaque data. Add
'send' api, and prototype for client handler function. Also
add registration/unreg messages, so that clients can 'subscribe'
to receive these messages as they're passing through zebra.

Signed-off-by: Mark Stapp <mjs@voltanet.io>
lib/log.c
lib/zclient.c
lib/zclient.h

index 9b0f5b3d85c7d9631ff15a67432f5330ba8547d6..089a3e3a0713810901fd2291979d669ea08f3255 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -443,7 +443,10 @@ static const struct zebra_desc_table command_types[] = {
        DESC_ENTRY(ZEBRA_MLAG_CLIENT_UNREGISTER),
        DESC_ENTRY(ZEBRA_MLAG_FORWARD_MSG),
        DESC_ENTRY(ZEBRA_ERROR),
-       DESC_ENTRY(ZEBRA_CLIENT_CAPABILITIES)};
+       DESC_ENTRY(ZEBRA_CLIENT_CAPABILITIES),
+       DESC_ENTRY(ZEBRA_OPAQUE_MESSAGE),
+       DESC_ENTRY(ZEBRA_OPAQUE_REGISTER),
+       DESC_ENTRY(ZEBRA_OPAQUE_UNREGISTER)};
 #undef DESC_ENTRY
 
 static const struct zebra_desc_table unknown = {0, "unknown", '?'};
index 02532e7069f58c90665f9e7941ea2589af16d6fe..9b1ff7237fc4b305940af63db660db22d238f629 100644 (file)
@@ -3112,6 +3112,114 @@ static void zclient_mlag_handle_msg(ZAPI_CALLBACK_ARGS)
                (*zclient->mlag_handle_msg)(zclient->ibuf, length);
 }
 
+/*
+ * Send an OPAQUE message, contents opaque to zebra. The message header
+ * is a message subtype.
+ */
+int zclient_send_opaque(struct zclient *zclient, uint32_t type,
+                       const uint8_t *data, size_t datasize)
+{
+       int ret;
+       struct stream *s;
+
+       /* Check buffer size */
+       if (STREAM_SIZE(zclient->obuf) <
+           (ZEBRA_HEADER_SIZE + sizeof(type) + datasize))
+               return -1;
+
+       s = zclient->obuf;
+       stream_reset(s);
+
+       zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT);
+
+       /* Send sub-type */
+       stream_putl(s, type);
+
+       /* Send opaque data */
+       stream_write(s, data, datasize);
+
+       /* Put length into the header at the start of the stream. */
+       stream_putw_at(s, 0, stream_get_endp(s));
+
+       ret = zclient_send_message(zclient);
+
+       return ret;
+}
+
+/*
+ * Send a registration request for opaque messages with a specified subtype.
+ */
+int zclient_register_opaque(struct zclient *zclient, uint32_t type)
+{
+       int ret;
+       struct stream *s;
+
+       s = zclient->obuf;
+       stream_reset(s);
+
+       zclient_create_header(s, ZEBRA_OPAQUE_REGISTER, VRF_DEFAULT);
+
+       /* Send sub-type */
+       stream_putl(s, type);
+
+       /* Add zclient info */
+       stream_putc(s, zclient->redist_default);
+       stream_putw(s, zclient->instance);
+       stream_putl(s, zclient->session_id);
+
+       /* Put length at the first point of the stream. */
+       stream_putw_at(s, 0, stream_get_endp(s));
+
+       ret = zclient_send_message(zclient);
+
+       return ret;
+}
+
+/*
+ * Send an un-registration request for a specified opaque subtype.
+ */
+int zclient_unregister_opaque(struct zclient *zclient, uint32_t type)
+{
+       int ret;
+       struct stream *s;
+
+       s = zclient->obuf;
+       stream_reset(s);
+
+       zclient_create_header(s, ZEBRA_OPAQUE_UNREGISTER, VRF_DEFAULT);
+
+       /* Send sub-type */
+       stream_putl(s, type);
+
+       /* Add zclient info */
+       stream_putc(s, zclient->redist_default);
+       stream_putw(s, zclient->instance);
+       stream_putl(s, zclient->session_id);
+
+       /* Put length at the first point of the stream. */
+       stream_putw_at(s, 0, stream_get_endp(s));
+
+       ret = zclient_send_message(zclient);
+
+       return ret;
+}
+
+/* Utility to parse opaque registration info */
+int zapi_parse_opaque_reg(struct stream *s,
+                         struct zapi_opaque_reg_info *info)
+{
+       STREAM_GETL(s, info->type);
+       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)
 {
@@ -3417,6 +3525,22 @@ static int zclient_read(struct thread *thread)
                break;
        case ZEBRA_ERROR:
                zclient_handle_error(command, zclient, length, vrf_id);
+               break;
+       case ZEBRA_OPAQUE_MESSAGE:
+               if (zclient->opaque_msg_handler)
+                       (*zclient->opaque_msg_handler)(command, zclient, length,
+                                                      vrf_id);
+               break;
+       case ZEBRA_OPAQUE_REGISTER:
+               if (zclient->opaque_register_handler)
+                       (*zclient->opaque_register_handler)(command, zclient,
+                                                           length, vrf_id);
+               break;
+       case ZEBRA_OPAQUE_UNREGISTER:
+               if (zclient->opaque_unregister_handler)
+                       (*zclient->opaque_unregister_handler)(command, zclient,
+                                                           length, vrf_id);
+               break;
        default:
                break;
        }
index feaabc0549c0fb5f9ba29c4155e42886343f5cfd..4682216d89984dfb1f3f7b351c23086abc474298 100644 (file)
@@ -200,7 +200,10 @@ typedef enum {
        ZEBRA_MLAG_CLIENT_UNREGISTER,
        ZEBRA_MLAG_FORWARD_MSG,
        ZEBRA_ERROR,
-       ZEBRA_CLIENT_CAPABILITIES
+       ZEBRA_CLIENT_CAPABILITIES,
+       ZEBRA_OPAQUE_MESSAGE,
+       ZEBRA_OPAQUE_REGISTER,
+       ZEBRA_OPAQUE_UNREGISTER,
 } zebra_message_types_t;
 
 enum zebra_error_types {
@@ -339,6 +342,9 @@ struct zclient {
        int (*mlag_process_down)(void);
        int (*mlag_handle_msg)(struct stream *msg, int len);
        int (*handle_error)(enum zebra_error_types error);
+       int (*opaque_msg_handler)(ZAPI_CALLBACK_ARGS);
+       int (*opaque_register_handler)(ZAPI_CALLBACK_ARGS);
+       int (*opaque_unregister_handler)(ZAPI_CALLBACK_ARGS);
 };
 
 /* Zebra API message flag. */
@@ -833,6 +839,44 @@ extern void zclient_send_mlag_deregister(struct zclient *client);
 extern void zclient_send_mlag_data(struct zclient *client,
                                   struct stream *client_s);
 
+/*
+ * Send an OPAQUE message, contents opaque to zebra - but note that
+ * the length of the payload is restricted by the zclient's
+ * outgoing message buffer.
+ * The message header is a message subtype; please use the registry
+ * below to avoid sub-type collisions. Clients use the registration
+ * apis to manage the specific opaque subtypes they want to receive.
+ */
+int zclient_send_opaque(struct zclient *zclient, uint32_t type,
+                       const uint8_t *data, size_t datasize);
+
+/* Simple struct to convey registration/unreg requests */
+struct zapi_opaque_reg_info {
+       /* Message subtype */
+       uint32_t type;
+
+       /* Client session tuple */
+       uint8_t proto;
+       uint16_t instance;
+       uint32_t session_id;
+};
+
+int zclient_register_opaque(struct zclient *zclient, uint32_t type);
+int zclient_unregister_opaque(struct zclient *zclient, uint32_t type);
+int zapi_parse_opaque_reg(struct stream *msg,
+                         struct zapi_opaque_reg_info *info);
+
+/*
+ * Registry of opaque message types. Please do not reuse an in-use
+ * type code; some daemons are likely relying on it.
+ */
+enum zapi_opaque_registry {
+       /* Request link-state database dump, at restart for example */
+       LINK_STATE_REQUEST = 1,
+       /* Update containing link-state db info */
+       LINK_STATE_UPDATE = 2,
+};
+
 /* Send the hello message.
  * Returns 0 for success or -1 on an I/O error.
  */