xref: /freebsd/sys/net/debugnet.h (revision 4d846d26)
17790c8c1SConrad Meyer /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
37790c8c1SConrad Meyer  *
47790c8c1SConrad Meyer  * Copyright (c) 2019 Isilon Systems, LLC.
57790c8c1SConrad Meyer  * Copyright (c) 2005-2014 Sandvine Incorporated
67790c8c1SConrad Meyer  * Copyright (c) 2000 Darrell Anderson <anderson@cs.duke.edu>
77790c8c1SConrad Meyer  * All rights reserved.
87790c8c1SConrad Meyer  *
97790c8c1SConrad Meyer  * Redistribution and use in source and binary forms, with or without
107790c8c1SConrad Meyer  * modification, are permitted provided that the following conditions
117790c8c1SConrad Meyer  * are met:
127790c8c1SConrad Meyer  * 1. Redistributions of source code must retain the above copyright
137790c8c1SConrad Meyer  *    notice, this list of conditions and the following disclaimer.
147790c8c1SConrad Meyer  * 2. Redistributions in binary form must reproduce the above copyright
157790c8c1SConrad Meyer  *    notice, this list of conditions and the following disclaimer in the
167790c8c1SConrad Meyer  *    documentation and/or other materials provided with the distribution.
177790c8c1SConrad Meyer  *
187790c8c1SConrad Meyer  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
197790c8c1SConrad Meyer  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
207790c8c1SConrad Meyer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
217790c8c1SConrad Meyer  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
227790c8c1SConrad Meyer  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
237790c8c1SConrad Meyer  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
247790c8c1SConrad Meyer  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
257790c8c1SConrad Meyer  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
267790c8c1SConrad Meyer  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
277790c8c1SConrad Meyer  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
287790c8c1SConrad Meyer  * SUCH DAMAGE.
297790c8c1SConrad Meyer  *
307790c8c1SConrad Meyer  * $FreeBSD$
317790c8c1SConrad Meyer  */
327790c8c1SConrad Meyer 
337790c8c1SConrad Meyer /*
347790c8c1SConrad Meyer  * Debugnet provides a reliable, bidirectional, UDP-encapsulated datagram
357790c8c1SConrad Meyer  * transport while a machine is in a debug state.  (N-1 CPUs stopped,
367790c8c1SConrad Meyer  * interrupts disabled, may or may not be in a panic(9) state.)  Only one
377790c8c1SConrad Meyer  * stream may be active at a time.  A dedicated server must be running to
387790c8c1SConrad Meyer  * accept connections.
397790c8c1SConrad Meyer  */
407790c8c1SConrad Meyer 
417790c8c1SConrad Meyer #pragma once
427790c8c1SConrad Meyer 
437790c8c1SConrad Meyer #include <sys/types.h>
447790c8c1SConrad Meyer #include <netinet/in.h>
457790c8c1SConrad Meyer 
467790c8c1SConrad Meyer /*
477790c8c1SConrad Meyer  * Debugnet protocol details.
487790c8c1SConrad Meyer  */
497790c8c1SConrad Meyer #define	DEBUGNET_HERALD		1	/* Connection handshake. */
507790c8c1SConrad Meyer #define	DEBUGNET_FINISHED	2	/* Close the connection. */
517790c8c1SConrad Meyer #define	DEBUGNET_DATA		3	/* Contains data. */
527790c8c1SConrad Meyer 
537790c8c1SConrad Meyer struct debugnet_msg_hdr {
547790c8c1SConrad Meyer 	uint32_t	mh_type;	/* Debugnet message type. */
557790c8c1SConrad Meyer 	uint32_t	mh_seqno;	/* Match acks with msgs. */
567790c8c1SConrad Meyer 	uint64_t	mh_offset;	/* Offset in fragment. */
577790c8c1SConrad Meyer 	uint32_t	mh_len;		/* Attached data (bytes). */
587790c8c1SConrad Meyer 	uint32_t	mh_aux2;	/* Consumer-specific. */
597790c8c1SConrad Meyer } __packed;
607790c8c1SConrad Meyer 
617790c8c1SConrad Meyer struct debugnet_ack {
627790c8c1SConrad Meyer 	uint32_t	da_seqno;	/* Match acks with msgs. */
637790c8c1SConrad Meyer } __packed;
647790c8c1SConrad Meyer 
657790c8c1SConrad Meyer #define	DEBUGNET_MAX_IN_FLIGHT	64
667790c8c1SConrad Meyer 
677790c8c1SConrad Meyer #ifdef _KERNEL
687790c8c1SConrad Meyer /*
697790c8c1SConrad Meyer  * Hook API for network drivers.
707790c8c1SConrad Meyer  */
717790c8c1SConrad Meyer enum debugnet_ev {
727790c8c1SConrad Meyer 	DEBUGNET_START,
737790c8c1SConrad Meyer 	DEBUGNET_END,
747790c8c1SConrad Meyer };
757790c8c1SConrad Meyer 
767790c8c1SConrad Meyer struct ifnet;
777790c8c1SConrad Meyer struct mbuf;
787790c8c1SConrad Meyer typedef void debugnet_init_t(struct ifnet *, int *nrxr, int *ncl, int *clsize);
797790c8c1SConrad Meyer typedef void debugnet_event_t(struct ifnet *, enum debugnet_ev);
807790c8c1SConrad Meyer typedef int debugnet_transmit_t(struct ifnet *, struct mbuf *);
817790c8c1SConrad Meyer typedef int debugnet_poll_t(struct ifnet *, int);
827790c8c1SConrad Meyer 
837790c8c1SConrad Meyer struct debugnet_methods {
847790c8c1SConrad Meyer 	debugnet_init_t		*dn_init;
857790c8c1SConrad Meyer 	debugnet_event_t	*dn_event;
867790c8c1SConrad Meyer 	debugnet_transmit_t	*dn_transmit;
877790c8c1SConrad Meyer 	debugnet_poll_t		*dn_poll;
887790c8c1SConrad Meyer };
897790c8c1SConrad Meyer 
907790c8c1SConrad Meyer #define	DEBUGNET_SUPPORTED_NIC(ifp)				\
917790c8c1SConrad Meyer 	((ifp)->if_debugnet_methods != NULL && (ifp)->if_type == IFT_ETHER)
927790c8c1SConrad Meyer 
93e9c69625SConrad Meyer struct debugnet_pcb; /* opaque */
94e9c69625SConrad Meyer 
957790c8c1SConrad Meyer /*
967790c8c1SConrad Meyer  * Debugnet consumer API.
977790c8c1SConrad Meyer  */
987790c8c1SConrad Meyer struct debugnet_conn_params {
997790c8c1SConrad Meyer 	struct ifnet	*dc_ifp;
1007790c8c1SConrad Meyer 	in_addr_t	dc_client;
1017790c8c1SConrad Meyer 	in_addr_t	dc_server;
1027790c8c1SConrad Meyer 	in_addr_t	dc_gateway;
1037790c8c1SConrad Meyer 
1047790c8c1SConrad Meyer 	uint16_t	dc_herald_port;
105e9c69625SConrad Meyer 	uint16_t	dc_client_port;
1067790c8c1SConrad Meyer 
1077790c8c1SConrad Meyer 	const void	*dc_herald_data;
1087790c8c1SConrad Meyer 	uint32_t	dc_herald_datalen;
1097790c8c1SConrad Meyer 
110e9c69625SConrad Meyer 	/*
111b2b1bb04SGordon Bergling 	 * Consistent with debugnet_send(), aux parameters to debugnet
112dda17b36SConrad Meyer 	 * functions are provided host-endian (but converted to
113dda17b36SConrad Meyer 	 * network endian on the wire).
114dda17b36SConrad Meyer 	 */
115dda17b36SConrad Meyer 	uint32_t	dc_herald_aux2;
116dda17b36SConrad Meyer 	uint64_t	dc_herald_offset;
117dda17b36SConrad Meyer 
118dda17b36SConrad Meyer 	/*
119e9c69625SConrad Meyer 	 * If NULL, debugnet is a unidirectional channel from panic machine to
120e9c69625SConrad Meyer 	 * remote server (like netdump).
121e9c69625SConrad Meyer 	 *
122e9c69625SConrad Meyer 	 * If handler is non-NULL, packets received on the client port that are
123e9c69625SConrad Meyer 	 * not just tx acks are forwarded to the provided handler.
124e9c69625SConrad Meyer 	 *
125e9c69625SConrad Meyer 	 * The mbuf chain will have all non-debugnet framing headers removed
126e9c69625SConrad Meyer 	 * (ethernet, inet, udp).  It will start with a debugnet_msg_hdr, of
127e9c69625SConrad Meyer 	 * which the header is guaranteed to be contiguous.  If m_pullup is
128e9c69625SConrad Meyer 	 * used, the supplied in-out mbuf pointer should be updated
129e9c69625SConrad Meyer 	 * appropriately.
130e9c69625SConrad Meyer 	 *
131e9c69625SConrad Meyer 	 * If the handler frees the mbuf chain, it should set the mbuf pointer
132e9c69625SConrad Meyer 	 * to NULL.  Otherwise, the debugnet input framework will free the
133e9c69625SConrad Meyer 	 * chain.
134dda17b36SConrad Meyer 	 *
135dda17b36SConrad Meyer 	 * The handler should ACK receieved packets with debugnet_ack_output.
136e9c69625SConrad Meyer 	 */
137e9c69625SConrad Meyer 	void		(*dc_rx_handler)(struct debugnet_pcb *, struct mbuf **);
138e9c69625SConrad Meyer };
1397790c8c1SConrad Meyer 
1407790c8c1SConrad Meyer /*
141dda17b36SConrad Meyer  * Open a stream to the specified server's herald port.
1427790c8c1SConrad Meyer  *
1437790c8c1SConrad Meyer  * If all goes well, the server will send ACK from a different port to our ack
1447790c8c1SConrad Meyer  * port.  This allows servers to somewhat gracefully handle multiple debugnet
1457790c8c1SConrad Meyer  * clients.  (Clients are limited to single connections.)
1467790c8c1SConrad Meyer  *
1477790c8c1SConrad Meyer  * Returns zero on success, or errno.
1487790c8c1SConrad Meyer  */
1497790c8c1SConrad Meyer int debugnet_connect(const struct debugnet_conn_params *,
1507790c8c1SConrad Meyer     struct debugnet_pcb **pcb_out);
1517790c8c1SConrad Meyer 
1527790c8c1SConrad Meyer /*
1537790c8c1SConrad Meyer  * Free a debugnet stream that was previously successfully opened.
1547790c8c1SConrad Meyer  *
1557790c8c1SConrad Meyer  * No attempt is made to cleanly terminate communication with the remote
1567790c8c1SConrad Meyer  * server.  Consumers should first send an empty DEBUGNET_FINISHED message, or
1577790c8c1SConrad Meyer  * otherwise let the remote know they are signing off.
1587790c8c1SConrad Meyer  */
1597790c8c1SConrad Meyer void debugnet_free(struct debugnet_pcb *);
1607790c8c1SConrad Meyer 
1617790c8c1SConrad Meyer /*
1627790c8c1SConrad Meyer  * Send a message, with common debugnet_msg_hdr header, to the connected remote
1637790c8c1SConrad Meyer  * server.
1647790c8c1SConrad Meyer  *
1657790c8c1SConrad Meyer  * - mhtype translates directly to mh_type (e.g., DEBUGNET_DATA, or some other
1667790c8c1SConrad Meyer  *   protocol-specific type).
1677790c8c1SConrad Meyer  * - Data and datalen describe the attached data; datalen may be zero.
1687790c8c1SConrad Meyer  * - If auxdata is NULL, mh_offset's initial value and mh_aux2 will be zero.
1697790c8c1SConrad Meyer  *   Otherwise, mh_offset's initial value will be auxdata->dp_offset_start and
1707790c8c1SConrad Meyer  *   mh_aux2 will have the value of auxdata->dp_aux2.
1717790c8c1SConrad Meyer  *
1727790c8c1SConrad Meyer  * Returns zero on success, or an errno on failure.
1737790c8c1SConrad Meyer  */
1747790c8c1SConrad Meyer struct debugnet_proto_aux {
1757790c8c1SConrad Meyer 	uint64_t dp_offset_start;
1767790c8c1SConrad Meyer 	uint32_t dp_aux2;
1777790c8c1SConrad Meyer };
1787790c8c1SConrad Meyer int debugnet_send(struct debugnet_pcb *, uint32_t mhtype, const void *data,
1797790c8c1SConrad Meyer     uint32_t datalen, const struct debugnet_proto_aux *auxdata);
1807790c8c1SConrad Meyer 
1817790c8c1SConrad Meyer /*
1827790c8c1SConrad Meyer  * A simple wrapper around the above when no data or auxdata is needed.
1837790c8c1SConrad Meyer  */
1847790c8c1SConrad Meyer static inline int
1857790c8c1SConrad Meyer debugnet_sendempty(struct debugnet_pcb *pcb, uint32_t mhtype)
1867790c8c1SConrad Meyer {
1877790c8c1SConrad Meyer 	return (debugnet_send(pcb, mhtype, NULL, 0, NULL));
1887790c8c1SConrad Meyer }
1897790c8c1SConrad Meyer 
1907790c8c1SConrad Meyer /*
191dda17b36SConrad Meyer  * Full-duplex RX should ACK received messages.
192dda17b36SConrad Meyer  */
193dda17b36SConrad Meyer int debugnet_ack_output(struct debugnet_pcb *, uint32_t seqno /*net endian*/);
194dda17b36SConrad Meyer 
195dda17b36SConrad Meyer /*
196dda17b36SConrad Meyer  * Check and/or wait for further packets.
197dda17b36SConrad Meyer  */
198dda17b36SConrad Meyer void debugnet_network_poll(struct debugnet_pcb *);
199dda17b36SConrad Meyer 
200dda17b36SConrad Meyer /*
2017790c8c1SConrad Meyer  * PCB accessors.
2027790c8c1SConrad Meyer  */
2037790c8c1SConrad Meyer 
2047790c8c1SConrad Meyer /*
2057790c8c1SConrad Meyer  * Get the 48-bit MAC address of the discovered next hop (gateway, or
2067790c8c1SConrad Meyer  * destination server if it is on the same segment.
2077790c8c1SConrad Meyer  */
2087790c8c1SConrad Meyer const unsigned char *debugnet_get_gw_mac(const struct debugnet_pcb *);
2097790c8c1SConrad Meyer 
2107790c8c1SConrad Meyer /*
2117790c8c1SConrad Meyer  * Callbacks from core mbuf code.
2127790c8c1SConrad Meyer  */
2137790c8c1SConrad Meyer void debugnet_any_ifnet_update(struct ifnet *);
2147790c8c1SConrad Meyer 
2158270d35eSConrad Meyer /*
2168270d35eSConrad Meyer  * DDB parsing helper for common debugnet options.
2178270d35eSConrad Meyer  *
218fde2cf65SConrad Meyer  * -s <server> [-g <gateway -c <localip> -i <interface>]
2198270d35eSConrad Meyer  *
2208270d35eSConrad Meyer  * Order is not significant.  Interface is an online interface that supports
2218270d35eSConrad Meyer  * debugnet and can route to the debugnet server.  The other parameters are all
222fde2cf65SConrad Meyer  * IP addresses.  Only the server parameter is required.  The others are
223fde2cf65SConrad Meyer  * inferred automatically from the routing table, if not explicitly provided.
2248270d35eSConrad Meyer  *
2258270d35eSConrad Meyer  * Provides basic '-h' using provided 'cmd' string.
2268270d35eSConrad Meyer  *
2278270d35eSConrad Meyer  * Returns zero on success, or errno.
2288270d35eSConrad Meyer  */
2298270d35eSConrad Meyer struct debugnet_ddb_config {
2308270d35eSConrad Meyer 	struct ifnet	*dd_ifp;	/* not ref'd */
2318270d35eSConrad Meyer 	in_addr_t	dd_client;
2328270d35eSConrad Meyer 	in_addr_t	dd_server;
2338270d35eSConrad Meyer 	in_addr_t	dd_gateway;
234fde2cf65SConrad Meyer 	bool		dd_has_client : 1;
2358270d35eSConrad Meyer 	bool		dd_has_gateway : 1;
2368270d35eSConrad Meyer };
2378270d35eSConrad Meyer int debugnet_parse_ddb_cmd(const char *cmd,
2388270d35eSConrad Meyer     struct debugnet_ddb_config *result);
2398270d35eSConrad Meyer 
2407790c8c1SConrad Meyer /* Expose sysctl variables for netdump(4) to alias. */
2417790c8c1SConrad Meyer extern int debugnet_npolls;
2427790c8c1SConrad Meyer extern int debugnet_nretries;
2437790c8c1SConrad Meyer extern int debugnet_arp_nretries;
2447790c8c1SConrad Meyer 
2457790c8c1SConrad Meyer /*
2467790c8c1SConrad Meyer  * Conditionally-defined macros for device drivers so we can avoid ifdef
2477790c8c1SConrad Meyer  * wrappers in every single implementation.
2487790c8c1SConrad Meyer  */
2497790c8c1SConrad Meyer #ifdef DEBUGNET
2507790c8c1SConrad Meyer #define	DEBUGNET_DEFINE(driver)					\
2517790c8c1SConrad Meyer 	static debugnet_init_t driver##_debugnet_init;		\
2527790c8c1SConrad Meyer 	static debugnet_event_t driver##_debugnet_event;	\
2537790c8c1SConrad Meyer 	static debugnet_transmit_t driver##_debugnet_transmit;	\
2547790c8c1SConrad Meyer 	static debugnet_poll_t driver##_debugnet_poll;		\
2557790c8c1SConrad Meyer 								\
2567790c8c1SConrad Meyer 	static struct debugnet_methods driver##_debugnet_methods = { \
2577790c8c1SConrad Meyer 		.dn_init = driver##_debugnet_init,		\
2587790c8c1SConrad Meyer 		.dn_event = driver##_debugnet_event,		\
2597790c8c1SConrad Meyer 		.dn_transmit = driver##_debugnet_transmit,	\
2607790c8c1SConrad Meyer 		.dn_poll = driver##_debugnet_poll,		\
2617790c8c1SConrad Meyer 	}
2627790c8c1SConrad Meyer 
2637790c8c1SConrad Meyer #define	DEBUGNET_NOTIFY_MTU(ifp)	debugnet_any_ifnet_update(ifp)
2647790c8c1SConrad Meyer 
2657790c8c1SConrad Meyer #define	DEBUGNET_SET(ifp, driver)				\
266053a24d1SJustin Hibbits 	if_setdebugnet_methods((ifp), &driver##_debugnet_methods)
2677790c8c1SConrad Meyer 
2687790c8c1SConrad Meyer #else /* !DEBUGNET || !INET */
2697790c8c1SConrad Meyer 
2707790c8c1SConrad Meyer #define	DEBUGNET_DEFINE(driver)
2717790c8c1SConrad Meyer #define	DEBUGNET_NOTIFY_MTU(ifp)
2727790c8c1SConrad Meyer #define	DEBUGNET_SET(ifp, driver)
2737790c8c1SConrad Meyer 
2747790c8c1SConrad Meyer #endif /* DEBUGNET && INET */
2757790c8c1SConrad Meyer #endif /* _KERNEL */
276