VirtualBox

source: vbox/trunk/include/VBox/intnet.h@ 5283

Last change on this file since 5283 was 5283, checked in by vboxsync, 17 years ago

internal networking fixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.5 KB
Line 
1/** @file
2 * INETNET - Internal Networking.
3 */
4
5/*
6 * Copyright (C) 2006-2007 innotek GmbH
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License as published by the Free Software Foundation,
12 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
13 * distribution. VirtualBox OSE is distributed in the hope that it will
14 * be useful, but WITHOUT ANY WARRANTY of any kind.
15 */
16
17#ifndef ___VBox_intnet_h
18#define ___VBox_intnet_h
19
20#include <VBox/types.h>
21#include <VBox/stam.h>
22#include <VBox/sup.h>
23#include <iprt/assert.h>
24#include <iprt/asm.h>
25
26__BEGIN_DECLS
27
28
29/** Pointer to an internal network ring-0 instance. */
30typedef struct INTNET *PINTNET;
31
32/**
33 * Generic two-sided ring buffer.
34 *
35 * The deal is that there is exactly one writer and one reader.
36 * When offRead equals offWrite the buffer is empty. In the other
37 * extreme the writer will not use the last free byte in the buffer.
38 */
39typedef struct INTNETRINGBUF
40{
41 /** The start of the buffer offset relative to the. (inclusive) */
42 uint32_t offStart;
43 /** The offset to the end of the buffer. (exclusive) */
44 uint32_t offEnd;
45 /** The current read offset. */
46 uint32_t volatile offRead;
47 /** The current write offset. */
48 uint32_t volatile offWrite;
49} INTNETRINGBUF;
50/** Pointer to a ring buffer. */
51typedef INTNETRINGBUF *PINTNETRINGBUF;
52
53/**
54 * Get the amount of space available for writing.
55 *
56 * @returns Number of available bytes.
57 * @param pRingBuf The ring buffer.
58 */
59DECLINLINE(uint32_t) INTNETRingGetWritable(PINTNETRINGBUF pRingBuf)
60{
61 return pRingBuf->offRead <= pRingBuf->offWrite
62 ? pRingBuf->offEnd - pRingBuf->offWrite + pRingBuf->offRead - pRingBuf->offStart - 1
63 : pRingBuf->offRead - pRingBuf->offWrite - 1;
64}
65
66
67/**
68 * Get the amount of data ready for reading.
69 *
70 * @returns Number of ready bytes.
71 * @param pRingBuf The ring buffer.
72 */
73DECLINLINE(uint32_t) INTNETRingGetReadable(PINTNETRINGBUF pRingBuf)
74{
75 return pRingBuf->offRead <= pRingBuf->offWrite
76 ? pRingBuf->offWrite - pRingBuf->offRead
77 : pRingBuf->offEnd - pRingBuf->offRead + pRingBuf->offWrite - pRingBuf->offStart;
78}
79
80
81/**
82 * A interface buffer.
83 */
84typedef struct INTNETBUF
85{
86 /** The size of the entire buffer. */
87 uint32_t cbBuf;
88 /** The size of the send area. */
89 uint32_t cbSend;
90 /** The size of the receive area. */
91 uint32_t cbRecv;
92 /** The receive buffer. */
93 INTNETRINGBUF Recv;
94 /** The send buffer. */
95 INTNETRINGBUF Send;
96 /** Number of times yields help solve an overflow. */
97 STAMCOUNTER cStatYieldsOk;
98 /** Number of times yields didn't help solve an overflow. */
99 STAMCOUNTER cStatYieldsNok;
100 /** Number of lost packets due to overflows. */
101 STAMCOUNTER cStatLost;
102 /** Number of packets received (not counting lost ones). */
103 STAMCOUNTER cStatRecvs;
104 /** Number of frame bytes received (not couting lost frames). */
105 STAMCOUNTER cbStatRecv;
106 /** Number of packets received. */
107 STAMCOUNTER cStatSends;
108 /** Number of frame bytes sent. */
109 STAMCOUNTER cbStatSend;
110} INTNETBUF;
111typedef INTNETBUF *PINTNETBUF;
112
113/** Internal networking interface handle. */
114typedef uint32_t INTNETIFHANDLE;
115/** Pointer to an internal networking interface handle. */
116typedef INTNETIFHANDLE *PINTNETIFHANDLE;
117
118/** Or mask to obscure the handle index. */
119#define INTNET_HANDLE_MAGIC 0x88880000
120/** Mask to extract the handle index. */
121#define INTNET_HANDLE_INDEX_MASK 0xffff
122/** The maximum number of handles (exclusive) */
123#define INTNET_HANDLE_MAX 0xffff
124/** Invalid handle. */
125#define INTNET_HANDLE_INVALID (0)
126
127
128/**
129 * The packet header.
130 *
131 * The header is intentionally 8 bytes long. It will always
132 * start at an 8 byte aligned address. Assuming that the buffer
133 * size is a multiple of 8 bytes, that means that we can guarantee
134 * that the entire header is contiguous in both virtual and physical
135 * memory.
136 */
137#pragma pack(1)
138typedef struct INTNETHDR
139{
140 /** Header type. This is currently serving as a magic, it
141 * can be extended later to encode special command packets and stuff.. */
142 uint16_t u16Type;
143 /** The size of the frame. */
144 uint16_t cbFrame;
145 /** The offset from the start of this header to where the actual frame starts.
146 * This is used to keep the frame it self continguous in virtual memory and
147 * thereby both simplify reading and */
148 int32_t offFrame;
149} INTNETHDR, *PINTNETHDR;
150#pragma pack()
151
152/** INTNETHDR::u16Type value for normal frames. */
153#define INTNETHDR_TYPE_FRAME 0x2442
154
155
156/**
157 * Calculates the pointer to the frame.
158 *
159 * @returns Pointer to the start of the frame.
160 * @param pHdr Pointer to the packet header
161 * @param pBuf The buffer the header is within. Only used in strict builds.
162 */
163DECLINLINE(void *) INTNETHdrGetFramePtr(PINTNETHDR pHdr, PINTNETBUF pBuf)
164{
165 uint8_t *pu8 = (uint8_t *)pHdr + pHdr->offFrame;
166#ifdef VBOX_STRICT
167 const uintptr_t off = (uintptr_t)pu8 - (uintptr_t)pBuf;
168 Assert(pHdr->u16Type == INTNETHDR_TYPE_FRAME);
169 Assert(off < pBuf->cbBuf);
170 Assert(off + pHdr->cbFrame <= pBuf->cbBuf);
171#endif
172 NOREF(pBuf);
173 return pu8;
174}
175
176
177/**
178 * Skips to the next (read) frame in the buffer.
179 *
180 * @param pBuf The buffer.
181 * @param pRingBuf The ring buffer in question.
182 */
183DECLINLINE(void) INTNETRingSkipFrame(PINTNETBUF pBuf, PINTNETRINGBUF pRingBuf)
184{
185 Assert(pRingBuf->offRead < pBuf->cbBuf);
186 Assert(pRingBuf->offRead >= pRingBuf->offStart);
187 Assert(pRingBuf->offRead < pRingBuf->offEnd);
188 uint32_t offRead = pRingBuf->offRead;
189 PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pBuf + offRead);
190
191 /* skip the frame */
192 offRead += pHdr->offFrame + pHdr->cbFrame;
193 offRead = RT_ALIGN_32(offRead, sizeof(INTNETHDR));
194 Assert(offRead <= pRingBuf->offEnd && offRead >= pRingBuf->offStart);
195 if (offRead >= pRingBuf->offEnd)
196 offRead = pRingBuf->offStart;
197 ASMAtomicXchgU32(&pRingBuf->offRead, offRead);
198}
199
200/** The maximum length of a network name. */
201#define INTNET_MAX_NETWORK_NAME 128
202
203
204/**
205 * Request buffer for INTNETR0OpenReq / VMMR0_DO_INTNET_OPEN.
206 * @see INTNETR0Open.
207 */
208typedef struct INTNETOPENREQ
209{
210 /** The request header. */
211 SUPVMMR0REQHDR Hdr;
212 /** The network name. (input) */
213 char szNetwork[INTNET_MAX_NETWORK_NAME];
214 /** The size of the send buffer. (input) */
215 uint32_t cbSend;
216 /** The size of the receive buffer. (input) */
217 uint32_t cbRecv;
218 /** Whether new participants should be subjected to access check or not. */
219 bool fRestrictAccess;
220 /** The handle to the network interface. (output) */
221 INTNETIFHANDLE hIf;
222} INTNETOPENREQ;
223/** Pointer to an INTNETR0OpenReq / VMMR0_DO_INTNET_OPEN request buffer. */
224typedef INTNETOPENREQ *PINTNETOPENREQ;
225
226INTNETR0DECL(int) INTNETR0OpenReq(PINTNET pIntNet, PSUPDRVSESSION pSession, PINTNETOPENREQ pReq);
227
228
229/**
230 * Request buffer for INTNETR0IfCloseReq / VMMR0_DO_INTNET_IF_CLOSE.
231 * @see INTNETR0IfClose.
232 */
233typedef struct INTNETIFCLOSEREQ
234{
235 /** The request header. */
236 SUPVMMR0REQHDR Hdr;
237 /** The handle to the network interface. */
238 INTNETIFHANDLE hIf;
239} INTNETIFCLOSEREQ;
240/** Pointer to an INTNETR0IfCloseReq / VMMR0_DO_INTNET_IF_CLOSE request buffer. */
241typedef INTNETIFCLOSEREQ *PINTNETIFCLOSEREQ;
242
243INTNETR0DECL(int) INTNETR0IfCloseReq(PINTNET pIntNet, PINTNETIFCLOSEREQ pReq);
244
245
246/**
247 * Request buffer for INTNETR0IfGetRing3BufferReq / VMMR0_DO_INTNET_IF_GET_RING3_BUFFER.
248 * @see INTNETR0IfGetRing3Buffer.
249 */
250typedef struct INTNETIFGETRING3BUFFERREQ
251{
252 /** The request header. */
253 SUPVMMR0REQHDR Hdr;
254 /** Handle to the interface. */
255 INTNETIFHANDLE hIf;
256 /** The pointer to the ring3 buffer. (output) */
257 R3PTRTYPE(PINTNETBUF) pRing3Buf;
258} INTNETIFGETRING3BUFFERREQ;
259/** Pointer to an INTNETR0IfGetRing3BufferReq / VMMR0_DO_INTNET_IF_GET_RING3_BUFFER request buffer. */
260typedef INTNETIFGETRING3BUFFERREQ *PINTNETIFGETRING3BUFFERREQ;
261
262INTNETR0DECL(int) INTNETR0IfGetRing3BufferReq(PINTNET pIntNet, PINTNETIFGETRING3BUFFERREQ pReq);
263
264
265/**
266 * Request buffer for INTNETR0IfSetPromiscuousModeReq / VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE.
267 * @see INTNETR0IfSetPromiscuousMode.
268 */
269typedef struct INTNETIFSETPROMISCUOUSMODEREQ
270{
271 /** The request header. */
272 SUPVMMR0REQHDR Hdr;
273 /** Handle to the interface. */
274 INTNETIFHANDLE hIf;
275 /** The new promiscuous mode. */
276 bool fPromiscuous;
277} INTNETIFSETPROMISCUOUSMODEREQ;
278/** Pointer to an INTNETR0IfSetPromiscuousModeReq / VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE request buffer. */
279typedef INTNETIFSETPROMISCUOUSMODEREQ *PINTNETIFSETPROMISCUOUSMODEREQ;
280
281INTNETR0DECL(int) INTNETR0IfSetPromiscuousModeReq(PINTNET pIntNet, PINTNETIFSETPROMISCUOUSMODEREQ pReq);
282
283
284/**
285 * Request buffer for INTNETR0IfSendReq / VMMR0_DO_INTNET_IF_SEND.
286 * @see INTNETR0IfSend.
287 */
288typedef struct INTNETIFSENDREQ
289{
290 /** The request header. */
291 SUPVMMR0REQHDR Hdr;
292 /** Handle to the interface. */
293 INTNETIFHANDLE hIf;
294} INTNETIFSENDREQ;
295/** Pointer to an INTNETR0IfSend() argument package. */
296typedef INTNETIFSENDREQ *PINTNETIFSENDREQ;
297
298INTNETR0DECL(int) INTNETR0IfSendReq(PINTNET pIntNet, PINTNETIFSENDREQ pReq);
299
300
301/**
302 * Request buffer for INTNETR0IfWaitReq / VMMR0_DO_INTNET_IF_WAIT.
303 * @see INTNETR0IfWait.
304 */
305typedef struct INTNETIFWAITREQ
306{
307 /** The request header. */
308 SUPVMMR0REQHDR Hdr;
309 /** Handle to the interface. */
310 INTNETIFHANDLE hIf;
311 /** The number of milliseconds to wait. */
312 uint32_t cMillies;
313} INTNETIFWAITREQ;
314/** Pointer to an INTNETR0IfWaitReq / VMMR0_DO_INTNET_IF_WAIT request buffer. */
315typedef INTNETIFWAITREQ *PINTNETIFWAITREQ;
316
317INTNETR0DECL(int) INTNETR0IfWaitReq(PINTNET pIntNet, PINTNETIFWAITREQ pReq);
318
319
320#if defined(IN_RING0) || defined(IN_INTNET_TESTCASE)
321/** @name
322 * @{
323 */
324
325/**
326 * Create an instance of the Ring-0 internal networking service.
327 *
328 * @returns VBox status code.
329 * @param ppIntNet Where to store the instance pointer.
330 */
331INTNETR0DECL(int) INTNETR0Create(PINTNET *ppIntNet);
332
333/**
334 * Destroys an instance of the Ring-0 internal networking service.
335 *
336 * @param pIntNet Pointer to the instance data.
337 */
338INTNETR0DECL(void) INTNETR0Destroy(PINTNET pIntNet);
339
340/**
341 * Opens a network interface and attaches it to the specified network.
342 *
343 * @returns VBox status code.
344 * @param pIntNet The internal network instance.
345 * @param pSession The session handle.
346 * @param pszNetwork The network name.
347 * @param cbSend The send buffer size.
348 * @param cbRecv The receive buffer size.
349 * @param fRestrictAccess Whether new participants should be subjected to access check or not.
350 * @param phIf Where to store the handle to the network interface.
351 */
352INTNETR0DECL(int) INTNETR0Open(PINTNET pIntNet, PSUPDRVSESSION pSession, const char *pszNetwork, unsigned cbSend, unsigned cbRecv, bool fRestrictAccess, PINTNETIFHANDLE phIf);
353
354/**
355 * Close an interface.
356 *
357 * @returns VBox status code.
358 * @param pIntNet The instance handle.
359 * @param hIf The interface handle.
360 */
361INTNETR0DECL(int) INTNETR0IfClose(PINTNET pIntNet, INTNETIFHANDLE hIf);
362
363/**
364 * Gets the ring-0 address of the current buffer.
365 *
366 * @returns VBox status code.
367 * @param pIntNet The instance data.
368 * @param hIF The interface handle.
369 * @param ppRing0Buf Where to store the address of the ring-3 mapping.
370 */
371INTNETR0DECL(int) INTNETR0IfGetRing0Buffer(PINTNET pIntNet, INTNETIFHANDLE hIf, PINTNETBUF *ppRing0Buf);
372
373/**
374 * Maps the default buffer into ring 3.
375 *
376 * @returns VBox status code.
377 * @param pIntNet The instance data.
378 * @param hIF The interface handle.
379 * @param ppRing3Buf Where to store the address of the ring-3 mapping.
380 */
381INTNETR0DECL(int) INTNETR0IfGetRing3Buffer(PINTNET pIntNet, INTNETIFHANDLE hIf, R3PTRTYPE(PINTNETBUF) *ppRing3Buf);
382
383/**
384 * Sets the promiscuous mode property of an interface.
385 *
386 * @returns VBox status code.
387 * @param pIntNet The instance handle.
388 * @param hIf The interface handle.
389 * @param fPromiscuous Set if the interface should be in promiscuous mode, clear if not.
390 */
391INTNETR0DECL(int) INTNETR0IfSetPromiscuousMode(PINTNET pIntNet, INTNETIFHANDLE hIf, bool fPromiscuous);
392
393/**
394 * Sends one or more frames.
395 *
396 * The function will first the frame which is passed as the optional
397 * arguments pvFrame and cbFrame. These are optional since it also
398 * possible to chain together one or more frames in the send buffer
399 * which the function will process after considering it's arguments.
400 *
401 * @returns VBox status code.
402 * @param pIntNet The instance data.
403 * @param hIF The interface handle.
404 * @param pvFrame Pointer to the frame.
405 * @param cbFrame Size of the frame.
406 */
407INTNETR0DECL(int) INTNETR0IfSend(PINTNET pIntNet, INTNETIFHANDLE hIf, const void *pvFrame, unsigned cbFrame);
408
409/**
410 * Wait for the interface to get signaled.
411 * The interface will be signaled when is put into the receive buffer.
412 *
413 * @returns VBox status code.
414 * @param pIntNet The instance handle.
415 * @param hIf The interface handle.
416 * @param cMillies Number of milliseconds to wait. RT_INDEFINITE_WAIT should be
417 * used if indefinite wait is desired.
418 */
419INTNETR0DECL(int) INTNETR0IfWait(PINTNET pIntNet, INTNETIFHANDLE hIf, uint32_t cMillies);
420
421/** @} */
422#endif /* IN_RING0 */
423
424__END_DECLS
425
426#endif
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use