summaryrefslogtreecommitdiff
path: root/usr/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd')
-rw-r--r--usr/src/cmd/cmd-inet/usr.sbin/snoop/Makefile2
-rw-r--r--usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_svp.c77
-rw-r--r--usr/src/cmd/dladm/dladm.c130
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/Makefile.files1
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/genunix.c7
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/qqcache.c117
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/qqcache.h40
7 files changed, 354 insertions, 20 deletions
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/Makefile b/usr/src/cmd/cmd-inet/usr.sbin/snoop/Makefile
index 4e3dd8259a..9b11174c49 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/Makefile
+++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/Makefile
@@ -22,7 +22,7 @@
#
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
-# Copyright (c) 2018, Joyent, Inc.
+# Copyright 2018 Joyent, Inc.
#
PROG= snoop
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_svp.c b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_svp.c
index a0768c2234..3da8c57f44 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_svp.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_svp.c
@@ -322,6 +322,11 @@ do_svp_log_ack(void *data, int len)
case SVP_LOG_VL3:
rlen = sizeof (svp_log_vl3_t);
break;
+#if 0 /* XXX KEBE SAYS ROUTE */
+ case SVP_LOG_ROUTE:
+ rlen = sizeof (svp_log_route_t);
+ break;
+#endif
default:
/*
* If we don't know the type of log record we have,
@@ -362,6 +367,33 @@ do_svp_log_ack(void *data, int len)
ntohl(u.vl3->svl3_vnetid));
u.vl3++;
break;
+#if 0 /* XXX KEBE SAYS ROUTE */
+ case SVP_LOG_ROUTE:
+ show_printf("%8s Source Vnet = %u", "",
+ ntohl(u.vr->svlr_src_vnetid));
+ show_printf("%8s Source VLAN = %hu", "",
+ ntohs(u.vr->svlr_src_vlan));
+
+ prefixlen = u.vr->svlr_src_prefixlen;
+ is_host = prefixlen == 128 ? B_TRUE : B_FALSE;
+ show_printf("%8s Source %s = %s", "",
+ is_host ? "address" : "subnet",
+ svp_addr_str(u.vr->svlr_srcip, &prefixlen));
+ show_printf("%8s Destination DC id = %u", "",
+ ntohl(u.vr->svlr_dcid));
+ show_printf("%8s Destination Vnet = %u", "",
+ ntohl(u.vr->svlr_dst_vnetid));
+ show_printf("%8s Destination VLAN = %hu", "",
+ ntohs(u.vr->svlr_dst_vlan));
+
+ prefixlen = u.vr->svlr_dst_prefixlen;
+ is_host = prefixlen == 128 ? B_TRUE : B_FALSE;
+ show_printf("%8s Destination %s = %s", "",
+ is_host ? "address" : "subnet",
+ svp_addr_str(u.vr->svlr_dstip, &prefixlen));
+ u.vr++;
+ break;
+#endif
}
len -= rlen;
@@ -423,6 +455,39 @@ do_svp_shootdown(void *data, int len)
ether_ntoa((struct ether_addr *)sd->svsd_mac));
}
+#if 0 /* XXX KEBE SAYS ROUTE */
+static void
+do_svp_route_req(void *data, int len)
+{
+ svp_route_req_t *req = data;
+
+ show_printf("Vnet = %u", ntohl(req->srr_vnetid));
+ show_printf("VLAN = %hu", ntohs(req->srr_vlan));
+ show_printf("Source Address = %s", svp_addr_str(req->srr_srcip, NULL));
+ show_printf("Destination Address = %s", svp_addr_str(req->srr_dstip,
+ NULL));
+}
+
+static void
+do_svp_route_ack(void *data, int len)
+{
+ svp_route_ack_t *ack = data;
+
+ show_printf("Status = %s", svp_status_str(ntohl(ack->sra_status)));
+ show_printf("Remote DC Id = %u", ntohl(ack->sra_dcid));
+ show_printf("Remote Vnet = %u", ntohl(ack->sra_vnetid));
+ show_printf("Remote VLAN = %hu", ntohs(ack->sra_vlan));
+ show_printf("Remote UL3 Address = %s", svp_addr_str(ack->sra_ip, NULL));
+ show_printf("Remote UL3 Port = %hu", ntohs(ack->sra_port));
+ show_printf("Source MAC Address = %s",
+ ether_ntoa((struct ether_addr *)ack->sra_srcmac));
+ show_printf("Destination MAC Address = %s",
+ ether_ntoa((struct ether_addr *)ack->sra_dstmac));
+ show_printf("Source IP Prefix = %hhu", ack->sra_src_pfx);
+ show_printf("Destination IP Prefix = %hhu", ack->sra_dst_pfx);
+}
+#endif
+
static struct svp_len_tbl {
uint16_t slt_op;
size_t slt_len;
@@ -441,6 +506,10 @@ static struct svp_len_tbl {
{ SVP_R_LOG_RM, sizeof (svp_lrm_req_t) },
{ SVP_R_LOG_RM_ACK, sizeof (svp_lrm_ack_t) },
{ SVP_R_SHOOTDOWN, sizeof (svp_shootdown_t) },
+#if 0 /* XXX KEBE SAYS ROUTE */
+ { SVP_R_ROUTE_REQ, sizeof (svp_route_req_t) },
+ { SVP_R_ROUTE_ACK, sizeof (svp_route_ack_t) }
+#endif
};
static boolean_t
@@ -548,6 +617,14 @@ interpret_svp(int flags, char *data, int fraglen)
case SVP_R_SHOOTDOWN:
do_svp_shootdown(req, fraglen);
break;
+#if 0 /* XXX KEBE SAYS ROUTE */
+ case SVP_R_ROUTE_REQ:
+ do_svp_route_req(req, fraglen);
+ break;
+ case SVP_R_ROUTE_ACK:
+ do_svp_route_ack(req, fraglen);
+ break;
+#endif
}
show_space();
diff --git a/usr/src/cmd/dladm/dladm.c b/usr/src/cmd/dladm/dladm.c
index c59926be94..590f693a66 100644
--- a/usr/src/cmd/dladm/dladm.c
+++ b/usr/src/cmd/dladm/dladm.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2017 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
* Copyright 2016 Nexenta Systems, Inc.
* Copyright 2020 Peter Tribble.
*/
@@ -420,13 +420,14 @@ static cmd_t cmds[] = {
" show-bridge -t [-p] [-o <field>,...] [-s [-i <interval>]]"
" <bridge>\n" },
{ "create-overlay", do_create_overlay,
- " create-overlay [-t] -e <encap> -s <search> -v <vnetid>\n"
+ " create-overlay [-t] [-d <dcid>] -e <encap> -s <search> "
+ "-v <vnetid>\n"
"\t\t [ -p <prop>=<value>[,...]] <overlay>" },
{ "delete-overlay", do_delete_overlay,
" delete-overlay <overlay>" },
{ "modify-overlay", do_modify_overlay,
- " modify-overlay -d mac | -f | -s mac=ip:port "
- "<overlay>" },
+ " modify-overlay -d [dcid/]mac | -f | -s [dcid/]mac=ip:port "
+ " | -p prop=value[,...] <overlay>" },
{ "show-overlay", do_show_overlay,
" show-overlay [-f | -t] [[-p] -o <field>,...] "
"[<overlay>]\n" },
@@ -1464,12 +1465,14 @@ static const struct option overlay_create_lopts[] = {
{ "search", required_argument, NULL, 's' },
{ "temporary", no_argument, NULL, 't' },
{ "vnetid", required_argument, NULL, 'v' },
+ { "dcid", optional_argument, NULL, 'd' },
{ NULL, 0, NULL, 0 }
};
static const struct option overlay_modify_lopts[] = {
{ "delete-entry", required_argument, NULL, 'd' },
{ "flush-table", no_argument, NULL, 'f' },
+ { "prop", required_argument, NULL, 'p' },
{ "set-entry", required_argument, NULL, 's' },
{ NULL, 0, NULL, 0 }
};
@@ -9892,15 +9895,26 @@ do_create_overlay(int argc, char *argv[], const char *use)
char name[MAXLINKNAMELEN];
dladm_status_t status;
uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
+ uint32_t dcid = 0;
uint64_t vid;
boolean_t havevid = B_FALSE;
char propstr[DLADM_STRSIZE];
dladm_arg_list_t *proplist = NULL;
bzero(propstr, sizeof (propstr));
- while ((opt = getopt_long(argc, argv, ":te:v:p:s:",
+ while ((opt = getopt_long(argc, argv, ":td:e:v:p:s:",
overlay_create_lopts, NULL)) != -1) {
switch (opt) {
+ case 'd':
+ errno = 0;
+ dcid = strtoul(optarg, &endp, 10);
+ if (*endp != '\0' || (dcid == 0 && errno == EINVAL))
+ die("couldn't parse datacenter id: %s",
+ optarg);
+ /* XXX If we go 64-bit, add check for > UINT32_MAX. */
+ if (dcid == ULONG_MAX && errno == ERANGE)
+ die("datacenter id too large: %s", optarg);
+ break;
case 'e':
encap = optarg;
break;
@@ -9917,6 +9931,7 @@ do_create_overlay(int argc, char *argv[], const char *use)
die("property list too long '%s'", propstr);
break;
case 'v':
+ errno = 0;
vid = strtoul(optarg, &endp, 10);
if (*endp != '\0' || (vid == 0 && errno == EINVAL))
die("couldn't parse virtual networkd id: %s",
@@ -9959,7 +9974,7 @@ do_create_overlay(int argc, char *argv[], const char *use)
!= DLADM_STATUS_OK)
die("invalid overlay property");
- status = dladm_overlay_create(handle, name, encap, search, vid,
+ status = dladm_overlay_create(handle, name, encap, search, vid, dcid,
proplist, &errlist, flags);
dladm_free_props(proplist);
if (status != DLADM_STATUS_OK) {
@@ -9989,7 +10004,7 @@ do_delete_overlay(int argc, char *argv[], const char *use)
typedef struct showoverlay_state {
ofmt_handle_t sho_ofmt;
- const char *sho_linkname;
+ const char *sho_linkname;
dladm_overlay_propinfo_handle_t sho_info;
uint8_t sho_value[DLADM_OVERLAY_PROP_SIZEMAX];
uint32_t sho_size;
@@ -10080,6 +10095,12 @@ print_overlay_value(char *outbuf, uint_t bufsize, uint_t type, const void *pbuf,
case OVERLAY_PROP_T_STRING:
(void) snprintf(outbuf, bufsize, "%s", pbuf);
break;
+ case OVERLAY_PROP_T_ETHER:
+ if (ether_ntoa_r((struct ether_addr *)pbuf, outbuf) == NULL) {
+ warn("malformed overlay ethernet property\n");
+ (void) snprintf(outbuf, bufsize, "--");
+ }
+ break;
default:
abort();
}
@@ -10428,7 +10449,7 @@ do_show_overlay(int argc, char *argv[], const char *use)
int i, opt;
datalink_id_t linkid = DATALINK_ALL_LINKID;
dladm_status_t status;
- int (*funcp)(dladm_handle_t, datalink_id_t, void *);
+ int (*funcp)(dladm_handle_t, datalink_id_t, void *);
char *fields_str = NULL;
const ofmt_field_t *fieldsp;
ofmt_status_t oferr;
@@ -10498,17 +10519,54 @@ do_show_overlay(int argc, char *argv[], const char *use)
}
static void
+parse_overlay_mac(const char *s, uint32_t *dcidp, struct ether_addr *ep)
+{
+ const char *slash;
+
+ *dcidp = 0;
+
+ if ((slash = strchr(s, '/')) != NULL) {
+ ulong_t dcval = 0;
+ size_t slen = (size_t)(slash - s) + 1;
+
+ /*
+ * If present the dcid must be at least 1 digit, and <=
+ * UINT32_MAX (10 digits + 1 for NUL).
+ */
+ if (slen < 2 || slen > 11)
+ die("invalid mac specification: %s\n", s);
+
+ char dcstr[slen];
+
+ (void) strlcpy(dcstr, s, slen);
+ errno = 0;
+ if ((dcval = strtoul(dcstr, NULL, 10)) == 0 && errno != 0)
+ die("invalid data center id: %s\n", dcstr);
+ /* XXX if we become 64-bit, check for results > UINT32_MAX */
+
+ *dcidp = (uint32_t)dcval;
+ /* Move s past '/' */
+ s = slash + 1;
+ }
+
+ if (ether_aton_r(s, ep) == NULL)
+ die("invalid mac specification: %s\n", s);
+}
+
+static void
do_modify_overlay(int argc, char *argv[], const char *use)
{
int opt, ocnt = 0;
- boolean_t flush, set, delete;
+ boolean_t flush, set, delete, setprop;
+ uint32_t dcid = 0;
struct ether_addr e;
char *dest;
datalink_id_t linkid = DATALINK_ALL_LINKID;
dladm_status_t status;
+ char propstr[DLADM_STRSIZE] = { 0 };
- flush = set = delete = B_FALSE;
- while ((opt = getopt_long(argc, argv, ":fd:s:", overlay_modify_lopts,
+ flush = set = delete = setprop = B_FALSE;
+ while ((opt = getopt_long(argc, argv, ":fd:p:s:", overlay_modify_lopts,
NULL)) != -1) {
switch (opt) {
case 'd':
@@ -10516,8 +10574,7 @@ do_modify_overlay(int argc, char *argv[], const char *use)
die_optdup('d');
delete = B_TRUE;
ocnt++;
- if (ether_aton_r(optarg, &e) == NULL)
- die("invalid mac address: %s\n", optarg);
+ parse_overlay_mac(optarg, &dcid, &e);
break;
case 'f':
if (flush == B_TRUE)
@@ -10525,6 +10582,16 @@ do_modify_overlay(int argc, char *argv[], const char *use)
flush = B_TRUE;
ocnt++;
break;
+ case 'p':
+ if (setprop == B_TRUE)
+ die_optdup('p');
+ setprop = B_TRUE;
+ (void) strlcat(propstr, optarg, DLADM_STRSIZE);
+ if (strlcat(propstr, ",", DLADM_STRSIZE) >=
+ DLADM_STRSIZE)
+ die("property list too long '%s'", propstr);
+ ocnt++;
+ break;
case 's':
if (set == B_TRUE)
die_optdup('s');
@@ -10536,8 +10603,7 @@ do_modify_overlay(int argc, char *argv[], const char *use)
if (dest == NULL)
die("malformed value, expected mac=dest, "
"got: %s\n", optarg);
- if (ether_aton_r(optarg, &e) == NULL)
- die("invalid mac address: %s\n", optarg);
+ parse_overlay_mac(optarg, &dcid, &e);
break;
default:
die_opterr(optopt, opt, use);
@@ -10545,9 +10611,9 @@ do_modify_overlay(int argc, char *argv[], const char *use)
}
if (ocnt == 0)
- die("need to specify one of -d, -f, or -s");
+ die("need to specify one of -d, -f, -p, or -s");
if (ocnt > 1)
- die("only one of -d, -f, or -s may be used");
+ die("only one of -d, -f, -p, or -s may be used");
if (argv[optind] == NULL)
die("missing required overlay device\n");
@@ -10568,17 +10634,43 @@ do_modify_overlay(int argc, char *argv[], const char *use)
}
if (delete == B_TRUE) {
- status = dladm_overlay_cache_delete(handle, linkid, &e);
+ status = dladm_overlay_cache_delete(handle, linkid, dcid, &e);
if (status != DLADM_STATUS_OK)
die_dlerr(status, "failed to flush target %s from "
"overlay target cache %s", optarg, argv[optind]);
}
if (set == B_TRUE) {
- status = dladm_overlay_cache_set(handle, linkid, &e, dest);
+ status = dladm_overlay_cache_set(handle, linkid, dcid, &e,
+ dest);
if (status != DLADM_STATUS_OK)
die_dlerr(status, "failed to set target %s for overlay "
"target cache %s", optarg, argv[optind]);
}
+ if (setprop == B_TRUE) {
+ dladm_arg_list_t *proplist = NULL;
+ uint_t i;
+
+ if (dladm_parse_link_props(propstr, &proplist, B_FALSE)
+ != DLADM_STATUS_OK)
+ die("invalid overlay property");
+
+ for (i = 0; i < proplist->al_count; i++) {
+ dladm_status_t status;
+
+ status = dladm_overlay_setprop(handle, linkid,
+ proplist->al_info[i].ai_name,
+ proplist->al_info[i].ai_val,
+ proplist->al_info[i].ai_count);
+
+ if (status != DLADM_STATUS_OK) {
+ die_dlerr(status, "failed to set property %s "
+ "for overlay device %s",
+ proplist->al_info[i].ai_name, argv[optind]);
+ }
+ }
+
+ dladm_free_props(proplist);
+ }
}
diff --git a/usr/src/cmd/mdb/common/modules/genunix/Makefile.files b/usr/src/cmd/mdb/common/modules/genunix/Makefile.files
index d371cf70fe..05ab8fe59c 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/Makefile.files
+++ b/usr/src/cmd/mdb/common/modules/genunix/Makefile.files
@@ -71,6 +71,7 @@ GENUNIX_SRCS = \
nvpair.c \
pci.c \
pg.c \
+ qqcache.c \
rctl.c \
refhash.c \
refstr.c \
diff --git a/usr/src/cmd/mdb/common/modules/genunix/genunix.c b/usr/src/cmd/mdb/common/modules/genunix/genunix.c
index 32370ba7e1..e0f21979e9 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/genunix.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/genunix.c
@@ -98,6 +98,7 @@
#include "nvpair.h"
#include "pci.h"
#include "pg.h"
+#include "qqcache.h"
#include "rctl.h"
#include "refhash.h"
#include "sobj.h"
@@ -4788,6 +4789,12 @@ static const mdb_walker_t walkers[] = {
{ "pcie_bus", "walk all pcie_bus_t's", pcie_bus_walk_init,
pcie_bus_walk_step, NULL },
+ /* from qqcache.c */
+ { QQCACHE_WALK_NAME, QQCACHE_WALK_DESC,
+ qqcache_walk_init_cache, qqcache_walk_step, qqcache_walk_fini },
+ { QQCACHE_HASH_WALK_NAME, QQCACHE_HASH_WALK_DESC,
+ qqcache_walk_init_hash, qqcache_walk_step, qqcache_walk_fini },
+
/* from rctl.c */
{ "rctl_dict_list", "walk all rctl_dict_entry_t's from rctl_lists",
rctl_dict_walk_init, rctl_dict_walk_step, NULL },
diff --git a/usr/src/cmd/mdb/common/modules/genunix/qqcache.c b/usr/src/cmd/mdb/common/modules/genunix/qqcache.c
new file mode 100644
index 0000000000..a2ba1463b9
--- /dev/null
+++ b/usr/src/cmd/mdb/common/modules/genunix/qqcache.c
@@ -0,0 +1,117 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2018, Joyent, Inc.
+ */
+
+#include <mdb/mdb_modapi.h>
+#include <mdb/mdb_ctf.h>
+
+#include <sys/qqcache.h>
+#include <sys/qqcache_impl.h>
+
+#include "qqcache.h"
+
+typedef struct qqcache_walk_data {
+ size_t qwd_link_off;
+} qqcache_walk_data_t;
+
+typedef struct mdb_qqcache {
+ size_t qqc_link_off;
+ size_t qqc_nbuckets;
+} mdb_qqcache_t;
+
+static int
+qqcache_walk_init(mdb_walk_state_t *wsp, boolean_t use_hash)
+{
+ qqcache_walk_data_t *qwd;
+ uintptr_t base;
+ size_t i, n, qqc_list_sz;
+ int cache_off, bucket_off, list_off;
+ mdb_qqcache_t qc;
+
+ /* mdb_ctf_offsetof_by_name will print any errors */
+ cache_off = mdb_ctf_offsetof_by_name("qqcache_t", "qqc_lists");
+ if (cache_off == -1)
+ return (WALK_ERR);
+
+ bucket_off = mdb_ctf_offsetof_by_name("qqcache_t", "qqc_buckets");
+ if (bucket_off == -1)
+ return (WALK_ERR);
+
+ list_off = mdb_ctf_offsetof_by_name("qqcache_list_t", "qqcl_list");
+ if (list_off == -1)
+ return (WALK_ERR);
+
+ /* mdb_ctf_sizeof_by_name will print any errors */
+ qqc_list_sz = mdb_ctf_sizeof_by_name("qqcache_list_t");
+ if (qqc_list_sz == -1)
+ return (WALK_ERR);
+
+ if (mdb_ctf_vread(&qc, "qqcache_t", "mdb_qqcache_t", wsp->walk_addr,
+ 0) == -1) {
+ mdb_warn("failed to read qqcache_t at %#lx", wsp->walk_addr);
+ return (WALK_ERR);
+ }
+
+ qwd = wsp->walk_data = mdb_zalloc(sizeof (*qwd), UM_SLEEP);
+ qwd->qwd_link_off = qc.qqc_link_off;
+
+ if (use_hash) {
+ base = wsp->walk_addr + bucket_off;
+ n = qc.qqc_nbuckets;
+ } else {
+ base = wsp->walk_addr + cache_off;
+ n = QQCACHE_NUM_LISTS;
+ }
+
+ for (i = 0; i < n; i++) {
+ wsp->walk_addr = base + i * qqc_list_sz + list_off;
+
+ if (mdb_layered_walk("list", wsp) == -1) {
+ mdb_warn("can't walk qqcache_t");
+ mdb_free(qwd, sizeof (*qwd));
+ return (WALK_ERR);
+ }
+ }
+
+ return (WALK_NEXT);
+}
+
+int
+qqcache_walk_init_cache(mdb_walk_state_t *wsp)
+{
+ return (qqcache_walk_init(wsp, B_FALSE));
+}
+
+int
+qqcache_walk_init_hash(mdb_walk_state_t *wsp)
+{
+ return (qqcache_walk_init(wsp, B_TRUE));
+}
+
+int
+qqcache_walk_step(mdb_walk_state_t *wsp)
+{
+ qqcache_walk_data_t *qwd = wsp->walk_data;
+ uintptr_t addr = wsp->walk_addr - qwd->qwd_link_off;
+
+ return (wsp->walk_callback(addr, wsp->walk_layer, wsp->walk_cbdata));
+}
+
+void
+qqcache_walk_fini(mdb_walk_state_t *wsp)
+{
+ qqcache_walk_data_t *qwd = wsp->walk_data;
+
+ mdb_free(qwd, sizeof (*qwd));
+}
diff --git a/usr/src/cmd/mdb/common/modules/genunix/qqcache.h b/usr/src/cmd/mdb/common/modules/genunix/qqcache.h
new file mode 100644
index 0000000000..c0d1d14fe6
--- /dev/null
+++ b/usr/src/cmd/mdb/common/modules/genunix/qqcache.h
@@ -0,0 +1,40 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2018, Joyent Inc.
+ */
+
+#ifndef _MDB_QQCACHE_H
+#define _MDB_QQCACHE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define QQCACHE_WALK_NAME "qqcache"
+#define QQCACHE_WALK_DESC "walk a qqcache (2Q cache)"
+
+#define QQCACHE_HASH_WALK_NAME "qqhash"
+#define QQCACHE_HASH_WALK_DESC "walk a qqcache (2Q cache) via the hash buckets"
+
+struct mdb_walk_state;
+
+extern int qqcache_walk_init_cache(struct mdb_walk_state *);
+extern int qqcache_walk_init_hash(struct mdb_walk_state *);
+extern int qqcache_walk_step(struct mdb_walk_state *);
+extern void qqcache_walk_fini(struct mdb_walk_state *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MDB_QQCACHE_H */