]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: add notifications for opaque zapi messages
authorMark Stapp <mjs@labn.net>
Wed, 31 May 2023 20:22:16 +0000 (16:22 -0400)
committerMark Stapp <mjs@labn.net>
Fri, 23 Jun 2023 12:57:37 +0000 (08:57 -0400)
Add a new notification zapi message type. A zapi client
that uses opaque messages can register to be notified
when a server for an opaque type is present.

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

index 00b897dca1f241a8b0884cbea635273f742374bb..df9b6c71763311d4fdbcd4615b92b6630fea2d0a 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -457,7 +457,9 @@ static const struct zebra_desc_table command_types[] = {
        DESC_ENTRY(ZEBRA_TC_CLASS_ADD),
        DESC_ENTRY(ZEBRA_TC_CLASS_DELETE),
        DESC_ENTRY(ZEBRA_TC_FILTER_ADD),
-       DESC_ENTRY(ZEBRA_TC_FILTER_DELETE)};
+       DESC_ENTRY(ZEBRA_TC_FILTER_DELETE),
+       DESC_ENTRY(ZEBRA_OPAQUE_NOTIFY)
+};
 #undef DESC_ENTRY
 
 static const struct zebra_desc_table unknown = {0, "unknown", '?'};
index b3b3c923025d4dc8f45f5baf1465676db6f1368e..1654c984bd32359302594f3538fc57572e110637 100644 (file)
@@ -4512,3 +4512,125 @@ int zclient_send_zebra_gre_request(struct zclient *client,
        zclient_send_message(client);
        return 0;
 }
