summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/user/sharp.rst22
-rw-r--r--sharpd/sharp_vty.c30
-rw-r--r--sharpd/sharp_zebra.c16
-rw-r--r--sharpd/sharp_zebra.h3
-rw-r--r--zebra/zebra_opaque.c26
-rw-r--r--zebra/zserv.c17
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 <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.
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);
}
/*