lib: add notifications for opaque zapi messages

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>
This commit is contained in:
Mark Stapp 2023-05-31 16:22:16 -04:00
parent ef8e3ac02c
commit 06647109ab
3 changed files with 173 additions and 2 deletions

View File

@ -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", '?'};

View 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);
}

View 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.