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 &&