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