summaryrefslogtreecommitdiffstats
path: root/include/VBox/vmm/pdmnetifs.h
blob: 49e93cb52660bb7c90c4ed6830ca5573f1c78be5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
/** @file
 * PDM - Pluggable Device Manager, Network Interfaces.
 */

/*
 * Copyright (C) 2006-2022 Oracle and/or its affiliates.
 *
 * This file is part of VirtualBox base platform packages, as
 * available from https://www.virtualbox.org.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation, in version 3 of the
 * License.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <https://www.gnu.org/licenses>.
 *
 * The contents of this file may alternatively be used under the terms
 * of the Common Development and Distribution License Version 1.0
 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
 * in the VirtualBox distribution, in which case the provisions of the
 * CDDL are applicable instead of those of the GPL.
 *
 * You may elect to license modified versions of this file under the
 * terms and conditions of either the GPL or the CDDL or both.
 *
 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
 */

#ifndef VBOX_INCLUDED_vmm_pdmnetifs_h
#define VBOX_INCLUDED_vmm_pdmnetifs_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif

#include <VBox/types.h>


RT_C_DECLS_BEGIN

/** @defgroup grp_pdm_ifs_net       PDM Network Interfaces
 * @ingroup grp_pdm_interfaces
 * @{
 */


/**
 * PDM scatter/gather buffer.
 *
 * @todo Promote this to VBox/types.h, VBox/vmm/pdmcommon.h or some such place.
 */
typedef struct PDMSCATTERGATHER
{
    /** Flags. */
    size_t          fFlags;
    /** The number of bytes used.
     * This is cleared on alloc and set by the user. */
    size_t          cbUsed;
    /** The number of bytes available.
     * This is set on alloc and not changed by the user. */
    size_t          cbAvailable;
    /** Private data member for the allocator side. */
    void           *pvAllocator;
    /** Private data member for the user side. */
    void           *pvUser;
    /** The number of segments
     * This is set on alloc and not changed by the user. */
    size_t          cSegs;
    /** Variable sized array of segments. */
    PDMDATASEG      aSegs[1];
} PDMSCATTERGATHER;
/** Pointer to a PDM scatter/gather buffer. */
typedef PDMSCATTERGATHER *PPDMSCATTERGATHER;
/** Pointer to a PDM scatter/gather buffer pointer. */
typedef PPDMSCATTERGATHER *PPPDMSCATTERGATHER;


/** @name PDMSCATTERGATHER::fFlags
 * @{  */
/** Magic value. */
#define PDMSCATTERGATHER_FLAGS_MAGIC        UINT32_C(0xb1b10000)
/** Magic mask. */
#define PDMSCATTERGATHER_FLAGS_MAGIC_MASK   UINT32_C(0xffff0000)
/** Owned by owner number 1. */
#define PDMSCATTERGATHER_FLAGS_OWNER_1      UINT32_C(0x00000001)
/** Owned by owner number 2. */
#define PDMSCATTERGATHER_FLAGS_OWNER_2      UINT32_C(0x00000002)
/** Owned by owner number 3. */
#define PDMSCATTERGATHER_FLAGS_OWNER_3      UINT32_C(0x00000002)
/** Owner mask. */
#define PDMSCATTERGATHER_FLAGS_OWNER_MASK   UINT32_C(0x00000003)
/** Mask of flags available to general use.
 * The parties using the SG must all agree upon how to use these of course. */
#define PDMSCATTERGATHER_FLAGS_AVL_MASK     UINT32_C(0x0000f000)
/** Flags reserved for future use, MBZ. */
#define PDMSCATTERGATHER_FLAGS_RVD_MASK     UINT32_C(0x00000ff8)
/** @} */


/**
 * Sets the owner of a scatter/gather buffer.
 *
 * @param   pSgBuf              .
 * @param   uNewOwner           The new owner.
 */
