From c8b27f2ad98f71842e506b8ccff403971769d8cb Mon Sep 17 00:00:00 2001 From: Mark Stapp Date: Mon, 8 Jun 2020 16:38:36 -0400 Subject: [PATCH] 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 --- doc/user/sharp.rst | 22 ++++++++++++++++++++++ sharpd/sharp_vty.c | 30 +++++++++++++++++++++++++++++- sharpd/sharp_zebra.c | 16 ++++++++++++---- sharpd/sharp_zebra.h | 3 ++- zebra/zebra_opaque.c | 26 +++++++++++++++++++++++--- zebra/zserv.c | 17 +---------------- 6 files changed, 89 insertions(+), 25 deletions(-) diff --git a/doc/user/sharp.rst b/doc/user/sharp.rst index 199685cdfb..dd0e67d4b7 100644 --- a/doc/user/sharp.rst +++ b/doc/user/sharp.rst @@ -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 $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. diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c index bad59d172f..72e9c22f17 100644 --- a/sharpd/sharp_vty.c +++ b/sharpd/sharp_vty.c @@ -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); diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index d94e272dd2..6ebc04b9eb 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -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); diff --git a/sharpd/sharp_zebra.h b/sharpd/sharp_zebra.h index 7c714b52d3..7604f4b0a4 100644 --- a/sharpd/sharp_zebra.h +++ b/sharpd/sharp_zebra.h @@ -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, diff --git a/zebra/zebra_opaque.c b/zebra/zebra_opaque.c index 8fb02114d1..41e278f71b 100644 --- a/zebra/zebra_opaque.c +++ b/zebra/zebra_opaque.c @@ -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: diff --git a/zebra/zserv.c b/zebra/zserv.c index cb863b258c..99a85fd2ce 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -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); } /*