sharpd,zebra: unicast support for zapi messages

Distinguish between unicast and broadcast opaque messages
in zebra handler code. Add cli and internal api changes to
have sharpd send unicast opaque messages. Add opaque cli
commands to the sharp user doc.

Signed-off-by: Mark Stapp <mjs@voltanet.io>
This commit is contained in:
Mark Stapp 2020-06-08 16:38:36 -04:00
parent 478ff17be6
commit c8b27f2ad9
6 changed files with 89 additions and 25 deletions

View File

@ -103,3 +103,25 @@ keyword. At present, no sharp commands will be preserved in the config.
nexthops are specified in nexthop-group ``NAME``. If ``prefix`` is
specified, remove label bindings from the route of type ``TYPE``
also.
.. index:: sharp send opaque
.. clicmd:: sharp send opaque type (1-255) (1-1000)
Send opaque ZAPI messages with subtype ``type``. Sharpd will send
a stream of messages if the count is greater than one.
.. index:: sharp send opaque unicast
.. clicmd:: sharp send opaque unicast type (1-255) $proto_str [{instance (0-1000) | session (1-1000)}] (1-1000)
Send unicast opaque ZAPI messages with subtype ``type``. The
protocol, instance, and session_id identify a single target zapi
client. Sharpd will send a stream of messages if the count is
greater than one.
.. index:: sharp send opaque reg unreg
.. clicmd:: sharp send opaque <reg | unreg> $proto_str [{instance (0-1000) | session (1-1000)}] type (1-1000)
Send opaque ZAPI registration and unregistration messages for a
single subtype. The messages must specify a protocol daemon by
name, and can include optional zapi ``instance`` and ``session``
values.

View File

@ -557,7 +557,34 @@ DEFPY (send_opaque,
"Type code to send\n"
"Number of messages to send\n")
{
sharp_opaque_send(type, count);
sharp_opaque_send(type, 0, 0, 0, count);
return CMD_SUCCESS;
}
DEFPY (send_opaque_unicast,
send_opaque_unicast_cmd,
"sharp send opaque unicast type (1-255) \
" FRR_IP_REDIST_STR_ZEBRA "$proto_str \
[{instance (0-1000) | session (1-1000)}] (1-1000)$count",
SHARP_STR
"Send messages for testing\n"
"Send opaque messages\n"
"Send unicast messages\n"
"Type code to send\n"
"Type code to send\n"
FRR_IP_REDIST_HELP_STR_ZEBRA
"Daemon instance\n"
"Daemon instance\n"
"Session ID\n"
"Session ID\n"
"Number of messages to send\n")
{
uint32_t proto;
proto = proto_redistnum(AFI_IP, proto_str);
sharp_opaque_send(type, proto, instance, session, count);
return CMD_SUCCESS;
}
@ -600,6 +627,7 @@ void sharp_vty_init(void)
install_element(ENABLE_NODE, &sharp_remove_lsp_prefix_v4_cmd);
install_element(ENABLE_NODE, &logpump_cmd);
install_element(ENABLE_NODE, &send_opaque_cmd);
install_element(ENABLE_NODE, &send_opaque_unicast_cmd);
install_element(ENABLE_NODE, &send_opaque_reg_cmd);
install_element(VIEW_NODE, &show_debugging_sharpd_cmd);

View File

@ -491,7 +491,8 @@ static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS)
if (zclient_opaque_decode(s, &info) != 0)
return -1;
zlog_debug("%s: received opaque type %u", __func__, info.type);
zlog_debug("%s: [%d] received opaque type %u", __func__,
zclient->session_id, info.type);
return 0;
}
@ -499,7 +500,8 @@ static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS)
/*
* Send OPAQUE messages, using subtype 'type'.
*/
void sharp_opaque_send(uint32_t type, uint32_t count)
void sharp_opaque_send(uint32_t type, uint32_t proto, uint32_t instance,
uint32_t session_id, uint32_t count)
{
uint8_t buf[32];
int ret;
@ -513,9 +515,15 @@ void sharp_opaque_send(uint32_t type, uint32_t count)
buf[i] = 255;
}
/* Send some messages */
/* Send some messages - broadcast and unicast are supported */
for (i = 0; i < count; i++) {
ret = zclient_send_opaque(zclient, type, buf, sizeof(buf));
if (proto == 0)
ret = zclient_send_opaque(zclient, type, buf,
sizeof(buf));
else
ret = zclient_send_opaque_unicast(zclient, type, proto,
instance, session_id,
buf, sizeof(buf));
if (ret < 0) {
zlog_debug("%s: send_opaque() failed => %d",
__func__, ret);

View File

@ -46,7 +46,8 @@ int sharp_install_lsps_helper(bool install_p, const struct prefix *p,
const struct nexthop_group *backup_nhg);
/* Send OPAQUE messages, using subtype 'type'. */
void sharp_opaque_send(uint32_t type, uint32_t count);
void sharp_opaque_send(uint32_t type, uint32_t proto, uint32_t instance,
uint32_t session_id, uint32_t count);
/* Send OPAQUE registration messages, using subtype 'type'. */
void sharp_opaque_reg_send(bool is_reg, uint32_t proto, uint32_t instance,

View File

@ -394,9 +394,25 @@ static int dispatch_opq_messages(struct stream_fifo *msg_fifo)
for (client = reg->clients; client; client = client->next) {
dup = NULL;
/* Copy message if necessary */
if (client->next)
dup = stream_dup(msg);
if (CHECK_FLAG(info.flags, ZAPI_OPAQUE_FLAG_UNICAST)) {
if (client->proto != info.proto ||
client->instance != info.instance ||
client->session_id != info.session_id)
continue;
if (IS_ZEBRA_DEBUG_RECV)
zlog_debug("%s: found matching unicast client %s",
__func__,
opq_client2str(buf,
sizeof(buf),
client));
} else {
/* Copy message if more clients */
if (client->next)
dup = stream_dup(msg);
}
/*
* TODO -- this isn't ideal: we're going through an
@ -438,6 +454,10 @@ static int dispatch_opq_messages(struct stream_fifo *msg_fifo)
if (dup)
stream_free(dup);
}
/* If unicast, we're done */
if (CHECK_FLAG(info.flags, ZAPI_OPAQUE_FLAG_UNICAST))
break;
}
drop_it:

View File

@ -811,14 +811,6 @@ struct zserv *zserv_acquire_client(uint8_t proto, unsigned short instance,
*/
void zserv_release_client(struct zserv *client)
{
bool cleanup_p = false;
const char *proto_str;
uint16_t instance;
/* Capture some info for debugging */
proto_str = zebra_route_string(client->proto);
instance = client->instance;
/*
* Once we've decremented the client object's refcount, it's possible
* for it to be deleted as soon as we release the lock, so we won't
@ -833,13 +825,10 @@ void zserv_release_client(struct zserv *client)
* session is closed, schedule cleanup on the zebra
* main pthread.
*/
if (client->is_closed) {
if (client->is_closed)
thread_add_event(zrouter.master,
zserv_handle_client_fail,
client, 0, &client->t_cleanup);
cleanup_p = true;
}
}
}
@ -847,10 +836,6 @@ void zserv_release_client(struct zserv *client)
* Cleanup must take place on the zebra main pthread, so we've
* scheduled an event.
*/
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("%s: %s clean-up for client '%s'[%u]",
__func__, (cleanup_p ? "scheduled" : "NO"),
proto_str, instance);
}
/*