lib, zebra: include source client zapi info in opaque messages

Include the sending zapi client info (proto, instance, and
session id) in each opaque zapi message. Add opaque 'init'
apis for clients who want to encode their opaque data inline,
into the zclient's internal stream buffer. Use these init apis
in the TE/link-state lib code, instead of hand-coding the
zapi opaque header info.

Signed-off-by: Mark Stapp <mjs@labn.net>
This commit is contained in:
Mark Stapp 2023-05-29 13:04:24 -04:00
parent 3cbc7150bb
commit ef8e3ac02c
4 changed files with 98 additions and 67 deletions

View File

@ -1138,31 +1138,13 @@ int ls_unregister(struct zclient *zclient, bool server)
int ls_request_sync(struct zclient *zclient) int ls_request_sync(struct zclient *zclient)
{ {
struct stream *s;
uint16_t flags = 0;
/* Check buffer size */ /* Check buffer size */
if (STREAM_SIZE(zclient->obuf) if (STREAM_SIZE(zclient->obuf)
< (ZEBRA_HEADER_SIZE + 3 * sizeof(uint32_t))) < (ZEBRA_HEADER_SIZE + 3 * sizeof(uint32_t)))
return -1; return -1;
s = zclient->obuf; /* No data with this message */
stream_reset(s); return zclient_send_opaque(zclient, LINK_STATE_SYNC, NULL, 0);
zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT);
/* Set type and flags */
stream_putl(s, LINK_STATE_SYNC);
stream_putw(s, flags);
/* Send destination client info */
stream_putc(s, zclient->redist_default);
stream_putw(s, zclient->instance);
stream_putl(s, zclient->session_id);
/* Put length into the header at the start of the stream. */
stream_putw_at(s, 0, stream_get_endp(s));
return zclient_send_message(zclient);
} }
static struct ls_node *ls_parse_node(struct stream *s) static struct ls_node *ls_parse_node(struct stream *s)
@ -1623,23 +1605,15 @@ int ls_send_msg(struct zclient *zclient, struct ls_message *msg,
(ZEBRA_HEADER_SIZE + sizeof(uint32_t) + sizeof(msg))) (ZEBRA_HEADER_SIZE + sizeof(uint32_t) + sizeof(msg)))
return -1; return -1;
/* Init the message, then encode the data inline. */
if (dst == NULL)
zapi_opaque_init(zclient, LINK_STATE_UPDATE, flags);
else
zapi_opaque_unicast_init(zclient, LINK_STATE_UPDATE, flags,
dst->proto, dst->instance,
dst->session_id);
s = zclient->obuf; s = zclient->obuf;
stream_reset(s);
zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT);
/* Set sub-type, flags and destination for unicast message */
stream_putl(s, LINK_STATE_UPDATE);
if (dst != NULL) {
SET_FLAG(flags, ZAPI_OPAQUE_FLAG_UNICAST);
stream_putw(s, flags);
/* Send destination client info */
stream_putc(s, dst->proto);
stream_putw(s, dst->instance);
stream_putl(s, dst->session_id);
} else {
stream_putw(s, flags);
}
/* Format Link State message */ /* Format Link State message */
if (ls_format_msg(s, msg) < 0) { if (ls_format_msg(s, msg) < 0) {

View File

@ -3823,6 +3823,53 @@ enum zclient_send_status zclient_send_mlag_data(struct zclient *client,
return zclient_send_message(client); return zclient_send_message(client);
} }
/*
* Init/header setup for opaque zapi messages
*/
enum zclient_send_status zapi_opaque_init(struct zclient *zclient,
uint32_t type, uint16_t flags)
{
struct stream *s;
s = zclient->obuf;
stream_reset(s);
zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT);
/* Send sub-type and flags */
stream_putl(s, type);
stream_putw(s, flags);
/* Source daemon identifiers */
stream_putc(s, zclient->redist_default);
stream_putw(s, zclient->instance);
stream_putl(s, zclient->session_id);
return ZCLIENT_SEND_SUCCESS;
}
/*
* Init, header setup for opaque unicast messages.
*/
enum zclient_send_status
zapi_opaque_unicast_init(struct zclient *zclient, uint32_t type, uint16_t flags,
uint8_t proto, uint16_t instance, uint32_t session_id)
{
struct stream *s;
s = zclient->obuf;
/* Common init */
zapi_opaque_init(zclient, type, flags | ZAPI_OPAQUE_FLAG_UNICAST);
/* Send destination client info */
stream_putc(s, proto);
stream_putw(s, instance);
stream_putl(s, session_id);
return ZCLIENT_SEND_SUCCESS;
}
/* /*
* Send an OPAQUE message, contents opaque to zebra. The message header * Send an OPAQUE message, contents opaque to zebra. The message header
* is a message subtype. * is a message subtype.
@ -3840,16 +3887,12 @@ enum zclient_send_status zclient_send_opaque(struct zclient *zclient,
return ZCLIENT_SEND_FAILURE; return ZCLIENT_SEND_FAILURE;
s = zclient->obuf; s = zclient->obuf;
stream_reset(s);
zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT); zapi_opaque_init(zclient, type, flags);
/* Send sub-type and flags */
stream_putl(s, type);
stream_putw(s, flags);
/* Send opaque data */ /* Send opaque data */
stream_write(s, data, datasize); if (datasize > 0)
stream_write(s, data, datasize);
/* Put length into the header at the start of the stream. */ /* Put length into the header at the start of the stream. */
stream_putw_at(s, 0, stream_get_endp(s)); stream_putw_at(s, 0, stream_get_endp(s));
@ -3876,22 +3919,14 @@ zclient_send_opaque_unicast(struct zclient *zclient, uint32_t type,
return ZCLIENT_SEND_FAILURE; return ZCLIENT_SEND_FAILURE;
s = zclient->obuf; s = zclient->obuf;
stream_reset(s);
zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT); /* Common init */
zapi_opaque_unicast_init(zclient, type, flags, proto, instance,
/* Send sub-type and flags */ session_id);
SET_FLAG(flags, ZAPI_OPAQUE_FLAG_UNICAST);
stream_putl(s, type);
stream_putw(s, flags);
/* Send destination client info */
stream_putc(s, proto);
stream_putw(s, instance);
stream_putl(s, session_id);
/* Send opaque data */ /* Send opaque data */
stream_write(s, data, datasize); if (datasize > 0)
stream_write(s, data, datasize);
/* Put length into the header at the start of the stream. */ /* Put length into the header at the start of the stream. */
stream_putw_at(s, 0, stream_get_endp(s)); stream_putw_at(s, 0, stream_get_endp(s));
@ -3910,11 +3945,16 @@ int zclient_opaque_decode(struct stream *s, struct zapi_opaque_msg *info)
STREAM_GETL(s, info->type); STREAM_GETL(s, info->type);
STREAM_GETW(s, info->flags); STREAM_GETW(s, info->flags);
/* Decode unicast client info if present */ /* Decode sending daemon info */
STREAM_GETC(s, info->src_proto);
STREAM_GETW(s, info->src_instance);
STREAM_GETL(s, info->src_session_id);
/* Decode unicast destination info, if present */
if (CHECK_FLAG(info->flags, ZAPI_OPAQUE_FLAG_UNICAST)) { if (CHECK_FLAG(info->flags, ZAPI_OPAQUE_FLAG_UNICAST)) {
STREAM_GETC(s, info->proto); STREAM_GETC(s, info->dest_proto);
STREAM_GETW(s, info->instance); STREAM_GETW(s, info->dest_instance);
STREAM_GETL(s, info->session_id); STREAM_GETL(s, info->dest_session_id);
} }
info->len = STREAM_READABLE(s); info->len = STREAM_READABLE(s);

