diff --git a/doc/user/sharp.rst b/doc/user/sharp.rst index dd0e67d4b7..1c474193f2 100644 --- a/doc/user/sharp.rst +++ b/doc/user/sharp.rst @@ -125,3 +125,15 @@ keyword. At present, no sharp commands will be preserved in the config. single subtype. The messages must specify a protocol daemon by name, and can include optional zapi ``instance`` and ``session`` values. + +.. index:: sharp create session +.. clicmd:: sharp create session (1-1024) + + Create an additional zapi client session for testing, using the + specified session id. + +.. index:: sharp remove session +.. clicmd:: sharp remove session (1-1024) + + Remove a test zapi client session that was created with the + specified session id. diff --git a/lib/zclient.c b/lib/zclient.c index aa5fa082a1..793864243c 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -164,7 +164,7 @@ void zclient_stop(struct zclient *zclient) int i; if (zclient_debug) - zlog_debug("zclient stopped"); + zlog_debug("zclient %p stopped", zclient); /* Stop threads. */ THREAD_OFF(zclient->t_read); diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c index 72e9c22f17..48220d1c9b 100644 --- a/sharpd/sharp_vty.c +++ b/sharpd/sharp_vty.c @@ -547,6 +547,34 @@ DEFPY (logpump, return CMD_SUCCESS; } +DEFPY (create_session, + create_session_cmd, + "sharp create session (1-1024)", + "Sharp Routing Protocol\n" + "Create data\n" + "Create a test session\n" + "Session ID\n") +{ + if (sharp_zclient_create(session) != 0) { + vty_out(vty, "%% Client session error\n"); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + +DEFPY (remove_session, + remove_session_cmd, + "sharp remove session (1-1024)", + "Sharp Routing Protocol\n" + "Remove data\n" + "Remove a test session\n" + "Session ID\n") +{ + sharp_zclient_delete(session); + return CMD_SUCCESS; +} + DEFPY (send_opaque, send_opaque_cmd, "sharp send opaque type (1-255) (1-1000)$count", @@ -626,6 +654,8 @@ void sharp_vty_init(void) install_element(ENABLE_NODE, &sharp_lsp_prefix_v4_cmd); install_element(ENABLE_NODE, &sharp_remove_lsp_prefix_v4_cmd); install_element(ENABLE_NODE, &logpump_cmd); + install_element(ENABLE_NODE, &create_session_cmd); + install_element(ENABLE_NODE, &remove_session_cmd); install_element(ENABLE_NODE, &send_opaque_cmd); install_element(ENABLE_NODE, &send_opaque_unicast_cmd); install_element(ENABLE_NODE, &send_opaque_reg_cmd); diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index 6ebc04b9eb..baa4e2ad5b 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -25,14 +25,9 @@ #include "command.h" #include "network.h" #include "prefix.h" -#include "routemap.h" -#include "table.h" #include "stream.h" #include "memory.h" #include "zclient.h" -#include "filter.h" -#include "plist.h" -#include "log.h" #include "nexthop.h" #include "nexthop_group.h" @@ -44,9 +39,41 @@ struct zclient *zclient = NULL; /* For registering threads. */ -extern struct thread_master *master; +struct thread_master *master; -/* Inteface addition message from zebra. */ +/* Privs info */ +struct zebra_privs_t sharp_privs; + +DEFINE_MTYPE_STATIC(SHARPD, ZC, "Test zclients"); + +/* Struct to hold list of test zclients */ +struct sharp_zclient { + struct sharp_zclient *prev; + struct sharp_zclient *next; + struct zclient *client; +}; + +/* Head of test zclient list */ +static struct sharp_zclient *sharp_clients_head; + +static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS); + +/* Utility to add a test zclient struct to the list */ +static void add_zclient(struct zclient *client) +{ + struct sharp_zclient *node; + + node = XCALLOC(MTYPE_ZC, sizeof(struct sharp_zclient)); + + node->client = client; + + node->next = sharp_clients_head; + if (sharp_clients_head) + sharp_clients_head->prev = node; + sharp_clients_head = node; +} + +/* Interface addition message from zebra. */ static int sharp_ifp_create(struct interface *ifp) { return 0; @@ -480,6 +507,62 @@ static int sharp_redistribute_route(ZAPI_CALLBACK_ARGS) return 0; } +/* Add a zclient with a specified session id, for testing. */ +int sharp_zclient_create(uint32_t session_id) +{ + struct zclient *client; + struct sharp_zclient *node; + + /* Check for duplicates */ + for (node = sharp_clients_head; node != NULL; node = node->next) { + if (node->client->session_id == session_id) + return -1; + } + + client = zclient_new(master, &zclient_options_default); + client->sock = -1; + client->session_id = session_id; + + zclient_init(client, ZEBRA_ROUTE_SHARP, 0, &sharp_privs); + + /* Register handlers for messages we expect this session to see */ + client->opaque_msg_handler = sharp_opaque_handler; + + /* Enqueue on the list of test clients */ + add_zclient(client); + + return 0; +} + +/* Delete one of the extra test zclients */ +int sharp_zclient_delete(uint32_t session_id) +{ + struct sharp_zclient *node; + + /* Search for session */ + for (node = sharp_clients_head; node != NULL; node = node->next) { + if (node->client->session_id == session_id) { + /* Dequeue from list */ + if (node->next) + node->next->prev = node->prev; + if (node->prev) + node->prev->next = node->next; + if (node == sharp_clients_head) + sharp_clients_head = node->next; + + /* Clean up zclient */ + zclient_stop(node->client); + zclient_free(node->client); + + /* Free memory */ + XFREE(MTYPE_ZC, node); + break; + } + } + + return 0; +} + /* Handler for opaque messages */ static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS) { @@ -491,7 +574,7 @@ static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS) if (zclient_opaque_decode(s, &info) != 0) return -1; - zlog_debug("%s: [%d] received opaque type %u", __func__, + zlog_debug("%s: [%u] received opaque type %u", __func__, zclient->session_id, info.type); return 0; @@ -564,8 +647,6 @@ void sharp_opaque_reg_send(bool is_reg, uint32_t proto, uint32_t instance, } -extern struct zebra_privs_t sharp_privs; - void sharp_zebra_init(void) { struct zclient_options opt = {.receive_notify = true}; diff --git a/sharpd/sharp_zebra.h b/sharpd/sharp_zebra.h index 7604f4b0a4..cb2f38a6ab 100644 --- a/sharpd/sharp_zebra.h +++ b/sharpd/sharp_zebra.h @@ -24,6 +24,10 @@ extern void sharp_zebra_init(void); +/* Add and delete extra zapi client sessions, for testing */ +int sharp_zclient_create(uint32_t session_id); +int sharp_zclient_delete(uint32_t session_id); + extern void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label); extern void route_add(const struct prefix *p, vrf_id_t, uint8_t instance, const struct nexthop_group *nhg,