+
+
+/*
+ * Opaque notification features
+ */
+
+/*
+ * Common encode helper for opaque notifications, both registration
+ * and async notification messages.
+ */
+static int opaque_notif_encode_common(struct stream *s, uint32_t msg_type,
+                                     bool request, bool reg, uint8_t proto,
+                                     uint16_t instance, uint32_t session_id)
+{
+       int ret = 0;
+       uint8_t val = 0;
+
+       stream_reset(s);
+
+       zclient_create_header(s, ZEBRA_OPAQUE_NOTIFY, VRF_DEFAULT);
+
+       /* Notification or request */
+       if (request)
+               val = 1;
+       stream_putc(s, val);
+
+       if (reg)
+               val = 1;
+       else
+               val = 0;
+       stream_putc(s, val);
+
+       stream_putl(s, msg_type);
+
+       stream_putc(s, proto);
+       stream_putw(s, instance);
+       stream_putl(s, session_id);
+
+       /* And capture message length */
+       stream_putw_at(s, 0, stream_get_endp(s));
+
+       return ret;
+}
+
+/*
+ * Encode a zapi opaque message type notification into buffer 's'
+ */
+int zclient_opaque_notif_encode(struct stream *s, uint32_t msg_type, bool reg,
+                               uint8_t proto, uint16_t instance,
+                               uint32_t session_id)
+{
+       return opaque_notif_encode_common(s, msg_type, false /* !request */,
+                                         reg, proto, instance, session_id);
+}
+
+/*
+ * Decode an incoming zapi opaque message type notification
+ */
+int zclient_opaque_notif_decode(struct stream *s,
+                               struct zapi_opaque_notif_info *info)
+{
+       uint8_t val;
+
+       memset(info, 0, sizeof(*info));
+
+       STREAM_GETC(s, val); /* Registration or notification */
+       info->request = (val != 0);
+
+       STREAM_GETC(s, val);
+       info->reg = (val != 0);
+
+       STREAM_GETL(s, info->msg_type);
+
+       STREAM_GETC(s, info->proto);
+       STREAM_GETW(s, info->instance);
+       STREAM_GETL(s, info->session_id);
+
+       return 0;
+
+stream_failure:
+       return -1;
+}
+
+/*
+ * Encode and send a zapi opaque message type notification request to zebra
+ */
+enum zclient_send_status zclient_opaque_request_notify(struct zclient *zclient,
+                                                      uint32_t msgtype)
+{
+       struct stream *s;
+
+       if (!zclient || zclient->sock < 0)
+               return ZCLIENT_SEND_FAILURE;
+
+       s = zclient->obuf;
+
+       opaque_notif_encode_common(s, msgtype, true /* request */,
+                                  true /* register */, zclient->redist_default,
+                                  zclient->instance, zclient->session_id);
+
+       return zclient_send_message(zclient);
+}
+
+/*
+ * Encode and send a request to drop notifications for an opaque message type.
+ */
+enum zclient_send_status zclient_opaque_drop_notify(struct zclient *zclient,
+                                                   uint32_t msgtype)
+{
+       struct stream *s;
+
+       if (!zclient || zclient->sock < 0)
+               return ZCLIENT_SEND_FAILURE;
+
+       s = zclient->obuf;
+
+       opaque_notif_encode_common(s, msgtype, true /* req */,
+                                  false /* unreg */, zclient->redist_default,
+                                  zclient->instance, zclient->session_id);
+
+       return zclient_send_message(zclient);
+}
index fe296fe95058356419d4675a333d35520dcd0e90..316dd4cd68b9a7601ffa72f76aa696a01b64ace8 100644 (file)
@@ -87,7 +87,9 @@ enum zserv_client_capabilities {
 extern struct sockaddr_storage zclient_addr;
 extern socklen_t zclient_addr_len;
 
-/* Zebra message types. */
+/* Zebra message types. Please update the corresponding
+ * command_types array with any changes!
+ */
 typedef enum {
        ZEBRA_INTERFACE_ADD,
        ZEBRA_INTERFACE_DELETE,
@@ -232,7 +234,11 @@ typedef enum {
        ZEBRA_TC_CLASS_DELETE,
        ZEBRA_TC_FILTER_ADD,
        ZEBRA_TC_FILTER_DELETE,
+       ZEBRA_OPAQUE_NOTIFY,
 } zebra_message_types_t;
+/* Zebra message types. Please update the corresponding
+ * command_types array with any changes!
+ */
 
 enum zebra_error_types {
        ZEBRA_UNKNOWN_ERROR,    /* Error of unknown type */
@@ -1218,6 +1224,34 @@ struct zapi_opaque_reg_info {
        uint32_t session_id;
 };
 
+/* Simple struct conveying information about opaque notifications.
+ * Daemons can request notifications about the status of registration for
+ * opaque message types. For example, a client daemon can request notification
+ * when a server registers to receive a certain message code. Or a server can
+ * request notification when a subscriber registers for its output.
+ */
+struct zapi_opaque_notif_info {
+       bool request;      /* Request to register, or notification from zebra */
+       bool reg;          /* Register or unregister */
+       uint32_t msg_type; /* Target message code */
+
+       /* For notif registration, zapi info for the client.
+        * For notifications, zapi info for the message's server/registrant.
+        * For notification that there is no server/registrant, not present.
+        */
+       uint8_t proto;
+       uint16_t instance;
+       uint32_t session_id;
+};
+
+/* The same ZAPI message is used for daemon->zebra requests, and for
+ * zebra->daemon notifications.
+ * Daemons send 'request' true, and 'reg' true or false.
+ * Zebra sends 'request' false, 'reg' set if the notification is a
+ * server/receiver registration for the message type, and false if the event
+ * is the end of registrations.
+ */
+
 /* Decode incoming opaque */
 int zclient_opaque_decode(struct stream *msg, struct zapi_opaque_msg *info);
 
@@ -1228,6 +1262,19 @@ enum zclient_send_status zclient_unregister_opaque(struct zclient *zclient,
 int zapi_opaque_reg_decode(struct stream *msg,
                           struct zapi_opaque_reg_info *info);
 
+/* Opaque notification features */
+enum zclient_send_status zclient_opaque_request_notify(struct zclient *zclient,
+                                                      uint32_t msgtype);
+enum zclient_send_status zclient_opaque_drop_notify(struct zclient *zclient,
+                                                   uint32_t msgtype);
+
+/* Encode, decode an incoming zapi opaque notification */
+int zclient_opaque_notif_encode(struct stream *s, uint32_t msg_type,
+                               bool reg /* register or unreg*/, uint8_t proto,
+                               uint16_t instance, uint32_t session_id);
+int zclient_opaque_notif_decode(struct stream *s,
+                               struct zapi_opaque_notif_info *info);
+
 /*
  * Registry of opaque message types. Please do not reuse an in-use
  * type code; some daemons are likely relying on it.