View File

@ -1176,16 +1176,33 @@ zclient_send_opaque_unicast(struct zclient *zclient, uint32_t type,
uint32_t session_id, const uint8_t *data, uint32_t session_id, const uint8_t *data,
size_t datasize); size_t datasize);
/* Init functions also provided for clients who want to encode their
* data inline into the zclient's stream buffer. Please use these instead
* of hand-encoding the header info, since that may change over time.
* Note that these will reset the zclient's outbound stream before encoding.
*/
enum zclient_send_status zapi_opaque_init(struct zclient *zclient,
uint32_t type, uint16_t flags);
enum zclient_send_status
zapi_opaque_unicast_init(struct zclient *zclient, uint32_t type, uint16_t flags,
uint8_t proto, uint16_t instance, uint32_t session_id);
/* Struct representing the decoded opaque header info */ /* Struct representing the decoded opaque header info */
struct zapi_opaque_msg { struct zapi_opaque_msg {
uint32_t type; /* Subtype */ uint32_t type; /* Subtype */
uint16_t len; /* len after zapi header and this info */ uint16_t len; /* len after zapi header and this info */
uint16_t flags; uint16_t flags;
/* Client-specific info - *if* UNICAST flag is set */ /* Sending client info */
uint8_t proto; uint8_t src_proto;
uint16_t instance; uint16_t src_instance;
uint32_t session_id; uint32_t src_session_id;
/* Destination client info - *if* UNICAST flag is set */
uint8_t dest_proto;
uint16_t dest_instance;
uint32_t dest_session_id;
}; };
#define ZAPI_OPAQUE_FLAG_UNICAST 0x01 #define ZAPI_OPAQUE_FLAG_UNICAST 0x01

View File

@ -381,9 +381,9 @@ static int dispatch_opq_messages(struct stream_fifo *msg_fifo)
if (CHECK_FLAG(info.flags, ZAPI_OPAQUE_FLAG_UNICAST)) { if (CHECK_FLAG(info.flags, ZAPI_OPAQUE_FLAG_UNICAST)) {
if (client->proto != info.proto || if (client->proto != info.dest_proto ||
client->instance != info.instance || client->instance != info.dest_instance ||
client->session_id != info.session_id) client->session_id != info.dest_session_id)
continue; continue;
if (IS_ZEBRA_DEBUG_RECV && if (IS_ZEBRA_DEBUG_RECV &&