xref: /f-stack/freebsd/net/debugnet.h (revision 22ce4aff)
1*22ce4affSfengbojiang /*-
2*22ce4affSfengbojiang  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*22ce4affSfengbojiang  *
4*22ce4affSfengbojiang  * Copyright (c) 2019 Isilon Systems, LLC.
5*22ce4affSfengbojiang  * Copyright (c) 2005-2014 Sandvine Incorporated
6*22ce4affSfengbojiang  * Copyright (c) 2000 Darrell Anderson <[email protected]>
7*22ce4affSfengbojiang  * All rights reserved.
8*22ce4affSfengbojiang  *
9*22ce4affSfengbojiang  * Redistribution and use in source and binary forms, with or without
10*22ce4affSfengbojiang  * modification, are permitted provided that the following conditions
11*22ce4affSfengbojiang  * are met:
12*22ce4affSfengbojiang  * 1. Redistributions of source code must retain the above copyright
13*22ce4affSfengbojiang  *    notice, this list of conditions and the following disclaimer.
14*22ce4affSfengbojiang  * 2. Redistributions in binary form must reproduce the above copyright
15*22ce4affSfengbojiang  *    notice, this list of conditions and the following disclaimer in the
16*22ce4affSfengbojiang  *    documentation and/or other materials provided with the distribution.
17*22ce4affSfengbojiang  *
18*22ce4affSfengbojiang  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19*22ce4affSfengbojiang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*22ce4affSfengbojiang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*22ce4affSfengbojiang  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22*22ce4affSfengbojiang  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23*22ce4affSfengbojiang  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24*22ce4affSfengbojiang  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25*22ce4affSfengbojiang  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26*22ce4affSfengbojiang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27*22ce4affSfengbojiang  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28*22ce4affSfengbojiang  * SUCH DAMAGE.
29*22ce4affSfengbojiang  *
30*22ce4affSfengbojiang  * $FreeBSD$
31*22ce4affSfengbojiang  */
32*22ce4affSfengbojiang 
33*22ce4affSfengbojiang /*
34*22ce4affSfengbojiang  * Debugnet provides a reliable, bidirectional, UDP-encapsulated datagram
35*22ce4affSfengbojiang  * transport while a machine is in a debug state.  (N-1 CPUs stopped,
36*22ce4affSfengbojiang  * interrupts disabled, may or may not be in a panic(9) state.)  Only one
37*22ce4affSfengbojiang  * stream may be active at a time.  A dedicated server must be running to
38*22ce4affSfengbojiang  * accept connections.
39*22ce4affSfengbojiang  */
40*22ce4affSfengbojiang 
41*22ce4affSfengbojiang #pragma once
42*22ce4affSfengbojiang 
43*22ce4affSfengbojiang #include <sys/types.h>
44*22ce4affSfengbojiang #include <netinet/in.h>
45*22ce4affSfengbojiang 
46*22ce4affSfengbojiang /*
47*22ce4affSfengbojiang  * Debugnet protocol details.
48*22ce4affSfengbojiang  */
49*22ce4affSfengbojiang #define	DEBUGNET_HERALD		1	/* Connection handshake. */
50*22ce4affSfengbojiang #define	DEBUGNET_FINISHED	2	/* Close the connection. */
51*22ce4affSfengbojiang #define	DEBUGNET_DATA		3	/* Contains data. */
52*22ce4affSfengbojiang 
53*22ce4affSfengbojiang struct debugnet_msg_hdr {
54*22ce4affSfengbojiang 	uint32_t	mh_type;	/* Debugnet message type. */
55*22ce4affSfengbojiang 	uint32_t	mh_seqno;	/* Match acks with msgs. */
56*22ce4affSfengbojiang 	uint64_t	mh_offset;	/* Offset in fragment. */
57*22ce4affSfengbojiang 	uint32_t	mh_len;		/* Attached data (bytes). */
58*22ce4affSfengbojiang 	uint32_t	mh_aux2;	/* Consumer-specific. */
59*22ce4affSfengbojiang } __packed;
60*22ce4affSfengbojiang 
61*22ce4affSfengbojiang struct debugnet_ack {
62*22ce4affSfengbojiang 	uint32_t	da_seqno;	/* Match acks with msgs. */
63*22ce4affSfengbojiang } __packed;
64*22ce4affSfengbojiang 
65*22ce4affSfengbojiang #define	DEBUGNET_MAX_IN_FLIGHT	64
66*22ce4affSfengbojiang 
67*22ce4affSfengbojiang #ifdef _KERNEL
68*22ce4affSfengbojiang /*
69*22ce4affSfengbojiang  * Hook API for network drivers.
70*22ce4affSfengbojiang  */
71*22ce4affSfengbojiang enum debugnet_ev {
72*22ce4affSfengbojiang 	DEBUGNET_START,
73*22ce4affSfengbojiang 	DEBUGNET_END,
74*22ce4affSfengbojiang };
75*22ce4affSfengbojiang 
76*22ce4affSfengbojiang struct ifnet;
77*22ce4affSfengbojiang struct mbuf;
78*22ce4affSfengbojiang typedef void debugnet_init_t(struct ifnet *, int *nrxr, int *ncl, int *clsize);
79*22ce4affSfengbojiang typedef void debugnet_event_t(struct ifnet *, enum debugnet_ev);
80*22ce4affSfengbojiang typedef int debugnet_transmit_t(struct ifnet *, struct mbuf *);
81*22ce4affSfengbojiang typedef int debugnet_poll_t(struct ifnet *, int);
82*22ce4affSfengbojiang 
83*22ce4affSfengbojiang struct debugnet_methods {
84*22ce4affSfengbojiang 	debugnet_init_t		*dn_init;
85*22ce4affSfengbojiang 	debugnet_event_t	*dn_event;
86*22ce4affSfengbojiang 	debugnet_transmit_t	*dn_transmit;
87*22ce4affSfengbojiang 	debugnet_poll_t		*dn_poll;
88*22ce4affSfengbojiang };
89*22ce4affSfengbojiang 
90*22ce4affSfengbojiang #define	DEBUGNET_SUPPORTED_NIC(ifp)				\
91*22ce4affSfengbojiang 	((ifp)->if_debugnet_methods != NULL && (ifp)->if_type == IFT_ETHER)
92*22ce4affSfengbojiang 
93*22ce4affSfengbojiang struct debugnet_pcb; /* opaque */
94*22ce4affSfengbojiang 
95*22ce4affSfengbojiang /*
96*22ce4affSfengbojiang  * Debugnet consumer API.
97*22ce4affSfengbojiang  */
98*22ce4affSfengbojiang struct debugnet_conn_params {
99*22ce4affSfengbojiang 	struct ifnet	*dc_ifp;
100*22ce4affSfengbojiang 	in_addr_t	dc_client;
101*22ce4affSfengbojiang 	in_addr_t	dc_server;
102*22ce4affSfengbojiang 	in_addr_t	dc_gateway;
103*22ce4affSfengbojiang 
104*22ce4affSfengbojiang 	uint16_t	dc_herald_port;
105*22ce4affSfengbojiang 	uint16_t	dc_client_port;
106*22ce4affSfengbojiang 
107*22ce4affSfengbojiang 	const void	*dc_herald_data;
108*22ce4affSfengbojiang 	uint32_t	dc_herald_datalen;
109*22ce4affSfengbojiang 
110*22ce4affSfengbojiang 	/*
111*22ce4affSfengbojiang 	 * Consistent with debugnet_send(), aux paramaters to debugnet
112*22ce4affSfengbojiang 	 * functions are provided host-endian (but converted to
113*22ce4affSfengbojiang 	 * network endian on the wire).
114*22ce4affSfengbojiang 	 */
115*22ce4affSfengbojiang 	uint32_t	dc_herald_aux2;
116*22ce4affSfengbojiang 	uint64_t	dc_herald_offset;
117*22ce4affSfengbojiang 
118*22ce4affSfengbojiang 	/*
119*22ce4affSfengbojiang 	 * If NULL, debugnet is a unidirectional channel from panic machine to
120*22ce4affSfengbojiang 	 * remote server (like netdump).
121*22ce4affSfengbojiang 	 *
122*22ce4affSfengbojiang 	 * If handler is non-NULL, packets received on the client port that are
123*22ce4affSfengbojiang 	 * not just tx acks are forwarded to the provided handler.
124*22ce4affSfengbojiang 	 *
125*22ce4affSfengbojiang 	 * The mbuf chain will have all non-debugnet framing headers removed
126*22ce4affSfengbojiang 	 * (ethernet, inet, udp).  It will start with a debugnet_msg_hdr, of
127*22ce4affSfengbojiang 	 * which the header is guaranteed to be contiguous.  If m_pullup is
128*22ce4affSfengbojiang 	 * used, the supplied in-out mbuf pointer should be updated
129*22ce4affSfengbojiang 	 * appropriately.
130*22ce4affSfengbojiang 	 *
131*22ce4affSfengbojiang 	 * If the handler frees the mbuf chain, it should set the mbuf pointer
132*22ce4affSfengbojiang 	 * to NULL.  Otherwise, the debugnet input framework will free the
133*22ce4affSfengbojiang 	 * chain.
134*22ce4affSfengbojiang 	 *
135*22ce4affSfengbojiang 	 * The handler should ACK receieved packets with debugnet_ack_output.
136*22ce4affSfengbojiang 	 */
137*22ce4affSfengbojiang 	void		(*dc_rx_handler)(struct debugnet_pcb *, struct mbuf **);
138*22ce4affSfengbojiang };
139*22ce4affSfengbojiang 
140*22ce4affSfengbojiang /*
141*22ce4affSfengbojiang  * Open a stream to the specified server's herald port.
142*22ce4affSfengbojiang  *
143*22ce4affSfengbojiang  * If all goes well, the server will send ACK from a different port to our ack
144*22ce4affSfengbojiang  * port.  This allows servers to somewhat gracefully handle multiple debugnet
145*22ce4affSfengbojiang  * clients.  (Clients are limited to single connections.)
146*22ce4affSfengbojiang  *
147*22ce4affSfengbojiang  * Returns zero on success, or errno.
148*22ce4affSfengbojiang  */
149*22ce4affSfengbojiang int debugnet_connect(const struct debugnet_conn_params *,
150*22ce4affSfengbojiang     struct debugnet_pcb **pcb_out);
151*22ce4affSfengbojiang 
152*22ce4affSfengbojiang /*
153*22ce4affSfengbojiang  * Free a debugnet stream that was previously successfully opened.
154*22ce4affSfengbojiang  *
155*22ce4affSfengbojiang  * No attempt is made to cleanly terminate communication with the remote
156*22ce4affSfengbojiang  * server.  Consumers should first send an empty DEBUGNET_FINISHED message, or
157*22ce4affSfengbojiang  * otherwise let the remote know they are signing off.
158*22ce4affSfengbojiang  */
159*22ce4affSfengbojiang void debugnet_free(struct debugnet_pcb *);
160*22ce4affSfengbojiang 
161*22ce4affSfengbojiang /*
162*22ce4affSfengbojiang  * Send a message, with common debugnet_msg_hdr header, to the connected remote
163*22ce4affSfengbojiang  * server.
164*22ce4affSfengbojiang  *
165*22ce4affSfengbojiang  * - mhtype translates directly to mh_type (e.g., DEBUGNET_DATA, or some other
166*22ce4affSfengbojiang  *   protocol-specific type).
167*22ce4affSfengbojiang  * - Data and datalen describe the attached data; datalen may be zero.
168*22ce4affSfengbojiang  * - If auxdata is NULL, mh_offset's initial value and mh_aux2 will be zero.
169*22ce4affSfengbojiang  *   Otherwise, mh_offset's initial value will be auxdata->dp_offset_start and
170*22ce4affSfengbojiang  *   mh_aux2 will have the value of auxdata->dp_aux2.
171*22ce4affSfengbojiang  *
172*22ce4affSfengbojiang  * Returns zero on success, or an errno on failure.
173*22ce4affSfengbojiang  */
174*22ce4affSfengbojiang struct debugnet_proto_aux {
175*22ce4affSfengbojiang 	uint64_t dp_offset_start;
176*22ce4affSfengbojiang 	uint32_t dp_aux2;
177*22ce4affSfengbojiang };
178*22ce4affSfengbojiang int debugnet_send(struct debugnet_pcb *, uint32_t mhtype, const void *data,
179*22ce4affSfengbojiang     uint32_t datalen, const struct debugnet_proto_aux *auxdata);
180*22ce4affSfengbojiang 
181*22ce4affSfengbojiang /*
182*22ce4affSfengbojiang  * A simple wrapper around the above when no data or auxdata is needed.
183*22ce4affSfengbojiang  */
184*22ce4affSfengbojiang static inline int
debugnet_sendempty(struct debugnet_pcb * pcb,uint32_t mhtype)185*22ce4affSfengbojiang debugnet_sendempty(struct debugnet_pcb *pcb, uint32_t mhtype)
186*22ce4affSfengbojiang {
187*22ce4affSfengbojiang 	return (debugnet_send(pcb, mhtype, NULL, 0, NULL));
188*22ce4affSfengbojiang }
189*22ce4affSfengbojiang 
190*22ce4affSfengbojiang /*
191*22ce4affSfengbojiang  * Full-duplex RX should ACK received messages.
192*22ce4affSfengbojiang  */
193*22ce4affSfengbojiang int debugnet_ack_output(struct debugnet_pcb *, uint32_t seqno /*net endian*/);
194*22ce4affSfengbojiang 
195*22ce4affSfengbojiang /*
196*22ce4affSfengbojiang  * Check and/or wait for further packets.
197*22ce4affSfengbojiang  */
198*22ce4affSfengbojiang void debugnet_network_poll(struct debugnet_pcb *);
199*22ce4affSfengbojiang 
200*22ce4affSfengbojiang /*
201*22ce4affSfengbojiang  * PCB accessors.
202*22ce4affSfengbojiang  */
203*22ce4affSfengbojiang 
204*22ce4affSfengbojiang /*
205*22ce4affSfengbojiang  * Get the 48-bit MAC address of the discovered next hop (gateway, or
206*22ce4affSfengbojiang  * destination server if it is on the same segment.
207*22ce4affSfengbojiang  */
208*22ce4affSfengbojiang const unsigned char *debugnet_get_gw_mac(const struct debugnet_pcb *);
209*22ce4affSfengbojiang 
210*22ce4affSfengbojiang /*
211*22ce4affSfengbojiang  * Callbacks from core mbuf code.
212*22ce4affSfengbojiang  */
213*22ce4affSfengbojiang void debugnet_any_ifnet_update(struct ifnet *);
214*22ce4affSfengbojiang 
215*22ce4affSfengbojiang /*
216*22ce4affSfengbojiang  * DDB parsing helper for common debugnet options.
217*22ce4affSfengbojiang  *
218*22ce4affSfengbojiang  * -s <server> [-g <gateway -c <localip> -i <interface>]
219*22ce4affSfengbojiang  *
220*22ce4affSfengbojiang  * Order is not significant.  Interface is an online interface that supports
221*22ce4affSfengbojiang  * debugnet and can route to the debugnet server.  The other parameters are all
222*22ce4affSfengbojiang  * IP addresses.  Only the server parameter is required.  The others are
223*22ce4affSfengbojiang  * inferred automatically from the routing table, if not explicitly provided.
224*22ce4affSfengbojiang  *
225*22ce4affSfengbojiang  * Provides basic '-h' using provided 'cmd' string.
226*22ce4affSfengbojiang  *
227*22ce4affSfengbojiang  * Returns zero on success, or errno.
228*22ce4affSfengbojiang  */
229*22ce4affSfengbojiang struct debugnet_ddb_config {
230*22ce4affSfengbojiang 	struct ifnet	*dd_ifp;	/* not ref'd */
231*22ce4affSfengbojiang 	in_addr_t	dd_client;
232*22ce4affSfengbojiang 	in_addr_t	dd_server;
233*22ce4affSfengbojiang 	in_addr_t	dd_gateway;
234*22ce4affSfengbojiang 	bool		dd_has_client : 1;
235*22ce4affSfengbojiang 	bool		dd_has_gateway : 1;
236*22ce4affSfengbojiang };
237*22ce4affSfengbojiang int debugnet_parse_ddb_cmd(const char *cmd,
238*22ce4affSfengbojiang     struct debugnet_ddb_config *result);
239*22ce4affSfengbojiang 
240*22ce4affSfengbojiang /* Expose sysctl variables for netdump(4) to alias. */
241*22ce4affSfengbojiang extern int debugnet_npolls;
242*22ce4affSfengbojiang extern int debugnet_nretries;
243*22ce4affSfengbojiang extern int debugnet_arp_nretries;
244*22ce4affSfengbojiang 
245*22ce4affSfengbojiang /*
246*22ce4affSfengbojiang  * Conditionally-defined macros for device drivers so we can avoid ifdef
247*22ce4affSfengbojiang  * wrappers in every single implementation.
248*22ce4affSfengbojiang  */
249*22ce4affSfengbojiang #ifdef DEBUGNET
250*22ce4affSfengbojiang #define	DEBUGNET_DEFINE(driver)					\
251*22ce4affSfengbojiang 	static debugnet_init_t driver##_debugnet_init;		\
252*22ce4affSfengbojiang 	static debugnet_event_t driver##_debugnet_event;	\
253*22ce4affSfengbojiang 	static debugnet_transmit_t driver##_debugnet_transmit;	\
254*22ce4affSfengbojiang 	static debugnet_poll_t driver##_debugnet_poll;		\
255*22ce4affSfengbojiang 								\
256*22ce4affSfengbojiang 	static struct debugnet_methods driver##_debugnet_methods = { \
257*22ce4affSfengbojiang 		.dn_init = driver##_debugnet_init,		\
258*22ce4affSfengbojiang 		.dn_event = driver##_debugnet_event,		\
259*22ce4affSfengbojiang 		.dn_transmit = driver##_debugnet_transmit,	\
260*22ce4affSfengbojiang 		.dn_poll = driver##_debugnet_poll,		\
261*22ce4affSfengbojiang 	}
262*22ce4affSfengbojiang 
263*22ce4affSfengbojiang #define	DEBUGNET_NOTIFY_MTU(ifp)	debugnet_any_ifnet_update(ifp)
264*22ce4affSfengbojiang 
265*22ce4affSfengbojiang #define	DEBUGNET_SET(ifp, driver)				\
266*22ce4affSfengbojiang 	(ifp)->if_debugnet_methods = &driver##_debugnet_methods
267*22ce4affSfengbojiang 
268*22ce4affSfengbojiang #else /* !DEBUGNET || !INET */
269*22ce4affSfengbojiang 
270*22ce4affSfengbojiang #define	DEBUGNET_DEFINE(driver)
271*22ce4affSfengbojiang #define	DEBUGNET_NOTIFY_MTU(ifp)
272*22ce4affSfengbojiang #define	DEBUGNET_SET(ifp, driver)
273*22ce4affSfengbojiang 
274*22ce4affSfengbojiang #endif /* DEBUGNET && INET */
275*22ce4affSfengbojiang #endif /* _KERNEL */
276