xref: /spdk/module/bdev/nvme/bdev_mdns_client.c (revision dd98a248aed2b94b20b0717ce05a9db73b668ae0)
12796687dSParameswaran Krishnamurthy /*  SPDX-License-Identifier: BSD-3-Clause
22796687dSParameswaran Krishnamurthy  *  Copyright (c) 2022 Dell Inc, or its subsidiaries.
32796687dSParameswaran Krishnamurthy  *  All rights reserved.
42796687dSParameswaran Krishnamurthy  */
52796687dSParameswaran Krishnamurthy 
62796687dSParameswaran Krishnamurthy #include "spdk/stdinc.h"
72796687dSParameswaran Krishnamurthy #include "spdk/version.h"
82796687dSParameswaran Krishnamurthy 
92796687dSParameswaran Krishnamurthy #include "spdk_internal/event.h"
102796687dSParameswaran Krishnamurthy 
112796687dSParameswaran Krishnamurthy #include "spdk/assert.h"
122796687dSParameswaran Krishnamurthy #include "spdk/config.h"
132796687dSParameswaran Krishnamurthy #include "spdk/env.h"
142796687dSParameswaran Krishnamurthy #include "spdk/init.h"
152796687dSParameswaran Krishnamurthy #include "spdk/log.h"
162796687dSParameswaran Krishnamurthy #include "spdk/thread.h"
172796687dSParameswaran Krishnamurthy #include "spdk/trace.h"
182796687dSParameswaran Krishnamurthy #include "spdk/string.h"
192796687dSParameswaran Krishnamurthy #include "spdk/scheduler.h"
202796687dSParameswaran Krishnamurthy #include "spdk/rpc.h"
212796687dSParameswaran Krishnamurthy #include "spdk/util.h"
222796687dSParameswaran Krishnamurthy #include "spdk/nvme.h"
23*dd98a248SMehakjot Singh Sidhu #include "spdk/module/bdev/nvme.h"
242796687dSParameswaran Krishnamurthy #include "bdev_nvme.h"
252796687dSParameswaran Krishnamurthy 
262796687dSParameswaran Krishnamurthy #ifdef SPDK_CONFIG_AVAHI
272796687dSParameswaran Krishnamurthy #include <avahi-client/client.h>
282796687dSParameswaran Krishnamurthy #include <avahi-client/lookup.h>
292796687dSParameswaran Krishnamurthy #include <avahi-common/simple-watch.h>
302796687dSParameswaran Krishnamurthy #include <avahi-common/malloc.h>
312796687dSParameswaran Krishnamurthy #include <avahi-common/error.h>
322796687dSParameswaran Krishnamurthy 
332796687dSParameswaran Krishnamurthy static AvahiSimplePoll *g_avahi_simple_poll = NULL;
342796687dSParameswaran Krishnamurthy static AvahiClient *g_avahi_client = NULL;
352796687dSParameswaran Krishnamurthy 
362796687dSParameswaran Krishnamurthy struct mdns_discovery_entry_ctx {
372796687dSParameswaran Krishnamurthy 	char                                            name[256];
382796687dSParameswaran Krishnamurthy 	struct spdk_nvme_transport_id                   trid;
392796687dSParameswaran Krishnamurthy 	struct spdk_nvme_ctrlr_opts                     drv_opts;
402796687dSParameswaran Krishnamurthy 	TAILQ_ENTRY(mdns_discovery_entry_ctx)           tailq;
412796687dSParameswaran Krishnamurthy 	struct mdns_discovery_ctx                       *ctx;
422796687dSParameswaran Krishnamurthy };
432796687dSParameswaran Krishnamurthy 
442796687dSParameswaran Krishnamurthy struct mdns_discovery_ctx {
452796687dSParameswaran Krishnamurthy 	char                                    *name;
462796687dSParameswaran Krishnamurthy 	char                                    *svcname;
472796687dSParameswaran Krishnamurthy 	char                                    *hostnqn;
482796687dSParameswaran Krishnamurthy 	AvahiServiceBrowser                     *sb;
492796687dSParameswaran Krishnamurthy 	struct spdk_poller                      *poller;
502796687dSParameswaran Krishnamurthy 	struct spdk_nvme_ctrlr_opts             drv_opts;
51*dd98a248SMehakjot Singh Sidhu 	struct spdk_bdev_nvme_ctrlr_opts        bdev_opts;
522796687dSParameswaran Krishnamurthy 	uint32_t                                seqno;
532796687dSParameswaran Krishnamurthy 	bool                                    stop;
542796687dSParameswaran Krishnamurthy 	struct spdk_thread                      *calling_thread;
552796687dSParameswaran Krishnamurthy 	TAILQ_ENTRY(mdns_discovery_ctx)         tailq;
562796687dSParameswaran Krishnamurthy 	TAILQ_HEAD(, mdns_discovery_entry_ctx)  mdns_discovery_entry_ctxs;
572796687dSParameswaran Krishnamurthy };
582796687dSParameswaran Krishnamurthy 
592796687dSParameswaran Krishnamurthy TAILQ_HEAD(mdns_discovery_ctxs, mdns_discovery_ctx);
602796687dSParameswaran Krishnamurthy static struct mdns_discovery_ctxs g_mdns_discovery_ctxs = TAILQ_HEAD_INITIALIZER(
612796687dSParameswaran Krishnamurthy 			g_mdns_discovery_ctxs);
622796687dSParameswaran Krishnamurthy 
632796687dSParameswaran Krishnamurthy static struct mdns_discovery_entry_ctx *
642796687dSParameswaran Krishnamurthy create_mdns_discovery_entry_ctx(struct mdns_discovery_ctx *ctx, struct spdk_nvme_transport_id *trid)
652796687dSParameswaran Krishnamurthy {
662796687dSParameswaran Krishnamurthy 	struct mdns_discovery_entry_ctx *new_ctx;
672796687dSParameswaran Krishnamurthy 
682796687dSParameswaran Krishnamurthy 	assert(ctx);
692796687dSParameswaran Krishnamurthy 	assert(trid);
702796687dSParameswaran Krishnamurthy 	new_ctx = calloc(1, sizeof(*new_ctx));
712796687dSParameswaran Krishnamurthy 	if (new_ctx == NULL) {
722796687dSParameswaran Krishnamurthy 		SPDK_ERRLOG("could not allocate new mdns_entry_ctx\n");
732796687dSParameswaran Krishnamurthy 		return NULL;
742796687dSParameswaran Krishnamurthy 	}
752796687dSParameswaran Krishnamurthy 
762796687dSParameswaran Krishnamurthy 	new_ctx->ctx = ctx;
772796687dSParameswaran Krishnamurthy 	memcpy(&new_ctx->trid, trid, sizeof(struct spdk_nvme_transport_id));
782796687dSParameswaran Krishnamurthy 	snprintf(new_ctx->name, sizeof(new_ctx->name), "%s%u_nvme", ctx->name, ctx->seqno);
792796687dSParameswaran Krishnamurthy 	memcpy(&new_ctx->drv_opts, &ctx->drv_opts, sizeof(ctx->drv_opts));
802796687dSParameswaran Krishnamurthy 	snprintf(new_ctx->drv_opts.hostnqn, sizeof(ctx->drv_opts.hostnqn), "%s", ctx->hostnqn);
812796687dSParameswaran Krishnamurthy 	ctx->seqno = ctx->seqno + 1;
822796687dSParameswaran Krishnamurthy 	return new_ctx;
832796687dSParameswaran Krishnamurthy }
842796687dSParameswaran Krishnamurthy 
852796687dSParameswaran Krishnamurthy static void
862796687dSParameswaran Krishnamurthy mdns_bdev_nvme_start_discovery(void *_entry_ctx)
872796687dSParameswaran Krishnamurthy {
882796687dSParameswaran Krishnamurthy 	int status;
892796687dSParameswaran Krishnamurthy 	struct mdns_discovery_entry_ctx *entry_ctx = _entry_ctx;
902796687dSParameswaran Krishnamurthy 
912796687dSParameswaran Krishnamurthy 	assert(_entry_ctx);
922796687dSParameswaran Krishnamurthy 	status = bdev_nvme_start_discovery(&entry_ctx->trid, entry_ctx->name,
932796687dSParameswaran Krishnamurthy 					   &entry_ctx->ctx->drv_opts,
942796687dSParameswaran Krishnamurthy 					   &entry_ctx->ctx->bdev_opts,
952796687dSParameswaran Krishnamurthy 					   0, true, NULL, NULL);
962796687dSParameswaran Krishnamurthy 	if (status) {
972796687dSParameswaran Krishnamurthy 		SPDK_ERRLOG("Error starting discovery for name %s addr %s port %s subnqn %s &trid %p\n",
982796687dSParameswaran Krishnamurthy 			    entry_ctx->ctx->name, entry_ctx->trid.traddr, entry_ctx->trid.trsvcid,
992796687dSParameswaran Krishnamurthy 			    entry_ctx->trid.subnqn, &entry_ctx->trid);
1002796687dSParameswaran Krishnamurthy 	}
1012796687dSParameswaran Krishnamurthy }
1022796687dSParameswaran Krishnamurthy 
1032796687dSParameswaran Krishnamurthy static void
1042796687dSParameswaran Krishnamurthy free_mdns_discovery_entry_ctx(struct mdns_discovery_ctx *ctx)
1052796687dSParameswaran Krishnamurthy {
1067ed18ac6SJim Harris 	struct mdns_discovery_entry_ctx *entry_ctx, *tmp;
1072796687dSParameswaran Krishnamurthy 
1082796687dSParameswaran Krishnamurthy 	if (!ctx) {
1092796687dSParameswaran Krishnamurthy 		return;
1102796687dSParameswaran Krishnamurthy 	}
1112796687dSParameswaran Krishnamurthy 
1127ed18ac6SJim Harris 	TAILQ_FOREACH_SAFE(entry_ctx, &ctx->mdns_discovery_entry_ctxs, tailq, tmp) {
1137ed18ac6SJim Harris 		TAILQ_REMOVE(&ctx->mdns_discovery_entry_ctxs, entry_ctx, tailq);
1142796687dSParameswaran Krishnamurthy 		free(entry_ctx);
1152796687dSParameswaran Krishnamurthy 	}
1162796687dSParameswaran Krishnamurthy }
1172796687dSParameswaran Krishnamurthy 
1182796687dSParameswaran Krishnamurthy static void
1192796687dSParameswaran Krishnamurthy free_mdns_discovery_ctx(struct mdns_discovery_ctx *ctx)
1202796687dSParameswaran Krishnamurthy {
1212796687dSParameswaran Krishnamurthy 	if (!ctx) {
1222796687dSParameswaran Krishnamurthy 		return;
1232796687dSParameswaran Krishnamurthy 	}
1242796687dSParameswaran Krishnamurthy 
1252796687dSParameswaran Krishnamurthy 	free(ctx->name);
1262796687dSParameswaran Krishnamurthy 	free(ctx->svcname);
1272796687dSParameswaran Krishnamurthy 	free(ctx->hostnqn);
1282796687dSParameswaran Krishnamurthy 	avahi_service_browser_free(ctx->sb);
1292796687dSParameswaran Krishnamurthy 	free_mdns_discovery_entry_ctx(ctx);
1302796687dSParameswaran Krishnamurthy 	free(ctx);
1312796687dSParameswaran Krishnamurthy }
1322796687dSParameswaran Krishnamurthy 
1332796687dSParameswaran Krishnamurthy /* get_key_val_avahi_resolve_txt - Search for the key string in the TXT received
1342796687dSParameswaran Krishnamurthy  *                            from Avavi daemon and return its value.
1352796687dSParameswaran Krishnamurthy  *   input
1362796687dSParameswaran Krishnamurthy  *       txt: TXT returned by Ahavi daemon will be of format
1372796687dSParameswaran Krishnamurthy  *            "NQN=nqn.1988-11.com.dell:SFSS:1:20221122170722e8" "p=tcp foo" and the
1382796687dSParameswaran Krishnamurthy  *            AvahiStringList txt is a linked list with each node holding a
1392796687dSParameswaran Krishnamurthy  *            key-value pair like key:p value:tcp
1402796687dSParameswaran Krishnamurthy  *
1412796687dSParameswaran Krishnamurthy  *       key: Key string to search in the txt list
1422796687dSParameswaran Krishnamurthy  *   output
1432796687dSParameswaran Krishnamurthy  *       Returns the value for the key or NULL if key is not present
1442796687dSParameswaran Krishnamurthy  *       Returned string needs to be freed with avahi_free()
1452796687dSParameswaran Krishnamurthy  */
1462796687dSParameswaran Krishnamurthy static char *
1472796687dSParameswaran Krishnamurthy get_key_val_avahi_resolve_txt(AvahiStringList *txt, const char *key)
1482796687dSParameswaran Krishnamurthy {
1492796687dSParameswaran Krishnamurthy 	char *k = NULL, *v = NULL;
1502796687dSParameswaran Krishnamurthy 	AvahiStringList *p = NULL;
1512796687dSParameswaran Krishnamurthy 	int r;
1522796687dSParameswaran Krishnamurthy 
1532796687dSParameswaran Krishnamurthy 	if (!txt || !key) {
1542796687dSParameswaran Krishnamurthy 		return NULL;
1552796687dSParameswaran Krishnamurthy 	}
1562796687dSParameswaran Krishnamurthy 
1572796687dSParameswaran Krishnamurthy 	p = avahi_string_list_find(txt, key);
1582796687dSParameswaran Krishnamurthy 	if (!p) {
1592796687dSParameswaran Krishnamurthy 		return NULL;
1602796687dSParameswaran Krishnamurthy 	}
1612796687dSParameswaran Krishnamurthy 
1622796687dSParameswaran Krishnamurthy 	r = avahi_string_list_get_pair(p, &k, &v, NULL);
1632796687dSParameswaran Krishnamurthy 	if (r < 0) {
1642796687dSParameswaran Krishnamurthy 		return NULL;
1652796687dSParameswaran Krishnamurthy 	}
1662796687dSParameswaran Krishnamurthy 
1672796687dSParameswaran Krishnamurthy 	avahi_free(k);
1682796687dSParameswaran Krishnamurthy 	return v;
1692796687dSParameswaran Krishnamurthy }
1702796687dSParameswaran Krishnamurthy 
1712796687dSParameswaran Krishnamurthy static int
1722796687dSParameswaran Krishnamurthy get_spdk_nvme_transport_from_proto_str(char *protocol, enum spdk_nvme_transport_type *trtype)
1732796687dSParameswaran Krishnamurthy {
1742796687dSParameswaran Krishnamurthy 	int status = -1;
1752796687dSParameswaran Krishnamurthy 
1762796687dSParameswaran Krishnamurthy 	if (!protocol || !trtype) {
1772796687dSParameswaran Krishnamurthy 		return status;
1782796687dSParameswaran Krishnamurthy 	}
1792796687dSParameswaran Krishnamurthy 
1802796687dSParameswaran Krishnamurthy 	if (strcmp("tcp", protocol) == 0) {
1812796687dSParameswaran Krishnamurthy 		*trtype = SPDK_NVME_TRANSPORT_TCP;
1822796687dSParameswaran Krishnamurthy 		return 0;
1832796687dSParameswaran Krishnamurthy 	}
1842796687dSParameswaran Krishnamurthy 
1852796687dSParameswaran Krishnamurthy 	return status;
1862796687dSParameswaran Krishnamurthy }
1872796687dSParameswaran Krishnamurthy 
1882796687dSParameswaran Krishnamurthy static enum spdk_nvmf_adrfam
1892796687dSParameswaran Krishnamurthy get_spdk_nvme_adrfam_from_avahi_addr(const AvahiAddress *address) {
1902796687dSParameswaran Krishnamurthy 
1912796687dSParameswaran Krishnamurthy 	if (!address)
1922796687dSParameswaran Krishnamurthy 	{
1932796687dSParameswaran Krishnamurthy 		/* Return ipv4 by default */
1942796687dSParameswaran Krishnamurthy 		return SPDK_NVMF_ADRFAM_IPV4;
1952796687dSParameswaran Krishnamurthy 	}
1962796687dSParameswaran Krishnamurthy 
1972796687dSParameswaran Krishnamurthy 	switch (address->proto)
1982796687dSParameswaran Krishnamurthy 	{
1992796687dSParameswaran Krishnamurthy 	case AVAHI_PROTO_INET:
2002796687dSParameswaran Krishnamurthy 		return SPDK_NVMF_ADRFAM_IPV4;
2012796687dSParameswaran Krishnamurthy 	case AVAHI_PROTO_INET6:
2022796687dSParameswaran Krishnamurthy 		return SPDK_NVMF_ADRFAM_IPV6;
2032796687dSParameswaran Krishnamurthy 	default:
2042796687dSParameswaran Krishnamurthy 		return SPDK_NVMF_ADRFAM_IPV4;
2052796687dSParameswaran Krishnamurthy 	}
2062796687dSParameswaran Krishnamurthy }
2072796687dSParameswaran Krishnamurthy 
2082796687dSParameswaran Krishnamurthy static struct mdns_discovery_ctx *
2092796687dSParameswaran Krishnamurthy get_mdns_discovery_ctx_by_svcname(const char *svcname)
2102796687dSParameswaran Krishnamurthy {
2112796687dSParameswaran Krishnamurthy 	struct mdns_discovery_ctx *ctx = NULL, *tmp_ctx = NULL;
2122796687dSParameswaran Krishnamurthy 
2132796687dSParameswaran Krishnamurthy 	if (!svcname) {
2142796687dSParameswaran Krishnamurthy 		return NULL;
2152796687dSParameswaran Krishnamurthy 	}
2162796687dSParameswaran Krishnamurthy 
2172796687dSParameswaran Krishnamurthy 	TAILQ_FOREACH_SAFE(ctx, &g_mdns_discovery_ctxs, tailq, tmp_ctx) {
2182796687dSParameswaran Krishnamurthy 		if (strcmp(ctx->svcname, svcname) == 0) {
2192796687dSParameswaran Krishnamurthy 			return ctx;
2202796687dSParameswaran Krishnamurthy 		}
2212796687dSParameswaran Krishnamurthy 	}
2222796687dSParameswaran Krishnamurthy 	return NULL;
2232796687dSParameswaran Krishnamurthy }
2242796687dSParameswaran Krishnamurthy 
2252796687dSParameswaran Krishnamurthy static void
22609eaba31SParameswaran Krishnamurthy mdns_resolve_handler(
22709eaba31SParameswaran Krishnamurthy 	AvahiServiceResolver *resolver,
22809eaba31SParameswaran Krishnamurthy 	AVAHI_GCC_UNUSED AvahiIfIndex intf,
22909eaba31SParameswaran Krishnamurthy 	AVAHI_GCC_UNUSED AvahiProtocol avahi_protocol,
23009eaba31SParameswaran Krishnamurthy 	AvahiResolverEvent resolve_event,
23109eaba31SParameswaran Krishnamurthy 	const char *svc_name,
23209eaba31SParameswaran Krishnamurthy 	const char *svc_type,
23309eaba31SParameswaran Krishnamurthy 	const char *svc_domain,
2342796687dSParameswaran Krishnamurthy 	const char *host_name,
23509eaba31SParameswaran Krishnamurthy 	const AvahiAddress *host_address,
2362796687dSParameswaran Krishnamurthy 	uint16_t port,
2372796687dSParameswaran Krishnamurthy 	AvahiStringList *txt,
23809eaba31SParameswaran Krishnamurthy 	AvahiLookupResultFlags result_flags,
23909eaba31SParameswaran Krishnamurthy 	AVAHI_GCC_UNUSED void *user_data)
2402796687dSParameswaran Krishnamurthy {
24109eaba31SParameswaran Krishnamurthy 	assert(resolver);
24209eaba31SParameswaran Krishnamurthy 	/* The handler gets called whenever a service has been resolved
24309eaba31SParameswaran Krishnamurthy 	   successfully or timed out */
24409eaba31SParameswaran Krishnamurthy 	switch (resolve_event) {
2452796687dSParameswaran Krishnamurthy 	case AVAHI_RESOLVER_FOUND: {
24609eaba31SParameswaran Krishnamurthy 		char ipaddr[SPDK_NVMF_TRADDR_MAX_LEN + 1], port_str[SPDK_NVMF_TRSVCID_MAX_LEN + 1], *str;
2472796687dSParameswaran Krishnamurthy 		struct spdk_nvme_transport_id *trid = NULL;
2482796687dSParameswaran Krishnamurthy 		char *subnqn = NULL, *proto = NULL;
2492796687dSParameswaran Krishnamurthy 		struct mdns_discovery_ctx *ctx = NULL;
2502796687dSParameswaran Krishnamurthy 		struct mdns_discovery_entry_ctx *entry_ctx = NULL;
2512796687dSParameswaran Krishnamurthy 		int status = -1;
2522796687dSParameswaran Krishnamurthy 
2532796687dSParameswaran Krishnamurthy 		memset(ipaddr, 0, sizeof(ipaddr));
2542796687dSParameswaran Krishnamurthy 		memset(port_str, 0, sizeof(port_str));
25509eaba31SParameswaran Krishnamurthy 		SPDK_INFOLOG(bdev_nvme, "Service '%s' of type '%s' in domain '%s'\n", svc_name, svc_type,
25609eaba31SParameswaran Krishnamurthy 			     svc_domain);
25709eaba31SParameswaran Krishnamurthy 		avahi_address_snprint(ipaddr, sizeof(ipaddr), host_address);
2582796687dSParameswaran Krishnamurthy 		snprintf(port_str, sizeof(port_str), "%d", port);
25909eaba31SParameswaran Krishnamurthy 		str = avahi_string_list_to_string(txt);
2602796687dSParameswaran Krishnamurthy 		SPDK_INFOLOG(bdev_nvme,
2612796687dSParameswaran Krishnamurthy 			     "\t%s:%u (%s)\n"
2622796687dSParameswaran Krishnamurthy 			     "\tTXT=%s\n"
2632796687dSParameswaran Krishnamurthy 			     "\tcookie is %u\n"
2642796687dSParameswaran Krishnamurthy 			     "\tis_local: %i\n"
2652796687dSParameswaran Krishnamurthy 			     "\tour_own: %i\n"
2662796687dSParameswaran Krishnamurthy 			     "\twide_area: %i\n"
2672796687dSParameswaran Krishnamurthy 			     "\tmulticast: %i\n"
2682796687dSParameswaran Krishnamurthy 			     "\tcached: %i\n",
2692796687dSParameswaran Krishnamurthy 			     host_name, port, ipaddr,
27009eaba31SParameswaran Krishnamurthy 			     str,
2712796687dSParameswaran Krishnamurthy 			     avahi_string_list_get_service_cookie(txt),
27209eaba31SParameswaran Krishnamurthy 			     !!(result_flags & AVAHI_LOOKUP_RESULT_LOCAL),
27309eaba31SParameswaran Krishnamurthy 			     !!(result_flags & AVAHI_LOOKUP_RESULT_OUR_OWN),
27409eaba31SParameswaran Krishnamurthy 			     !!(result_flags & AVAHI_LOOKUP_RESULT_WIDE_AREA),
27509eaba31SParameswaran Krishnamurthy 			     !!(result_flags & AVAHI_LOOKUP_RESULT_MULTICAST),
27609eaba31SParameswaran Krishnamurthy 			     !!(result_flags & AVAHI_LOOKUP_RESULT_CACHED));
27709eaba31SParameswaran Krishnamurthy 		avahi_free(str);
2782796687dSParameswaran Krishnamurthy 
27909eaba31SParameswaran Krishnamurthy 		ctx = get_mdns_discovery_ctx_by_svcname(svc_type);
2802796687dSParameswaran Krishnamurthy 		if (!ctx) {
28109eaba31SParameswaran Krishnamurthy 			SPDK_ERRLOG("Unknown Service '%s'\n", svc_type);
2822796687dSParameswaran Krishnamurthy 			break;
2832796687dSParameswaran Krishnamurthy 		}
2842796687dSParameswaran Krishnamurthy 
2852796687dSParameswaran Krishnamurthy 		trid = (struct spdk_nvme_transport_id *) calloc(1, sizeof(struct spdk_nvme_transport_id));
2862796687dSParameswaran Krishnamurthy 		if (!trid) {
2872796687dSParameswaran Krishnamurthy 			SPDK_ERRLOG(" Error allocating memory for trid\n");
2882796687dSParameswaran Krishnamurthy 			break;
2892796687dSParameswaran Krishnamurthy 		}
29009eaba31SParameswaran Krishnamurthy 		trid->adrfam = get_spdk_nvme_adrfam_from_avahi_addr(host_address);
2912796687dSParameswaran Krishnamurthy 		if (trid->adrfam != SPDK_NVMF_ADRFAM_IPV4) {
2922796687dSParameswaran Krishnamurthy 			/* TODO: For now process only ipv4 addresses */
2932796687dSParameswaran Krishnamurthy 			SPDK_INFOLOG(bdev_nvme, "trid family is not IPV4 %d\n", trid->adrfam);
2942796687dSParameswaran Krishnamurthy 			free(trid);
2952796687dSParameswaran Krishnamurthy 			break;
2962796687dSParameswaran Krishnamurthy 		}
2972796687dSParameswaran Krishnamurthy 		subnqn = get_key_val_avahi_resolve_txt(txt, "NQN");
2982796687dSParameswaran Krishnamurthy 		if (!subnqn) {
2992796687dSParameswaran Krishnamurthy 			free(trid);
3002796687dSParameswaran Krishnamurthy 			SPDK_ERRLOG("subnqn received is empty for service %s\n", ctx->svcname);
3012796687dSParameswaran Krishnamurthy 			break;
3022796687dSParameswaran Krishnamurthy 		}
3032796687dSParameswaran Krishnamurthy 		proto = get_key_val_avahi_resolve_txt(txt, "p");
3042796687dSParameswaran Krishnamurthy 		if (!proto) {
3052796687dSParameswaran Krishnamurthy 			free(trid);
3062796687dSParameswaran Krishnamurthy 			avahi_free(subnqn);
3072796687dSParameswaran Krishnamurthy 			SPDK_ERRLOG("Protocol not received for service %s\n", ctx->svcname);
3082796687dSParameswaran Krishnamurthy 			break;
3092796687dSParameswaran Krishnamurthy 		}
3102796687dSParameswaran Krishnamurthy 		status = get_spdk_nvme_transport_from_proto_str(proto, &trid->trtype);
3112796687dSParameswaran Krishnamurthy 		if (status) {
3122796687dSParameswaran Krishnamurthy 			free(trid);
3132796687dSParameswaran Krishnamurthy 			avahi_free(subnqn);
3142796687dSParameswaran Krishnamurthy 			avahi_free(proto);
3152796687dSParameswaran Krishnamurthy 			SPDK_ERRLOG("Unable to derive nvme transport type  for service %s\n", ctx->svcname);
3162796687dSParameswaran Krishnamurthy 			break;
3172796687dSParameswaran Krishnamurthy 		}
3182796687dSParameswaran Krishnamurthy 		snprintf(trid->traddr, sizeof(trid->traddr), "%s", ipaddr);
3192796687dSParameswaran Krishnamurthy 		snprintf(trid->trsvcid, sizeof(trid->trsvcid), "%s", port_str);
3202796687dSParameswaran Krishnamurthy 		snprintf(trid->subnqn, sizeof(trid->subnqn), "%s", subnqn);
3212796687dSParameswaran Krishnamurthy 		TAILQ_FOREACH(entry_ctx, &ctx->mdns_discovery_entry_ctxs, tailq) {
3222796687dSParameswaran Krishnamurthy 			if (!spdk_nvme_transport_id_compare(trid, &entry_ctx->trid)) {
3232796687dSParameswaran Krishnamurthy 				SPDK_ERRLOG("mDNS discovery entry exists already. trid->traddr: %s trid->trsvcid: %s\n",
3242796687dSParameswaran Krishnamurthy 					    trid->traddr, trid->trsvcid);
3252796687dSParameswaran Krishnamurthy 				free(trid);
3262796687dSParameswaran Krishnamurthy 				avahi_free(subnqn);
3272796687dSParameswaran Krishnamurthy 				avahi_free(proto);
32809eaba31SParameswaran Krishnamurthy 				avahi_service_resolver_free(resolver);
3290bd1ca9dSJim Harris 				return;
3302796687dSParameswaran Krishnamurthy 			}
3312796687dSParameswaran Krishnamurthy 		}
3322796687dSParameswaran Krishnamurthy 		entry_ctx = create_mdns_discovery_entry_ctx(ctx, trid);
3332796687dSParameswaran Krishnamurthy 		TAILQ_INSERT_TAIL(&ctx->mdns_discovery_entry_ctxs, entry_ctx, tailq);
3342796687dSParameswaran Krishnamurthy 		spdk_thread_send_msg(ctx->calling_thread, mdns_bdev_nvme_start_discovery, entry_ctx);
3352796687dSParameswaran Krishnamurthy 		free(trid);
3362796687dSParameswaran Krishnamurthy 		avahi_free(subnqn);
3372796687dSParameswaran Krishnamurthy 		avahi_free(proto);
3382796687dSParameswaran Krishnamurthy 		break;
3392796687dSParameswaran Krishnamurthy 	}
34009eaba31SParameswaran Krishnamurthy 	case AVAHI_RESOLVER_FAILURE:
34109eaba31SParameswaran Krishnamurthy 		SPDK_ERRLOG("(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s\n",
34209eaba31SParameswaran Krishnamurthy 			    svc_name, svc_type, svc_domain,
34309eaba31SParameswaran Krishnamurthy 			    avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(resolver))));
34409eaba31SParameswaran Krishnamurthy 		break;
3452796687dSParameswaran Krishnamurthy 	default:
34609eaba31SParameswaran Krishnamurthy 		SPDK_ERRLOG("Unknown Avahi resolver event: %d", resolve_event);
3472796687dSParameswaran Krishnamurthy 	}
34809eaba31SParameswaran Krishnamurthy 	avahi_service_resolver_free(resolver);
3492796687dSParameswaran Krishnamurthy }
3502796687dSParameswaran Krishnamurthy 
3512796687dSParameswaran Krishnamurthy static void
35209eaba31SParameswaran Krishnamurthy mdns_browse_handler(
35309eaba31SParameswaran Krishnamurthy 	AvahiServiceBrowser *browser,
35409eaba31SParameswaran Krishnamurthy 	AvahiIfIndex intf,
35509eaba31SParameswaran Krishnamurthy 	AvahiProtocol avahi_protocol,
35609eaba31SParameswaran Krishnamurthy 	AvahiBrowserEvent browser_event,
35709eaba31SParameswaran Krishnamurthy 	const char *svc_name,
35809eaba31SParameswaran Krishnamurthy 	const char *svc_type,
35909eaba31SParameswaran Krishnamurthy 	const char *svc_domain,
36009eaba31SParameswaran Krishnamurthy 	AVAHI_GCC_UNUSED AvahiLookupResultFlags result_flags,
36109eaba31SParameswaran Krishnamurthy 	void *user_data)
3622796687dSParameswaran Krishnamurthy {
36309eaba31SParameswaran Krishnamurthy 	AvahiClient *client = user_data;
3642796687dSParameswaran Krishnamurthy 
36509eaba31SParameswaran Krishnamurthy 	assert(browser);
36609eaba31SParameswaran Krishnamurthy 	/* The handler gets called whenever a new service becomes available
36709eaba31SParameswaran Krishnamurthy 	   or removed from the LAN */
36809eaba31SParameswaran Krishnamurthy 	switch (browser_event) {
3692796687dSParameswaran Krishnamurthy 	case AVAHI_BROWSER_NEW:
37009eaba31SParameswaran Krishnamurthy 		SPDK_DEBUGLOG(bdev_nvme, "(Browser) NEW: service '%s' of type '%s' in domain '%s'\n", svc_name,
37109eaba31SParameswaran Krishnamurthy 			      svc_type,
37209eaba31SParameswaran Krishnamurthy 			      svc_domain);
3732796687dSParameswaran Krishnamurthy 		/* We ignore the returned resolver object. In the callback
3742796687dSParameswaran Krishnamurthy 		   function we free it. If the server is terminated before
3752796687dSParameswaran Krishnamurthy 		   the callback function is called the server will free
3762796687dSParameswaran Krishnamurthy 		   the resolver for us. */
37709eaba31SParameswaran Krishnamurthy 		if (!(avahi_service_resolver_new(client, intf, avahi_protocol, svc_name, svc_type, svc_domain,
37809eaba31SParameswaran Krishnamurthy 						 AVAHI_PROTO_UNSPEC, 0,
37909eaba31SParameswaran Krishnamurthy 						 mdns_resolve_handler, client))) {
38009eaba31SParameswaran Krishnamurthy 			SPDK_ERRLOG("Failed to resolve service '%s': %s\n", svc_name,
38109eaba31SParameswaran Krishnamurthy 				    avahi_strerror(avahi_client_errno(client)));
3822796687dSParameswaran Krishnamurthy 		}
3832796687dSParameswaran Krishnamurthy 		break;
3842796687dSParameswaran Krishnamurthy 	case AVAHI_BROWSER_REMOVE:
38509eaba31SParameswaran Krishnamurthy 		SPDK_ERRLOG("(Browser) REMOVE: service '%s' of type '%s' in domain '%s'\n", svc_name, svc_type,
38609eaba31SParameswaran Krishnamurthy 			    svc_domain);
3872796687dSParameswaran Krishnamurthy 		/* On remove, we are not doing the automatic cleanup of connections
3882796687dSParameswaran Krishnamurthy 		 * to the targets that were learnt from the CDC, for which remove event has
3892796687dSParameswaran Krishnamurthy 		 * been received. If required, user can clear the connections manually by
3902796687dSParameswaran Krishnamurthy 		 * invoking bdev_nvme_stop_discovery. We can implement the automatic cleanup
3912796687dSParameswaran Krishnamurthy 		 * later, if there is a requirement in the future.
3922796687dSParameswaran Krishnamurthy 		 */
3932796687dSParameswaran Krishnamurthy 		break;
3942796687dSParameswaran Krishnamurthy 	case AVAHI_BROWSER_ALL_FOR_NOW:
3952796687dSParameswaran Krishnamurthy 	case AVAHI_BROWSER_CACHE_EXHAUSTED:
3962796687dSParameswaran Krishnamurthy 		SPDK_INFOLOG(bdev_nvme, "(Browser) %s\n",
39709eaba31SParameswaran Krishnamurthy 			     browser_event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
3982796687dSParameswaran Krishnamurthy 		break;
39909eaba31SParameswaran Krishnamurthy 	case AVAHI_BROWSER_FAILURE:
40009eaba31SParameswaran Krishnamurthy 		SPDK_ERRLOG("(Browser) Failure: %s\n",
40109eaba31SParameswaran Krishnamurthy 			    avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(browser))));
40209eaba31SParameswaran Krishnamurthy 		return;
4032796687dSParameswaran Krishnamurthy 	default:
40409eaba31SParameswaran Krishnamurthy 		SPDK_ERRLOG("Unknown Avahi browser event: %d", browser_event);
4052796687dSParameswaran Krishnamurthy 	}
4062796687dSParameswaran Krishnamurthy }
4072796687dSParameswaran Krishnamurthy 
4082796687dSParameswaran Krishnamurthy static void
40909eaba31SParameswaran Krishnamurthy client_handler(AvahiClient *client, AvahiClientState avahi_state, AVAHI_GCC_UNUSED void *user_data)
4102796687dSParameswaran Krishnamurthy {
41109eaba31SParameswaran Krishnamurthy 	assert(client);
41209eaba31SParameswaran Krishnamurthy 	/* The handler gets called whenever the client or server state changes */
41309eaba31SParameswaran Krishnamurthy 	if (avahi_state == AVAHI_CLIENT_FAILURE) {
41409eaba31SParameswaran Krishnamurthy 		SPDK_ERRLOG("Server connection failure: %s\n", avahi_strerror(avahi_client_errno(client)));
4152796687dSParameswaran Krishnamurthy 	}
4162796687dSParameswaran Krishnamurthy }
4172796687dSParameswaran Krishnamurthy 
4182796687dSParameswaran Krishnamurthy static int
4192796687dSParameswaran Krishnamurthy bdev_nvme_avahi_iterate(void *arg)
4202796687dSParameswaran Krishnamurthy {
4212796687dSParameswaran Krishnamurthy 	struct mdns_discovery_ctx *ctx = arg;
4222796687dSParameswaran Krishnamurthy 	int rc;
4232796687dSParameswaran Krishnamurthy 
4242796687dSParameswaran Krishnamurthy 	if (ctx->stop) {
4252796687dSParameswaran Krishnamurthy 		SPDK_INFOLOG(bdev_nvme, "Stopping avahi poller for service %s\n", ctx->svcname);
4262796687dSParameswaran Krishnamurthy 		spdk_poller_unregister(&ctx->poller);
4272796687dSParameswaran Krishnamurthy 		TAILQ_REMOVE(&g_mdns_discovery_ctxs, ctx, tailq);
4282796687dSParameswaran Krishnamurthy 		free_mdns_discovery_ctx(ctx);
4292796687dSParameswaran Krishnamurthy 		return SPDK_POLLER_IDLE;
4302796687dSParameswaran Krishnamurthy 	}
4312796687dSParameswaran Krishnamurthy 
4322796687dSParameswaran Krishnamurthy 	if (g_avahi_simple_poll == NULL) {
4332796687dSParameswaran Krishnamurthy 		spdk_poller_unregister(&ctx->poller);
4342796687dSParameswaran Krishnamurthy 		return SPDK_POLLER_IDLE;
4352796687dSParameswaran Krishnamurthy 	}
4362796687dSParameswaran Krishnamurthy 
4372796687dSParameswaran Krishnamurthy 	rc = avahi_simple_poll_iterate(g_avahi_simple_poll, 0);
4382796687dSParameswaran Krishnamurthy 	if (rc && rc != -EAGAIN) {
4392796687dSParameswaran Krishnamurthy 		SPDK_ERRLOG("avahi poll returned error for service: %s/n", ctx->svcname);
4402796687dSParameswaran Krishnamurthy 		return SPDK_POLLER_IDLE;
4412796687dSParameswaran Krishnamurthy 	}
4422796687dSParameswaran Krishnamurthy 
4432796687dSParameswaran Krishnamurthy 	return SPDK_POLLER_BUSY;
4442796687dSParameswaran Krishnamurthy }
4452796687dSParameswaran Krishnamurthy 
4462796687dSParameswaran Krishnamurthy static void
4472796687dSParameswaran Krishnamurthy start_mdns_discovery_poller(void *arg)
4482796687dSParameswaran Krishnamurthy {
4492796687dSParameswaran Krishnamurthy 	struct mdns_discovery_ctx *ctx = arg;
4502796687dSParameswaran Krishnamurthy 
4512796687dSParameswaran Krishnamurthy 	assert(arg);
4522796687dSParameswaran Krishnamurthy 	TAILQ_INSERT_TAIL(&g_mdns_discovery_ctxs, ctx, tailq);
45310f90ccdSJim Harris 	ctx->poller = SPDK_POLLER_REGISTER(bdev_nvme_avahi_iterate, ctx, 100 * 1000);
4542796687dSParameswaran Krishnamurthy }
4552796687dSParameswaran Krishnamurthy 
4562796687dSParameswaran Krishnamurthy int
4572796687dSParameswaran Krishnamurthy bdev_nvme_start_mdns_discovery(const char *base_name,
4582796687dSParameswaran Krishnamurthy 			       const char *svcname,
4592796687dSParameswaran Krishnamurthy 			       struct spdk_nvme_ctrlr_opts *drv_opts,
460*dd98a248SMehakjot Singh Sidhu 			       struct spdk_bdev_nvme_ctrlr_opts *bdev_opts)
4612796687dSParameswaran Krishnamurthy {
4622796687dSParameswaran Krishnamurthy 	AvahiServiceBrowser *sb = NULL;
4632796687dSParameswaran Krishnamurthy 	int error;
4642796687dSParameswaran Krishnamurthy 	struct mdns_discovery_ctx *ctx;
4652796687dSParameswaran Krishnamurthy 
4662796687dSParameswaran Krishnamurthy 	assert(base_name);
4672796687dSParameswaran Krishnamurthy 	assert(svcname);
4682796687dSParameswaran Krishnamurthy 
4692796687dSParameswaran Krishnamurthy 	TAILQ_FOREACH(ctx, &g_mdns_discovery_ctxs, tailq) {
4702796687dSParameswaran Krishnamurthy 		if (strcmp(ctx->name, base_name) == 0) {
4712796687dSParameswaran Krishnamurthy 			SPDK_ERRLOG("mDNS discovery already running with name %s\n", base_name);
4722796687dSParameswaran Krishnamurthy 			return -EEXIST;
4732796687dSParameswaran Krishnamurthy 		}
4742796687dSParameswaran Krishnamurthy 
4752796687dSParameswaran Krishnamurthy 		if (strcmp(ctx->svcname, svcname) == 0) {
4762796687dSParameswaran Krishnamurthy 			SPDK_ERRLOG("mDNS discovery already running for service %s\n", svcname);
4772796687dSParameswaran Krishnamurthy 			return -EEXIST;
4782796687dSParameswaran Krishnamurthy 		}
4792796687dSParameswaran Krishnamurthy 	}
4802796687dSParameswaran Krishnamurthy 
4812796687dSParameswaran Krishnamurthy 	if (g_avahi_simple_poll == NULL) {
4822796687dSParameswaran Krishnamurthy 
4832796687dSParameswaran Krishnamurthy 		/* Allocate main loop object */
4842796687dSParameswaran Krishnamurthy 		if (!(g_avahi_simple_poll = avahi_simple_poll_new())) {
4852796687dSParameswaran Krishnamurthy 			SPDK_ERRLOG("Failed to create poll object for mDNS discovery for service: %s.\n", svcname);
4862796687dSParameswaran Krishnamurthy 			return -ENOMEM;
4872796687dSParameswaran Krishnamurthy 		}
4882796687dSParameswaran Krishnamurthy 	}
4892796687dSParameswaran Krishnamurthy 
4902796687dSParameswaran Krishnamurthy 	if (g_avahi_client == NULL) {
4912796687dSParameswaran Krishnamurthy 
4922796687dSParameswaran Krishnamurthy 		/* Allocate a new client */
49309eaba31SParameswaran Krishnamurthy 		g_avahi_client = avahi_client_new(avahi_simple_poll_get(g_avahi_simple_poll), 0, client_handler,
4942796687dSParameswaran Krishnamurthy 						  NULL, &error);
4952796687dSParameswaran Krishnamurthy 		/* Check whether creating the client object succeeded */
4962796687dSParameswaran Krishnamurthy 		if (!g_avahi_client) {
4972796687dSParameswaran Krishnamurthy 			SPDK_ERRLOG("Failed to create mDNS client for service:%s Error: %s\n", svcname,
4982796687dSParameswaran Krishnamurthy 				    avahi_strerror(error));
4992796687dSParameswaran Krishnamurthy 			return -ENOMEM;
5002796687dSParameswaran Krishnamurthy 		}
5012796687dSParameswaran Krishnamurthy 	}
5022796687dSParameswaran Krishnamurthy 
5032796687dSParameswaran Krishnamurthy 	/* Create the service browser */
5042796687dSParameswaran Krishnamurthy 	if (!(sb = avahi_service_browser_new(g_avahi_client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, svcname,
50509eaba31SParameswaran Krishnamurthy 					     NULL, 0, mdns_browse_handler, g_avahi_client))) {
5062796687dSParameswaran Krishnamurthy 		SPDK_ERRLOG("Failed to create service browser for service: %s Error: %s\n", svcname,
5072796687dSParameswaran Krishnamurthy 			    avahi_strerror(avahi_client_errno(g_avahi_client)));
5082796687dSParameswaran Krishnamurthy 		return -ENOMEM;
5092796687dSParameswaran Krishnamurthy 	}
5102796687dSParameswaran Krishnamurthy 
5112796687dSParameswaran Krishnamurthy 	ctx = calloc(1, sizeof(*ctx));
5122796687dSParameswaran Krishnamurthy 	if (ctx == NULL) {
5132796687dSParameswaran Krishnamurthy 		SPDK_ERRLOG("Error creating mDNS discovery ctx for service: %s\n", svcname);
5142796687dSParameswaran Krishnamurthy 		avahi_service_browser_free(sb);
5152796687dSParameswaran Krishnamurthy 		return -ENOMEM;
5162796687dSParameswaran Krishnamurthy 	}
5172796687dSParameswaran Krishnamurthy 
5182796687dSParameswaran Krishnamurthy 	ctx->svcname = strdup(svcname);
5192796687dSParameswaran Krishnamurthy 	if (ctx->svcname == NULL) {
5202796687dSParameswaran Krishnamurthy 		SPDK_ERRLOG("Error creating mDNS discovery ctx svcname for service: %s\n", svcname);
5212796687dSParameswaran Krishnamurthy 		free_mdns_discovery_ctx(ctx);
5222796687dSParameswaran Krishnamurthy 		avahi_service_browser_free(sb);
5232796687dSParameswaran Krishnamurthy 		return -ENOMEM;
5242796687dSParameswaran Krishnamurthy 	}
5252796687dSParameswaran Krishnamurthy 	ctx->name = strdup(base_name);
5262796687dSParameswaran Krishnamurthy 	if (ctx->name == NULL) {
5272796687dSParameswaran Krishnamurthy 		SPDK_ERRLOG("Error creating mDNS discovery ctx name for service: %s\n", svcname);
5282796687dSParameswaran Krishnamurthy 		free_mdns_discovery_ctx(ctx);
5292796687dSParameswaran Krishnamurthy 		avahi_service_browser_free(sb);
5302796687dSParameswaran Krishnamurthy 		return -ENOMEM;
5312796687dSParameswaran Krishnamurthy 	}
5322796687dSParameswaran Krishnamurthy 	memcpy(&ctx->drv_opts, drv_opts, sizeof(*drv_opts));
5332796687dSParameswaran Krishnamurthy 	memcpy(&ctx->bdev_opts, bdev_opts, sizeof(*bdev_opts));
5342796687dSParameswaran Krishnamurthy 	ctx->sb = sb;
5352796687dSParameswaran Krishnamurthy 	ctx->calling_thread = spdk_get_thread();
5362796687dSParameswaran Krishnamurthy 	TAILQ_INIT(&ctx->mdns_discovery_entry_ctxs);
5372796687dSParameswaran Krishnamurthy 	/* Even if user did not specify hostnqn, we can still strdup("\0"); */
5382796687dSParameswaran Krishnamurthy 	ctx->hostnqn = strdup(ctx->drv_opts.hostnqn);
5392796687dSParameswaran Krishnamurthy 	if (ctx->hostnqn == NULL) {
5402796687dSParameswaran Krishnamurthy 		SPDK_ERRLOG("Error creating mDNS discovery ctx hostnqn for service: %s\n", svcname);
5412796687dSParameswaran Krishnamurthy 		free_mdns_discovery_ctx(ctx);
5422796687dSParameswaran Krishnamurthy 		return -ENOMEM;
5432796687dSParameswaran Krishnamurthy 	}
5442796687dSParameswaran Krishnamurthy 	/* Start the poller for the Avahi client browser in g_bdev_nvme_init_thread */
5452796687dSParameswaran Krishnamurthy 	spdk_thread_send_msg(g_bdev_nvme_init_thread, start_mdns_discovery_poller, ctx);
5462796687dSParameswaran Krishnamurthy 	return 0;
5472796687dSParameswaran Krishnamurthy }
5482796687dSParameswaran Krishnamurthy 
5492796687dSParameswaran Krishnamurthy static void
5502796687dSParameswaran Krishnamurthy mdns_stop_discovery_entry(struct mdns_discovery_ctx *ctx)
5512796687dSParameswaran Krishnamurthy {
5522796687dSParameswaran Krishnamurthy 	struct mdns_discovery_entry_ctx *entry_ctx = NULL;
5532796687dSParameswaran Krishnamurthy 
5542796687dSParameswaran Krishnamurthy 	assert(ctx);
5552796687dSParameswaran Krishnamurthy 
5562796687dSParameswaran Krishnamurthy 	TAILQ_FOREACH(entry_ctx, &ctx->mdns_discovery_entry_ctxs, tailq) {
5572796687dSParameswaran Krishnamurthy 		bdev_nvme_stop_discovery(entry_ctx->name, NULL, NULL);
5582796687dSParameswaran Krishnamurthy 	}
5592796687dSParameswaran Krishnamurthy }
5602796687dSParameswaran Krishnamurthy 
5612796687dSParameswaran Krishnamurthy int
5622796687dSParameswaran Krishnamurthy bdev_nvme_stop_mdns_discovery(const char *name)
5632796687dSParameswaran Krishnamurthy {
5642796687dSParameswaran Krishnamurthy 	struct mdns_discovery_ctx *ctx;
5652796687dSParameswaran Krishnamurthy 
5662796687dSParameswaran Krishnamurthy 	assert(name);
5672796687dSParameswaran Krishnamurthy 	TAILQ_FOREACH(ctx, &g_mdns_discovery_ctxs, tailq) {
5682796687dSParameswaran Krishnamurthy 		if (strcmp(name, ctx->name) == 0) {
5692796687dSParameswaran Krishnamurthy 			if (ctx->stop) {
5702796687dSParameswaran Krishnamurthy 				return -EALREADY;
5712796687dSParameswaran Krishnamurthy 			}
5722796687dSParameswaran Krishnamurthy 			/* set stop to true to stop the mdns poller instance */
5732796687dSParameswaran Krishnamurthy 			ctx->stop = true;
5742796687dSParameswaran Krishnamurthy 			mdns_stop_discovery_entry(ctx);
5752796687dSParameswaran Krishnamurthy 			return 0;
5762796687dSParameswaran Krishnamurthy 		}
5772796687dSParameswaran Krishnamurthy 	}
5782796687dSParameswaran Krishnamurthy 
5792796687dSParameswaran Krishnamurthy 	return -ENOENT;
5802796687dSParameswaran Krishnamurthy }
5812796687dSParameswaran Krishnamurthy 
5822796687dSParameswaran Krishnamurthy void
5832796687dSParameswaran Krishnamurthy bdev_nvme_get_mdns_discovery_info(struct spdk_jsonrpc_request *request)
5842796687dSParameswaran Krishnamurthy {
5852796687dSParameswaran Krishnamurthy 	struct mdns_discovery_ctx *ctx;
5862796687dSParameswaran Krishnamurthy 	struct mdns_discovery_entry_ctx *entry_ctx;
5872796687dSParameswaran Krishnamurthy 	struct spdk_json_write_ctx *w;
5882796687dSParameswaran Krishnamurthy 
5892796687dSParameswaran Krishnamurthy 	w = spdk_jsonrpc_begin_result(request);
5902796687dSParameswaran Krishnamurthy 	spdk_json_write_array_begin(w);
5912796687dSParameswaran Krishnamurthy 	TAILQ_FOREACH(ctx, &g_mdns_discovery_ctxs, tailq) {
5922796687dSParameswaran Krishnamurthy 		spdk_json_write_object_begin(w);
5932796687dSParameswaran Krishnamurthy 		spdk_json_write_named_string(w, "name", ctx->name);
5942796687dSParameswaran Krishnamurthy 		spdk_json_write_named_string(w, "svcname", ctx->svcname);
5952796687dSParameswaran Krishnamurthy 
5962796687dSParameswaran Krishnamurthy 		spdk_json_write_named_array_begin(w, "referrals");
5972796687dSParameswaran Krishnamurthy 		TAILQ_FOREACH(entry_ctx, &ctx->mdns_discovery_entry_ctxs, tailq) {
5982796687dSParameswaran Krishnamurthy 			spdk_json_write_object_begin(w);
5992796687dSParameswaran Krishnamurthy 			spdk_json_write_named_string(w, "name", entry_ctx->name);
6002796687dSParameswaran Krishnamurthy 			spdk_json_write_named_object_begin(w, "trid");
6012796687dSParameswaran Krishnamurthy 			nvme_bdev_dump_trid_json(&entry_ctx->trid, w);
6022796687dSParameswaran Krishnamurthy 			spdk_json_write_object_end(w);
6032796687dSParameswaran Krishnamurthy 			spdk_json_write_object_end(w);
6042796687dSParameswaran Krishnamurthy 		}
6052796687dSParameswaran Krishnamurthy 		spdk_json_write_array_end(w);
6062796687dSParameswaran Krishnamurthy 
6072796687dSParameswaran Krishnamurthy 		spdk_json_write_object_end(w);
6082796687dSParameswaran Krishnamurthy 	}
6092796687dSParameswaran Krishnamurthy 	spdk_json_write_array_end(w);
6102796687dSParameswaran Krishnamurthy 	spdk_jsonrpc_end_result(request, w);
6112796687dSParameswaran Krishnamurthy }
6122796687dSParameswaran Krishnamurthy 
6132796687dSParameswaran Krishnamurthy void
6142796687dSParameswaran Krishnamurthy bdev_nvme_mdns_discovery_config_json(struct spdk_json_write_ctx *w)
6152796687dSParameswaran Krishnamurthy {
6162796687dSParameswaran Krishnamurthy 	struct mdns_discovery_ctx *ctx;
6172796687dSParameswaran Krishnamurthy 
6182796687dSParameswaran Krishnamurthy 	TAILQ_FOREACH(ctx, &g_mdns_discovery_ctxs, tailq) {
6192796687dSParameswaran Krishnamurthy 		spdk_json_write_object_begin(w);
6202796687dSParameswaran Krishnamurthy 
6212796687dSParameswaran Krishnamurthy 		spdk_json_write_named_string(w, "method", "bdev_nvme_start_mdns_discovery");
6222796687dSParameswaran Krishnamurthy 
6232796687dSParameswaran Krishnamurthy 		spdk_json_write_named_object_begin(w, "params");
6242796687dSParameswaran Krishnamurthy 		spdk_json_write_named_string(w, "name", ctx->name);
6252796687dSParameswaran Krishnamurthy 		spdk_json_write_named_string(w, "svcname", ctx->svcname);
6262796687dSParameswaran Krishnamurthy 		spdk_json_write_named_string(w, "hostnqn", ctx->hostnqn);
6272796687dSParameswaran Krishnamurthy 		spdk_json_write_object_end(w);
6282796687dSParameswaran Krishnamurthy 
6292796687dSParameswaran Krishnamurthy 		spdk_json_write_object_end(w);
6302796687dSParameswaran Krishnamurthy 	}
6312796687dSParameswaran Krishnamurthy }
6322796687dSParameswaran Krishnamurthy 
6332796687dSParameswaran Krishnamurthy #else /* SPDK_CONFIG_AVAHI */
6342796687dSParameswaran Krishnamurthy 
6352796687dSParameswaran Krishnamurthy int
6362796687dSParameswaran Krishnamurthy bdev_nvme_start_mdns_discovery(const char *base_name,
6372796687dSParameswaran Krishnamurthy 			       const char *svcname,
6382796687dSParameswaran Krishnamurthy 			       struct spdk_nvme_ctrlr_opts *drv_opts,
639*dd98a248SMehakjot Singh Sidhu 			       struct spdk_bdev_nvme_ctrlr_opts *bdev_opts)
6402796687dSParameswaran Krishnamurthy {
6412796687dSParameswaran Krishnamurthy 	SPDK_ERRLOG("spdk not built with --with-avahi option\n");
6422796687dSParameswaran Krishnamurthy 	return -ENOTSUP;
6432796687dSParameswaran Krishnamurthy }
6442796687dSParameswaran Krishnamurthy 
6452796687dSParameswaran Krishnamurthy int
6462796687dSParameswaran Krishnamurthy bdev_nvme_stop_mdns_discovery(const char *name)
6472796687dSParameswaran Krishnamurthy {
6482796687dSParameswaran Krishnamurthy 	SPDK_ERRLOG("spdk not built with --with-avahi option\n");
6492796687dSParameswaran Krishnamurthy 	return -ENOTSUP;
6502796687dSParameswaran Krishnamurthy }
6512796687dSParameswaran Krishnamurthy 
6522796687dSParameswaran Krishnamurthy void
6532796687dSParameswaran Krishnamurthy bdev_nvme_get_mdns_discovery_info(struct spdk_jsonrpc_request *request)
6542796687dSParameswaran Krishnamurthy {
6552796687dSParameswaran Krishnamurthy 	SPDK_ERRLOG("spdk not built with --with-avahi option\n");
6562796687dSParameswaran Krishnamurthy 	spdk_jsonrpc_send_error_response(request, -ENOTSUP, spdk_strerror(ENOTSUP));
6572796687dSParameswaran Krishnamurthy }
6582796687dSParameswaran Krishnamurthy 
6592796687dSParameswaran Krishnamurthy void
6602796687dSParameswaran Krishnamurthy bdev_nvme_mdns_discovery_config_json(struct spdk_json_write_ctx *w)
6612796687dSParameswaran Krishnamurthy {
6622796687dSParameswaran Krishnamurthy 	/* Empty function to be invoked, when SPDK is built without --with-avahi */
6632796687dSParameswaran Krishnamurthy }
6642796687dSParameswaran Krishnamurthy 
6652796687dSParameswaran Krishnamurthy #endif
666