From: Mark Stapp Date: Mon, 6 Apr 2020 20:10:13 +0000 (-0400) Subject: lib: add OPAQUE zapi message X-Git-Tag: base_7.5~316^2~10 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=ff491140956129580a7d68ea8510b521cce80c9d;p=mirror%2Ffrr.git lib: add OPAQUE zapi message 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 --- diff --git a/lib/log.c b/lib/log.c index 9b0f5b3d85..089a3e3a07 100644 --- 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", '?'}; diff --git a/lib/zclient.c b/lib/zclient.c index 02532e7069..9b1ff7237f 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -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; } diff --git a/lib/zclient.h b/lib/zclient.h index feaabc0549..4682216d89 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -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. */