DECLINLINE(void) PDMScatterGatherSetOwner(PPDMSCATTERGATHER pSgBuf, uint32_t uNewOwner)
{
    pSgBuf->fFlags = (pSgBuf->fFlags & ~PDMSCATTERGATHER_FLAGS_OWNER_MASK) | uNewOwner;
}



/** Pointer to a network port interface */
typedef struct PDMINETWORKDOWN *PPDMINETWORKDOWN;
/**
 * Network port interface (down).
 * Pair with PDMINETWORKUP.
 */
typedef struct PDMINETWORKDOWN
{
    /**
     * Wait until there is space for receiving data. We do not care how much space is available
     * because pfnReceive() will re-check and notify the guest if necessary.
     *
     * This function must be called before the pfnRecieve() method is called.
     *
     * @returns VBox status code. VINF_SUCCESS means there is at least one receive descriptor available.
     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     * @param   cMillies        Number of milliseconds to wait. 0 means return immediately.
     *
     * @thread  Non-EMT.
     */
    DECLR3CALLBACKMEMBER(int, pfnWaitReceiveAvail,(PPDMINETWORKDOWN pInterface, RTMSINTERVAL cMillies));

    /**
     * Receive data from the network.
     *
     * @returns VBox status code.
     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     * @param   pvBuf           The available data.
     * @param   cb              Number of bytes available in the buffer.
     *
     * @thread  Non-EMT.
     */
    DECLR3CALLBACKMEMBER(int, pfnReceive,(PPDMINETWORKDOWN pInterface, const void *pvBuf, size_t cb));

    /**
     * Receive data with segmentation context from the network.
     *
     * @returns VBox status code.
     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     * @param   pvBuf           The available data.
     * @param   cb              Number of bytes available in the buffer.
     * @param   pGso            Segmentation context.
     *
     * @thread  Non-EMT.
     */
    DECLR3CALLBACKMEMBER(int, pfnReceiveGso,(PPDMINETWORKDOWN pInterface, const void *pvBuf, size_t cb, PCPDMNETWORKGSO pGso));

    /**
     * Do pending transmit work on the leaf driver's XMIT thread.
     *
     * When a PDMINETWORKUP::pfnBeginTransmit or PDMINETWORKUP::pfnAllocBuf call
     * fails with VERR_TRY_AGAIN, the leaf drivers XMIT thread will offer to process
     * the upstream device/driver when the the VERR_TRY_AGAIN condition has been
     * removed.  In some cases the VERR_TRY_AGAIN condition is simply being in an
     * inconvenient context and the XMIT thread will start working ASAP.
     *
     * @param   pInterface      Pointer to this interface.
     * @thread  Non-EMT.
     */
    DECLR3CALLBACKMEMBER(void, pfnXmitPending,(PPDMINETWORKDOWN pInterface));

} PDMINETWORKDOWN;
/** PDMINETWORKDOWN interface ID. */
#define PDMINETWORKDOWN_IID                     "52b8cdbb-a087-493b-baa7-81ec3b803e06"


/**
 * Network link state.
 */
typedef enum PDMNETWORKLINKSTATE
{
    /** Invalid state. */
    PDMNETWORKLINKSTATE_INVALID = 0,
    /** The link is up. */
    PDMNETWORKLINKSTATE_UP,
    /** The link is down. */
    PDMNETWORKLINKSTATE_DOWN,
    /** The link is temporarily down while resuming. */
    PDMNETWORKLINKSTATE_DOWN_RESUME
} PDMNETWORKLINKSTATE;


/** Pointer to a network connector interface */
typedef R3PTRTYPE(struct PDMINETWORKUP *) PPDMINETWORKUPR3;
/** Pointer to a network connector interface, ring-0 context. */
typedef R0PTRTYPE(struct PDMINETWORKUPR0 *) PPDMINETWORKUPR0;
/** Pointer to a network connector interface, raw-mode context. */
typedef RCPTRTYPE(struct PDMINETWORKUPRC *) PPDMINETWORKUPRC;
/** Pointer to a current context network connector interface. */
typedef CTX_SUFF(PPDMINETWORKUP) PPDMINETWORKUP;

