forked from Mirror/frr
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 <mjs@voltanet.io>
This commit is contained in:
parent
f8c511cddb
commit
ff49114095
|
@ -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", '?'};
|
||||
|
|
124
lib/zclient.c
124
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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue