aboutsummaryrefslogtreecommitdiff
path: root/sys/net/debugnet.h
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net/debugnet.h')
-rw-r--r--sys/net/debugnet.h286
1 files changed, 286 insertions, 0 deletions
diff --git a/sys/net/debugnet.h b/sys/net/debugnet.h
new file mode 100644
index 000000000000..eddf603e9b6b
--- /dev/null
+++ b/sys/net/debugnet.h
@@ -0,0 +1,286 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2019 Isilon Systems, LLC.
+ * Copyright (c) 2005-2014 Sandvine Incorporated
+ * Copyright (c) 2000 Darrell Anderson <anderson@cs.duke.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Debugnet provides a reliable, bidirectional, UDP-encapsulated datagram
+ * transport while a machine is in a debug state. (N-1 CPUs stopped,
+ * interrupts disabled, may or may not be in a panic(9) state.) Only one
+ * stream may be active at a time. A dedicated server must be running to
+ * accept connections.
+ */
+
+#pragma once
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+/*
+ * Debugnet protocol details.
+ */
+#define DEBUGNET_HERALD 1 /* Connection handshake. */
+#define DEBUGNET_FINISHED 2 /* Close the connection. */
+#define DEBUGNET_DATA 3 /* Contains data. */
+
+struct debugnet_msg_hdr {
+ uint32_t mh_type; /* Debugnet message type. */
+ uint32_t mh_seqno; /* Match acks with msgs. */
+ uint64_t mh_offset; /* Offset in fragment. */
+ uint32_t mh_len; /* Attached data (bytes). */
+ uint32_t mh_aux2; /* Consumer-specific. */
+} __packed;
+
+struct debugnet_ack {
+ uint32_t da_seqno; /* Match acks with msgs. */
+} __packed;
+
+#define DEBUGNET_MAX_IN_FLIGHT 64
+
+#ifdef _KERNEL
+/*
+ * Hook API for network drivers.
+ */
+enum debugnet_ev {
+ DEBUGNET_START,
+ DEBUGNET_END,
+};
+
+struct ifnet;
+struct mbuf;
+typedef void debugnet_init_t(struct ifnet *, int *nrxr, int *ncl, int *clsize);
+typedef void debugnet_event_t(struct ifnet *, enum debugnet_ev);
+typedef int debugnet_transmit_t(struct ifnet *, struct mbuf *);
+typedef int debugnet_poll_t(struct ifnet *, int);
+
+struct debugnet_methods {
+ debugnet_init_t *dn_init;
+ debugnet_event_t *dn_event;
+ debugnet_transmit_t *dn_transmit;
+ debugnet_poll_t *dn_poll;
+};
+
+#define DEBUGNET_SUPPORTED_NIC(ifp) \
+ ((ifp)->if_debugnet_methods != NULL && (ifp)->if_type == IFT_ETHER)
+
+struct debugnet_pcb; /* opaque */
+
+/*
+ * Debugnet consumer API.
+ */
+struct debugnet_conn_params {
+ struct ifnet *dc_ifp;
+ in_addr_t dc_client;
+ in_addr_t dc_server;
+ in_addr_t dc_gateway;
+
+ uint16_t dc_herald_port;
+ uint16_t dc_client_port;
+
+ const void *dc_herald_data;
+ uint32_t dc_herald_datalen;
+
+ /*
+ * Consistent with debugnet_send(), aux parameters to debugnet
+ * functions are provided host-endian (but converted to
+ * network endian on the wire).
+ */
+ uint32_t dc_herald_aux2;
+ uint64_t dc_herald_offset;
+
+ /*
+ * If NULL, debugnet is a unidirectional channel from panic machine to
+ * remote server (like netdump).
+ *
+ * If handler is non-NULL, packets received on the client port that are
+ * not just tx acks are forwarded to the provided handler.
+ *
+ * The mbuf chain will have all non-debugnet framing headers removed
+ * (ethernet, inet, udp). It will start with a debugnet_msg_hdr, of
+ * which the header is guaranteed to be contiguous. If m_pullup is
+ * used, the supplied in-out mbuf pointer should be updated
+ * appropriately.
+ *
+ * If the handler frees the mbuf chain, it should set the mbuf pointer
+ * to NULL. Otherwise, the debugnet input framework will free the
+ * chain.
+ *
+ * The handler should ACK receieved packets with debugnet_ack_output.
+ */
+ int (*dc_rx_handler)(struct mbuf *);
+
+ /* Cleanup signal for bidirectional protocols. */
+ void (*dc_finish_handler)(void);
+};
+
+/*
+ * Open a stream to the specified server's herald port.
+ *
+ * If all goes well, the server will send ACK from a different port to our ack
+ * port. This allows servers to somewhat gracefully handle multiple debugnet
+ * clients. (Clients are limited to single connections.)
+ *
+ * Returns zero on success, or errno.
+ */
+int debugnet_connect(const struct debugnet_conn_params *,
+ struct debugnet_pcb **pcb_out);
+
+/*
+ * Free a debugnet stream that was previously successfully opened.
+ *
+ * No attempt is made to cleanly terminate communication with the remote
+ * server. Consumers should first send an empty DEBUGNET_FINISHED message, or
+ * otherwise let the remote know they are signing off.
+ */
+void debugnet_free(struct debugnet_pcb *);
+
+/*
+ * Send a message, with common debugnet_msg_hdr header, to the connected remote
+ * server.
+ *
+ * - mhtype translates directly to mh_type (e.g., DEBUGNET_DATA, or some other
+ * protocol-specific type).
+ * - Data and datalen describe the attached data; datalen may be zero.
+ * - If auxdata is NULL, mh_offset's initial value and mh_aux2 will be zero.
+ * Otherwise, mh_offset's initial value will be auxdata->dp_offset_start and
+ * mh_aux2 will have the value of auxdata->dp_aux2.
+ *
+ * Returns zero on success, or an errno on failure.
+ */
+struct debugnet_proto_aux {
+ uint64_t dp_offset_start;
+ uint32_t dp_aux2;
+};
+int debugnet_send(struct debugnet_pcb *, uint32_t mhtype, const void *data,
+ uint32_t datalen, const struct debugnet_proto_aux *auxdata);
+
+/*
+ * A simple wrapper around the above when no data or auxdata is needed.
+ */
+static inline int
+debugnet_sendempty(struct debugnet_pcb *pcb, uint32_t mhtype)
+{
+ return (debugnet_send(pcb, mhtype, NULL, 0, NULL));
+}
+
+/*
+ * Full-duplex RX should ACK received messages.
+ */
+int debugnet_ack_output(struct debugnet_pcb *, uint32_t seqno /*net endian*/);
+
+/*
+ * Check and/or wait for further packets.
+ */
+void debugnet_network_poll(struct debugnet_pcb *);
+
+/*
+ * PCB accessors.
+ */
+
+/*
+ * Get the 48-bit MAC address of the discovered next hop (gateway, or
+ * destination server if it is on the same segment.
+ */
+const unsigned char *debugnet_get_gw_mac(const struct debugnet_pcb *);
+
+/*
+ * Get the connected server address.
+ */
+const in_addr_t *debugnet_get_server_addr(const struct debugnet_pcb *);
+
+/*
+ * Get the connected server port.
+ */
+const uint16_t debugnet_get_server_port(const struct debugnet_pcb *);
+
+/*
+ * Callbacks from core mbuf code.
+ */
+void debugnet_any_ifnet_update(struct ifnet *);
+
+/*
+ * DDB parsing helper for common debugnet options.
+ *
+ * -s <server> [-g <gateway -c <localip> -i <interface>]
+ *
+ * Order is not significant. Interface is an online interface that supports
+ * debugnet and can route to the debugnet server. The other parameters are all
+ * IP addresses. Only the server parameter is required. The others are
+ * inferred automatically from the routing table, if not explicitly provided.
+ *
+ * Provides basic '-h' using provided 'cmd' string.
+ *
+ * Returns zero on success, or errno.
+ */
+struct debugnet_ddb_config {
+ struct ifnet *dd_ifp; /* not ref'd */
+ in_addr_t dd_client;
+ in_addr_t dd_server;
+ in_addr_t dd_gateway;
+ bool dd_has_client : 1;
+ bool dd_has_gateway : 1;
+};
+int debugnet_parse_ddb_cmd(const char *cmd,
+ struct debugnet_ddb_config *result);
+
+/* Expose sysctl variables for netdump(4) to alias. */
+extern int debugnet_npolls;
+extern int debugnet_nretries;
+extern int debugnet_arp_nretries;
+
+/*
+ * Conditionally-defined macros for device drivers so we can avoid ifdef
+ * wrappers in every single implementation.
+ */
+#ifdef DEBUGNET
+#define DEBUGNET_DEFINE(driver) \
+ static debugnet_init_t driver##_debugnet_init; \
+ static debugnet_event_t driver##_debugnet_event; \
+ static debugnet_transmit_t driver##_debugnet_transmit; \
+ static debugnet_poll_t driver##_debugnet_poll; \
+ \
+ static struct debugnet_methods driver##_debugnet_methods = { \
+ .dn_init = driver##_debugnet_init, \
+ .dn_event = driver##_debugnet_event, \
+ .dn_transmit = driver##_debugnet_transmit, \
+ .dn_poll = driver##_debugnet_poll, \
+ }
+
+#define DEBUGNET_NOTIFY_MTU(ifp) debugnet_any_ifnet_update(ifp)
+
+#define DEBUGNET_SET(ifp, driver) \
+ if_setdebugnet_methods((ifp), &driver##_debugnet_methods)
+
+#else /* !DEBUGNET || !INET */
+
+#define DEBUGNET_DEFINE(driver)
+#define DEBUGNET_NOTIFY_MTU(ifp)
+#define DEBUGNET_SET(ifp, driver)
+
+#endif /* DEBUGNET && INET */
+#endif /* _KERNEL */