/**
 * Network connector interface (up).
 * Pair with PDMINETWORKDOWN.
 */
typedef struct PDMINETWORKUP
{
    /**
     * Begins a transmit session.
     *
     * The leaf driver guarantees that there are no concurrent sessions.
     *
     * @retval  VINF_SUCCESS on success.  Must always call
     *          PDMINETWORKUP::pfnEndXmit.
     * @retval  VERR_TRY_AGAIN if there is already an open transmit session or some
     *          important resource was unavailable (like buffer space).  If it's a
     *          resources issue, the driver will signal its XMIT thread and have it
     *          work the device thru the PDMINETWORKDOWN::pfnNotifyBufAvailable
     *          callback method.
     *
     * @param   pInterface      Pointer to the interface structure containing the
     *                          called function pointer.
     * @param   fOnWorkerThread Set if we're being called on a work thread.  Clear
     *                          if an EMT.
     *
     * @thread  Any, but normally EMT or the XMIT thread.
     */
    DECLR3CALLBACKMEMBER(int, pfnBeginXmit,(PPDMINETWORKUP pInterface, bool fOnWorkerThread));

    /**
     * Get a send buffer for passing to pfnSendBuf.
     *
     * @retval  VINF_SUCCESS on success.
     * @retval  VERR_TRY_AGAIN if temporarily out of buffer space.  After this
     *          happens, the driver will call PDMINETWORKDOWN::pfnNotifyBufAvailable
     *          when this is a buffer of the required size available.
     * @retval  VERR_NO_MEMORY if really out of buffer space.
     * @retval  VERR_NET_DOWN if we cannot send anything to the network at this
     *          point in time.  Drop the frame with a xmit error.  This is typically
     *          only seen when pausing the VM since the device keeps the link state,
     *          but there could of course be races.
     *
     * @param   pInterface      Pointer to the interface structure containing the
     *                          called function pointer.
     * @param   cbMin           The minimum buffer size.
     * @param   pGso            Pointer to a GSO context (only reference while in
     *                          this call).  NULL indicates no segmentation
     *                          offloading.  PDMSCATTERGATHER::pvUser is used to
     *                          indicate that a network SG uses GSO, usually by
     *                          pointing to a copy of @a pGso.
     * @param   ppSgBuf         Where to return the buffer.  The buffer will be
     *                          owned by the caller, designation owner number 1.
     *
     * @thread  Any, but normally EMT or the XMIT thread.
     */
    DECLR3CALLBACKMEMBER(int, pfnAllocBuf,(PPDMINETWORKUP pInterface, size_t cbMin, PCPDMNETWORKGSO pGso,
                                           PPPDMSCATTERGATHER ppSgBuf));

    /**
     * Frees an unused buffer.
     *
     * @retval  VINF_SUCCESS on success.
     *
     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     * @param   pSgBuf          A buffer from PDMINETWORKUP::pfnAllocBuf or
     *                          PDMINETWORKDOWN::pfnNotifyBufAvailable.  The buffer
     *                          ownership shall be 1.
     *
     * @thread  Any, but normally EMT or the XMIT thread.
     */
    DECLR3CALLBACKMEMBER(int, pfnFreeBuf,(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf));

    /**
     * Send data to the network.
     *
     * @retval  VINF_SUCCESS on success.
     * @retval  VERR_NET_DOWN if the NIC is not connected to a network.  pSgBuf will
     *          be freed.
     * @retval  VERR_NET_NO_BUFFER_SPACE if we're out of resources.  pSgBuf will be
     *          freed.
     *
     * @param   pInterface      Pointer to the interface structure containing the
     *                          called function pointer.
     * @param   pSgBuf          The buffer containing the data to send.  The buffer
     *                          ownership shall be 1.  The buffer will always be
     *                          consumed, regardless of the status code.
     *
     * @param   fOnWorkerThread Set if we're being called on a work thread.  Clear
     *                          if an EMT.
     *
     * @thread  Any, but normally EMT or the XMIT thread.
     */
    DECLR3CALLBACKMEMBER(int, pfnSendBuf,(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread));

    /**
     * Ends a transmit session.
     *
     * Pairs with successful PDMINETWORKUP::pfnBeginXmit calls.
     *
     * @param   pInterface      Pointer to the interface structure containing the
     *                          called function pointer.
     *
     * @thread  Any, but normally EMT or the XMIT thread.
     */
    DECLR3CALLBACKMEMBER(void, pfnEndXmit,(PPDMINETWORKUP pInterface));

    /**
     * Set promiscuous mode.
     *
     * This is called when the promiscuous mode is set. This means that there doesn't have
     * to be a mode change when it's called.
     *
     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     * @param   fPromiscuous    Set if the adaptor is now in promiscuous mode. Clear if it is not.
     * @thread  EMT ??
     */
    DECLR3CALLBACKMEMBER(void, pfnSetPromiscuousMode,(PPDMINETWORKUP pInterface, bool fPromiscuous));

    /**
     * Notification on link status changes.
     *
     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     * @param   enmLinkState    The new link state.
     * @thread  EMT ??
     */
    DECLR3CALLBACKMEMBER(void, pfnNotifyLinkChanged,(PPDMINETWORKUP pInterface, PDMNETWORKLINKSTATE enmLinkState));

    /** @todo Add a callback that informs the driver chain about MAC address changes if we ever implement that.  */

} PDMINETWORKUP;

/** Ring-0 edition of PDMINETWORKUP. */
typedef struct PDMINETWORKUPR0
{
    /** @copydoc PDMINETWORKUP::pfnBeginXmit */
    DECLR0CALLBACKMEMBER(int,  pfnBeginXmit,(PPDMINETWORKUPR0 pInterface, bool fOnWorkerThread));
    /** @copydoc PDMINETWORKUP::pfnAllocBuf */
    DECLR0CALLBACKMEMBER(int,  pfnAllocBuf,(PPDMINETWORKUPR0 pInterface, size_t cbMin, PCPDMNETWORKGSO pGso,
                                            PPPDMSCATTERGATHER ppSgBuf));
    /** @copydoc PDMINETWORKUP::pfnFreeBuf */
    DECLR0CALLBACKMEMBER(int,  pfnFreeBuf,(PPDMINETWORKUPR0 pInterface, PPDMSCATTERGATHER pSgBuf));
    /** @copydoc PDMINETWORKUP::pfnSendBuf */
    DECLR0CALLBACKMEMBER(int,  pfnSendBuf,(PPDMINETWORKUPR0 pInterface, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread));
    /** @copydoc PDMINETWORKUP::pfnEndXmit */
    DECLR0CALLBACKMEMBER(void, pfnEndXmit,(PPDMINETWORKUPR0 pInterface));
    /** @copydoc PDMINETWORKUP::pfnSetPromiscuousMode */
    DECLR0CALLBACKMEMBER(void, pfnSetPromiscuousMode,(PPDMINETWORKUPR0 pInterface, bool fPromiscuous));
} PDMINETWORKUPR0;

/** Raw-mode context edition of PDMINETWORKUP. */
typedef struct PDMINETWORKUPRC
{
    /** @copydoc PDMINETWORKUP::pfnBeginXmit */
    DECLRCCALLBACKMEMBER(int,  pfnBeginXmit,(PPDMINETWORKUPRC pInterface, bool fOnWorkerThread));
    /** @copydoc PDMINETWORKUP::pfnAllocBuf */
    DECLRCCALLBACKMEMBER(int,  pfnAllocBuf,(PPDMINETWORKUPRC pInterface, size_t cbMin, PCPDMNETWORKGSO pGso,
                                            PPPDMSCATTERGATHER ppSgBuf));
    /** @copydoc PDMINETWORKUP::pfnFreeBuf */
    DECLRCCALLBACKMEMBER(int,  pfnFreeBuf,(PPDMINETWORKUPRC pInterface, PPDMSCATTERGATHER pSgBuf));
    /** @copydoc PDMINETWORKUP::pfnSendBuf */
    DECLRCCALLBACKMEMBER(int,  pfnSendBuf,(PPDMINETWORKUPRC pInterface, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread));
    /** @copydoc PDMINETWORKUP::pfnEndXmit */
    DECLRCCALLBACKMEMBER(void, pfnEndXmit,(PPDMINETWORKUPRC pInterface));
    /** @copydoc PDMINETWORKUP::pfnSetPromiscuousMode */
    DECLRCCALLBACKMEMBER(void, pfnSetPromiscuousMode,(PPDMINETWORKUPRC pInterface, bool fPromiscuous));
} PDMINETWORKUPRC;

