From ef8e3ac02c4482bd6ef255578e325a98ec9c8e86 Mon Sep 17 00:00:00 2001 From: Mark Stapp Date: Mon, 29 May 2023 13:04:24 -0400 Subject: [PATCH] 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 --- lib/link_state.c | 46 +++++------------------ lib/zclient.c | 88 ++++++++++++++++++++++++++++++++------------ lib/zclient.h | 25 +++++++++++-- zebra/zebra_opaque.c | 6 +-- 4 files changed, 98 insertions(+), 67 deletions(-) diff --git a/lib/link_state.c b/lib/link_state.c index 58727a568b..6537f881ce 100644 --- a/lib/link_state.c +++ b/lib/link_state.c @@ -1138,31 +1138,13 @@ int ls_unregister(struct zclient *zclient, bool server) int ls_request_sync(struct zclient *zclient) { - struct stream *s; - uint16_t flags = 0; - /* Check buffer size */ if (STREAM_SIZE(zclient->obuf) < (ZEBRA_HEADER_SIZE + 3 * sizeof(uint32_t))) return -1; - s = zclient->obuf; - stream_reset(s); - - 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); + /* No data with this message */ + return zclient_send_opaque(zclient, LINK_STATE_SYNC, NULL, 0); } 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))) 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; - 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 */ if (ls_format_msg(s, msg) < 0) { diff --git a/lib/zclient.c b/lib/zclient.c index 8526cbfaa1..b3b3c92302 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -3823,6 +3823,53 @@ enum zclient_send_status zclient_send_mlag_data(struct zclient *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 * is a message subtype. @@ -3840,16 +3887,12 @@ enum zclient_send_status zclient_send_opaque(struct zclient *zclient, return ZCLIENT_SEND_FAILURE; 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); + zapi_opaque_init(zclient, type, flags); /* 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. */ 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; s = zclient->obuf; - stream_reset(s); - - zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT); - - /* Send sub-type and flags */ - 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); + /* Common init */ + zapi_opaque_unicast_init(zclient, type, flags, proto, instance, + session_id); /* 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. */ 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_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)) { - STREAM_GETC(s, info->proto); - STREAM_GETW(s, info->instance); - STREAM_GETL(s, info->session_id); + STREAM_GETC(s, info->dest_proto); + STREAM_GETW(s, info->dest_instance); + STREAM_GETL(s, info->dest_session_id); } info->len = STREAM_READABLE(s); diff --git a/lib/zclient.h b/lib/zclient.h index e43393fd70..fe296fe950 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -1176,16 +1176,33 @@ zclient_send_opaque_unicast(struct zclient *zclient, uint32_t type, uint32_t session_id, const uint8_t *data, 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 zapi_opaque_msg { uint32_t type; /* Subtype */ uint16_t len; /* len after zapi header and this info */ uint16_t flags; - /* Client-specific info - *if* UNICAST flag is set */ - uint8_t proto; - uint16_t instance; - uint32_t session_id; + /* Sending client info */ + uint8_t src_proto; + uint16_t src_instance; + 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 diff --git a/zebra/zebra_opaque.c b/zebra/zebra_opaque.c index 8ceb1f8dc5..2bd6ac084d 100644 --- a/zebra/zebra_opaque.c +++ b/zebra/zebra_opaque.c @@ -381,9 +381,9 @@ static int dispatch_opq_messages(struct stream_fifo *msg_fifo) if (CHECK_FLAG(info.flags, ZAPI_OPAQUE_FLAG_UNICAST)) { - if (client->proto != info.proto || - client->instance != info.instance || - client->session_id != info.session_id) + if (client->proto != info.dest_proto || + client->instance != info.dest_instance || + client->session_id != info.dest_session_id) continue; if (IS_ZEBRA_DEBUG_RECV && -- 2.39.5