/** PDMINETWORKUP interface ID. */
#define PDMINETWORKUP_IID                       "67e7e7a8-2594-4649-a1e3-7cee680c6083"
/** PDMINETWORKUP interface method names. */
#define PDMINETWORKUP_SYM_LIST                  "BeginXmit;AllocBuf;FreeBuf;SendBuf;EndXmit;SetPromiscuousMode"


/** Pointer to a network config port interface */
typedef struct PDMINETWORKCONFIG *PPDMINETWORKCONFIG;
/**
 * Network config port interface (main).
 * No interface pair.
 */
typedef struct PDMINETWORKCONFIG
{
    /**
     * Gets the current Media Access Control (MAC) address.
     *
     * @returns VBox status code.
     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     * @param   pMac            Where to store the MAC address.
     * @thread  EMT
     */
    DECLR3CALLBACKMEMBER(int, pfnGetMac,(PPDMINETWORKCONFIG pInterface, PRTMAC pMac));

    /**
     * Gets the new link state.
     *
     * @returns The current link state.
     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     * @thread  EMT
     */
    DECLR3CALLBACKMEMBER(PDMNETWORKLINKSTATE, pfnGetLinkState,(PPDMINETWORKCONFIG pInterface));

    /**
     * Sets the new link state.
     *
     * @returns VBox status code.
     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     * @param   enmState        The new link state
     * @thread  EMT
     */
    DECLR3CALLBACKMEMBER(int, pfnSetLinkState,(PPDMINETWORKCONFIG pInterface, PDMNETWORKLINKSTATE enmState));

} PDMINETWORKCONFIG;
/** PDMINETWORKCONFIG interface ID. */
#define PDMINETWORKCONFIG_IID                   "d6d909e8-716d-415d-b109-534e4478ff4e"


/** Pointer to a NAT configuration port.   */
typedef struct PDMINETWORKNATCONFIG *PPDMINETWORKNATCONFIG;
/**
 * Network config port interface (main).
 * No interface pair.
 */
typedef struct PDMINETWORKNATCONFIG
{
    /**
     * Inform NAT about the adding/removing redirection rule
     *
     * @todo D O C U M E N T   M E !
     * @todo s/u16/u/g
     */
    DECLR3CALLBACKMEMBER(int, pfnRedirectRuleCommand ,(PPDMINETWORKNATCONFIG pInterface, bool fRemove,
                                                       bool fUdp, const char *pHostIp, uint16_t u16HostPort,
                                                       const char *pGuestIp, uint16_t u16GuestPort));
    /**
     * Inform NAT about host DNS settings change.
     *
     * IHostNameResolutionConfigurationChangeEvent.
     */
    DECLR3CALLBACKMEMBER(void, pfnNotifyDnsChanged, (PPDMINETWORKNATCONFIG pInterface));

} PDMINETWORKNATCONFIG;
/** PDMINETWORKNATCONFIG interface ID. */
#define PDMINETWORKNATCONFIG_IID                "dc961028-3523-4b52-a93b-e38168a4a9fa"
/** @} */

RT_C_DECLS_END

#endif /* !VBOX_INCLUDED_vmm_pdmnetifs_h */