VirtualBox

source: vbox/trunk/include/VBox/intnetinline.h@ 27845

Last change on this file since 27845 was 27845, checked in by vboxsync, 15 years ago

build fix.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.6 KB
Line 
1/* $Id: intnetinline.h 27845 2010-03-30 21:09:26Z vboxsync $ */
2/** @file
3 * INTNET - Internal Networking, Inlined Code. (DEV,++)
4 *
5 * This is all inlined because it's too tedious to create 2-3 libraries to
6 * contain it all. Requires C++ since variables and code is mixed as usual.
7 */
8
9/*
10 * Copyright (C) 2006-2010 Sun Microsystems, Inc.
11 *
12 * This file is part of VirtualBox Open Source Edition (OSE), as
13 * available from http://www.virtualbox.org. This file is free software;
14 * you can redistribute it and/or modify it under the terms of the GNU
15 * General Public License (GPL) as published by the Free Software
16 * Foundation, in version 2 as it comes in the "COPYING" file of the
17 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19 *
20 * The contents of this file may alternatively be used under the terms
21 * of the Common Development and Distribution License Version 1.0
22 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
23 * VirtualBox OSE distribution, in which case the provisions of the
24 * CDDL are applicable instead of those of the GPL.
25 *
26 * You may elect to license modified versions of this file under the
27 * terms and conditions of either the GPL or the CDDL or both.
28 *
29 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
30 * Clara, CA 95054 USA or visit http://www.sun.com if you need
31 * additional information or have any questions.
32 */
33
34#ifndef ___VBox_intnetinline_h
35#define ___VBox_intnetinline_h
36
37#ifndef __cplusplus
38# error "C++ only header."
39#endif
40
41#include <VBox/intnet.h>
42#include <iprt/string.h>
43#include <iprt/assert.h>
44#include <iprt/err.h>
45#include <VBox/log.h>
46
47
48/**
49 * Get the amount of space available for writing.
50 *
51 * @returns Number of available bytes.
52 * @param pRingBuf The ring buffer.
53 */
54DECLINLINE(uint32_t) INTNETRingGetWritable(PINTNETRINGBUF pRingBuf)
55{
56 uint32_t const offRead = ASMAtomicUoReadU32(&pRingBuf->offReadX);
57 uint32_t const offWriteInt = ASMAtomicUoReadU32(&pRingBuf->offWriteInt);
58 return offRead <= offWriteInt
59 ? pRingBuf->offEnd - offWriteInt + offRead - pRingBuf->offStart - 1
60 : offRead - offWriteInt - 1;
61}
62
63
64/**
65 * Checks if the ring has more for us to read.
66 *
67 * @returns Number of ready bytes.
68 * @param pRingBuf The ring buffer.
69 */
70DECLINLINE(bool) INTNETRingHasMoreToRead(PINTNETRINGBUF pRingBuf)
71{
72 uint32_t const offRead = ASMAtomicUoReadU32(&pRingBuf->offReadX);
73 uint32_t const offWriteCom = ASMAtomicUoReadU32(&pRingBuf->offWriteCom);
74 return offRead != offWriteCom;
75}
76
77
78/**
79 * Gets the next frame to read.
80 *
81 * @returns Pointer to the next frame. NULL if done.
82 * @param pRingBuf The ring buffer.
83 */
84DECLINLINE(PINTNETHDR) INTNETRingGetNextFrameToRead(PINTNETRINGBUF pRingBuf)
85{
86 uint32_t const offRead = ASMAtomicUoReadU32(&pRingBuf->offReadX);
87 uint32_t const offWriteCom = ASMAtomicUoReadU32(&pRingBuf->offWriteCom);
88 if (offRead == offWriteCom)
89 return NULL;
90 return (PINTNETHDR)((uint8_t *)pRingBuf + offRead);
91}
92
93
94/**
95 * Get the amount of data ready for reading.
96 *
97 * @returns Number of ready bytes.
98 * @param pRingBuf The ring buffer.
99 */
100DECLINLINE(uint32_t) INTNETRingGetReadable(PINTNETRINGBUF pRingBuf)
101{
102 uint32_t const offRead = ASMAtomicUoReadU32(&pRingBuf->offReadX);
103 uint32_t const offWriteCom = ASMAtomicUoReadU32(&pRingBuf->offWriteCom);
104 return offRead <= offWriteCom
105 ? offWriteCom - offRead
106 : pRingBuf->offEnd - offRead + offWriteCom - pRingBuf->offStart;
107}
108
109
110/**
111 * Calculates the pointer to the frame.
112 *
113 * @returns Pointer to the start of the frame.
114 * @param pHdr Pointer to the packet header
115 * @param pBuf The buffer the header is within. Only used in strict builds.
116 */
117DECLINLINE(void *) INTNETHdrGetFramePtr(PCINTNETHDR pHdr, PCINTNETBUF pBuf)
118{
119 uint8_t *pu8 = (uint8_t *)pHdr + pHdr->offFrame;
120#ifdef VBOX_STRICT
121 const uintptr_t off = (uintptr_t)pu8 - (uintptr_t)pBuf;
122 Assert(pHdr->u16Type == INTNETHDR_TYPE_FRAME || pHdr->u16Type == INTNETHDR_TYPE_PADDING);
123 Assert(off < pBuf->cbBuf);
124 Assert(off + pHdr->cbFrame <= pBuf->cbBuf);
125#endif
126 NOREF(pBuf);
127 return pu8;
128}
129
130
131/**
132 * Skips to the next (read) frame in the buffer.
133 *
134 * @param pRingBuf The ring buffer in question.
135 */
136DECLINLINE(void) INTNETRingSkipFrame(PINTNETRINGBUF pRingBuf)
137{
138 uint32_t const offReadOld = ASMAtomicUoReadU32(&pRingBuf->offReadX);
139 PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pRingBuf + offReadOld);
140 Assert(offReadOld >= pRingBuf->offStart);
141 Assert(offReadOld < pRingBuf->offEnd);
142 Assert(RT_ALIGN_PT(pHdr, INTNETHDR_ALIGNMENT, INTNETHDR *) == pHdr);
143 Assert(pHdr->u16Type == INTNETHDR_TYPE_FRAME || pHdr->u16Type == INTNETHDR_TYPE_PADDING);
144
145 /* skip the frame */
146 uint32_t offReadNew = offReadOld + pHdr->offFrame + pHdr->cbFrame;
147 offReadNew = RT_ALIGN_32(offReadNew, INTNETHDR_ALIGNMENT);
148 Assert(offReadNew <= pRingBuf->offEnd && offReadNew >= pRingBuf->offStart);
149 if (offReadNew >= pRingBuf->offEnd)
150 offReadNew = pRingBuf->offStart;
151 Log2(("INTNETRingSkipFrame: offReadX: %#x -> %#x (1)\n", offReadOld, offReadNew));
152#ifdef INTNET_POISON_READ_FRAMES
153 memset((uint8_t *)pHdr + pHdr->offFrame, 0xfe, RT_ALIGN_32(pHdr->cbFrame, INTNETHDR_ALIGNMENT));
154 memset(pHdr, 0xef, sizeof(*pHdr));
155#endif
156 ASMAtomicWriteU32(&pRingBuf->offReadX, offReadNew);
157}
158
159
160/**
161 * Allocates a frame in the specified ring.
162 *
163 * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
164 * @param pRingBuf The ring buffer.
165 * @param cbFrame The frame size.
166 * @param ppHdr Where to return the frame header.
167 * Don't touch this!
168 * @param ppvFrame Where to return the frame pointer.
169 */
170DECLINLINE(int) INTNETRingAllocateFrame(PINTNETRINGBUF pRingBuf, uint32_t cbFrame, PINTNETHDR *ppHdr, void **ppvFrame)
171{
172 /*
173 * Validate input and adjust the input.
174 */
175 INTNETRINGBUF_ASSERT_SANITY(pRingBuf);
176 Assert(cbFrame >= sizeof(RTMAC) * 2);
177
178 const uint32_t cb = RT_ALIGN_32(cbFrame, INTNETHDR_ALIGNMENT);
179 uint32_t offWriteInt = ASMAtomicUoReadU32(&pRingBuf->offWriteInt);
180 uint32_t offRead = ASMAtomicUoReadU32(&pRingBuf->offReadX);
181 if (offRead <= offWriteInt)
182 {
183 /*
184 * Try fit it all before the end of the buffer.
185 */
186 if (pRingBuf->offEnd - offWriteInt >= cb + sizeof(INTNETHDR))
187 {
188 uint32_t offNew = offWriteInt + cb + sizeof(INTNETHDR);
189 if (offNew >= pRingBuf->offEnd)
190 offNew = pRingBuf->offStart;
191 if (RT_UNLIKELY(!ASMAtomicCmpXchgU32(&pRingBuf->offWriteInt, offNew, offWriteInt)))
192 return VERR_WRONG_ORDER; /* race */
193 Log2(("INTNETRingAllocateFrame: offWriteInt: %#x -> %#x (1) (offRead=%#x)\n", offWriteInt, offNew, offRead));
194
195 PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pRingBuf + offWriteInt);
196 pHdr->u16Type = INTNETHDR_TYPE_FRAME;
197 pHdr->cbFrame = (uint16_t)cbFrame; Assert(pHdr->cbFrame == cbFrame);
198 pHdr->offFrame = sizeof(INTNETHDR);
199
200 *ppHdr = pHdr;
201 *ppvFrame = pHdr + 1;
202 return VINF_SUCCESS;
203 }
204 /*
205 * Try fit the frame at the start of the buffer.
206 * (The header fits before the end of the buffer because of alignment.)
207 */
208 AssertMsg(pRingBuf->offEnd - offWriteInt >= sizeof(INTNETHDR), ("offEnd=%x offWriteInt=%x\n", pRingBuf->offEnd, offWriteInt));
209 if (offRead - pRingBuf->offStart > cb) /* not >= ! */
210 {
211 uint32_t offNew = pRingBuf->offStart + cb;
212 if (RT_UNLIKELY(!ASMAtomicCmpXchgU32(&pRingBuf->offWriteInt, offNew, offWriteInt)))
213 return VERR_WRONG_ORDER; /* race */
214 Log2(("INTNETRingAllocateFrame: offWriteInt: %#x -> %#x (2) (offRead=%#x)\n", offWriteInt, offNew, offRead));
215
216 PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pRingBuf + offWriteInt);
217 pHdr->u16Type = INTNETHDR_TYPE_FRAME;
218 pHdr->cbFrame = (uint16_t)cbFrame; Assert(pHdr->cbFrame == cbFrame);
219 pHdr->offFrame = pRingBuf->offStart - offWriteInt;
220
221 *ppHdr = pHdr;
222 *ppvFrame = (uint8_t *)pRingBuf + pRingBuf->offStart;
223 return VINF_SUCCESS;
224 }
225 }
226 /*
227 * The reader is ahead of the writer, try fit it into that space.
228 */
229 else if (offRead - offWriteInt > cb + sizeof(INTNETHDR)) /* not >= ! */
230 {
231 uint32_t offNew = offWriteInt + cb + sizeof(INTNETHDR);
232 if (RT_UNLIKELY(!ASMAtomicCmpXchgU32(&pRingBuf->offWriteInt, offNew, offWriteInt)))
233 return VERR_WRONG_ORDER; /* race */
234 Log2(("INTNETRingAllocateFrame: offWriteInt: %#x -> %#x (3) (offRead=%#x)\n", offWriteInt, offNew, offRead));
235
236 PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pRingBuf + offWriteInt);
237 pHdr->u16Type = INTNETHDR_TYPE_FRAME;
238 pHdr->cbFrame = (uint16_t)cbFrame; Assert(pHdr->cbFrame == cbFrame);
239 pHdr->offFrame = sizeof(INTNETHDR);
240
241 *ppHdr = pHdr;
242 *ppvFrame = pHdr + 1;
243 return VINF_SUCCESS;
244 }
245
246 /* (it didn't fit) */
247 STAM_REL_COUNTER_INC(&pRingBuf->cOverflows);
248 return VERR_BUFFER_OVERFLOW;
249}
250
251
252/**
253 * Commits a frame.
254 *
255 * Make sure to commit the frames in the order they've been allocated!
256 *
257 * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
258 * @param pRingBuf The ring buffer.
259 * @param pHdr The frame header returned by
260 * INTNETRingAllocateFrame.
261 */
262DECLINLINE(void) INTNETRingCommitFrame(PINTNETRINGBUF pRingBuf, PINTNETHDR pHdr)
263{
264 /*
265 * Validate input and commit order.
266 */
267 INTNETRINGBUF_ASSERT_SANITY(pRingBuf);
268 INTNETHDR_ASSERT_SANITY(pHdr, pRingBuf);
269 Assert(pRingBuf->offWriteCom == ((uintptr_t)pHdr - (uintptr_t)pRingBuf));
270
271 /*
272 * Figure out the offWriteCom for this packet and update the ring.
273 */
274 const uint32_t cbFrame = pHdr->cbFrame;
275 const uint32_t cb = RT_ALIGN_32(cbFrame, INTNETHDR_ALIGNMENT);
276 uint32_t offWriteCom = (uint32_t)((uintptr_t)pHdr - (uintptr_t)pRingBuf)
277 + pHdr->offFrame
278 + cb;
279 if (offWriteCom >= pRingBuf->offEnd)
280 {
281 Assert(offWriteCom == pRingBuf->offEnd);
282 offWriteCom = pRingBuf->offStart;
283 }
284 Log2(("INTNETRingCommitFrame: offWriteCom: %#x -> %#x (offRead=%#x)\n", pRingBuf->offWriteCom, offWriteCom, pRingBuf->offReadX));
285 ASMAtomicWriteU32(&pRingBuf->offWriteCom, offWriteCom);
286 STAM_REL_COUNTER_ADD(&pRingBuf->cbStatWritten, cbFrame);
287 STAM_REL_COUNTER_INC(&pRingBuf->cStatFrames);
288}
289
290
291/**
292 * Commits a frame and injects a filler frame if not all of the buffer was used.
293 *
294 * Make sure to commit the frames in the order they've been allocated!
295 *
296 * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
297 * @param pRingBuf The ring buffer.
298 * @param pHdr The frame header returned by
299 * INTNETRingAllocateFrame.
300 * @param cbUsed The amount of space actually used.
301 */
302DECLINLINE(void) INTNETRingCommitFrameEx(PINTNETRINGBUF pRingBuf, PINTNETHDR pHdr, size_t cbUsed)
303{
304 /*
305 * Validate input and commit order.
306 */
307 INTNETRINGBUF_ASSERT_SANITY(pRingBuf);
308 INTNETHDR_ASSERT_SANITY(pHdr, pRingBuf);
309 Assert(pRingBuf->offWriteCom == ((uintptr_t)pHdr - (uintptr_t)pRingBuf));
310
311 /*
312 * Calc the new write commit offset.
313 */
314 const uint32_t cbAlignedFrame = RT_ALIGN_32(pHdr->cbFrame, INTNETHDR_ALIGNMENT);
315 const uint32_t cbAlignedUsed = RT_ALIGN_32(cbUsed, INTNETHDR_ALIGNMENT);
316 uint32_t offWriteCom = (uint32_t)((uintptr_t)pHdr - (uintptr_t)pRingBuf)
317 + pHdr->offFrame
318 + cbAlignedFrame;
319 if (offWriteCom >= pRingBuf->offEnd)
320 {
321 Assert(offWriteCom == pRingBuf->offEnd);
322 offWriteCom = pRingBuf->offStart;
323 }
324
325 /*
326 * Insert a dummy frame to pad any unused space.
327 */
328 if (cbAlignedFrame != cbAlignedUsed)
329 {
330 /** @todo Later: Try unallocate the extra memory. */
331 PINTNETHDR pHdrPadding = (PINTNETHDR)((uint8_t *)pHdr + pHdr->offFrame + cbAlignedUsed);
332 pHdrPadding->u16Type = INTNETHDR_TYPE_PADDING;
333 pHdrPadding->cbFrame = (uint16_t)(cbAlignedFrame - cbAlignedUsed - sizeof(INTNETHDR));
334 pHdrPadding->offFrame = sizeof(INTNETHDR);
335 pHdr->cbFrame = (uint16_t)cbUsed;
336 }
337
338 Log2(("INTNETRingCommitFrame: offWriteCom: %#x -> %#x (offRead=%#x)\n", pRingBuf->offWriteCom, offWriteCom, pRingBuf->offReadX));
339 ASMAtomicWriteU32(&pRingBuf->offWriteCom, offWriteCom);
340 STAM_REL_COUNTER_ADD(&pRingBuf->cbStatWritten, cbUsed);
341 STAM_REL_COUNTER_INC(&pRingBuf->cStatFrames);
342}
343
344
345/**
346 * Writes a frame to the specified ring.
347 *
348 * Make sure you don't have any uncommitted frames when calling this function!
349 *
350 * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
351 * @param pRingBuf The ring buffer.
352 * @param pvFrame The bits to write.
353 * @param cbFrame How much to write.
354 */
355DECLINLINE(int) INTNETRingWriteFrame(PINTNETRINGBUF pRingBuf, const void *pvFrame, size_t cbFrame)
356{
357 /*
358 * Validate input.
359 */
360 INTNETRINGBUF_ASSERT_SANITY(pRingBuf);
361 Assert(cbFrame >= sizeof(RTMAC) * 2);
362
363 /*
364 * Align the size and read the volatile ring buffer variables.
365 */
366 const uint32_t cb = RT_ALIGN_32(cbFrame, INTNETHDR_ALIGNMENT);
367 uint32_t offWriteInt = ASMAtomicUoReadU32(&pRingBuf->offWriteInt);
368 uint32_t offRead = ASMAtomicUoReadU32(&pRingBuf->offReadX);
369 if (offRead <= offWriteInt)
370 {
371 /*
372 * Try fit it all before the end of the buffer.
373 */
374 if (pRingBuf->offEnd - offWriteInt >= cb + sizeof(INTNETHDR))
375 {
376 uint32_t offNew = offWriteInt + cb + sizeof(INTNETHDR);
377 if (offNew >= pRingBuf->offEnd)
378 offNew = pRingBuf->offStart;
379 if (RT_UNLIKELY(!ASMAtomicCmpXchgU32(&pRingBuf->offWriteInt, offNew, offWriteInt)))
380 return VERR_WRONG_ORDER; /* race */
381 Log2(("INTNETRingWriteFrame: offWriteInt: %#x -> %#x (1)\n", offWriteInt, offNew));
382
383 PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pRingBuf + offWriteInt);
384 pHdr->u16Type = INTNETHDR_TYPE_FRAME;
385 pHdr->cbFrame = (uint16_t)cbFrame; Assert(pHdr->cbFrame == cbFrame);
386 pHdr->offFrame = sizeof(INTNETHDR);
387
388 memcpy(pHdr + 1, pvFrame, cbFrame);
389
390 Log2(("INTNETRingWriteFrame: offWriteCom: %#x -> %#x (1)\n", pRingBuf->offWriteCom, offNew));
391 ASMAtomicWriteU32(&pRingBuf->offWriteCom, offNew);
392 STAM_REL_COUNTER_ADD(&pRingBuf->cbStatWritten, cbFrame);
393 STAM_REL_COUNTER_INC(&pRingBuf->cStatFrames);
394 return VINF_SUCCESS;
395 }
396 /*
397 * Try fit the frame at the start of the buffer.
398 * (The header fits before the end of the buffer because of alignment.)
399 */
400 AssertMsg(pRingBuf->offEnd - offWriteInt >= sizeof(INTNETHDR), ("offEnd=%x offWriteInt=%x\n", pRingBuf->offEnd, offWriteInt));
401 if (offRead - pRingBuf->offStart > cb) /* not >= ! */
402 {
403 uint32_t offNew = pRingBuf->offStart + cb;
404 if (RT_UNLIKELY(!ASMAtomicCmpXchgU32(&pRingBuf->offWriteInt, offNew, offWriteInt)))
405 return VERR_WRONG_ORDER; /* race */
406 Log2(("INTNETRingWriteFrame: offWriteInt: %#x -> %#x (2)\n", offWriteInt, offNew));
407
408 PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pRingBuf + offWriteInt);
409 pHdr->u16Type = INTNETHDR_TYPE_FRAME;
410 pHdr->cbFrame = (uint16_t)cbFrame; Assert(pHdr->cbFrame == cbFrame);
411 pHdr->offFrame = pRingBuf->offStart - offWriteInt;
412
413 memcpy((uint8_t *)pRingBuf + pRingBuf->offStart, pvFrame, cbFrame);
414
415 Log2(("INTNETRingWriteFrame: offWriteCom: %#x -> %#x (2)\n", pRingBuf->offWriteCom, offNew));
416 ASMAtomicWriteU32(&pRingBuf->offWriteCom, offNew);
417 STAM_REL_COUNTER_ADD(&pRingBuf->cbStatWritten, cbFrame);
418 STAM_REL_COUNTER_INC(&pRingBuf->cStatFrames);
419 return VINF_SUCCESS;
420 }
421 }
422 /*
423 * The reader is ahead of the writer, try fit it into that space.
424 */
425 else if (offRead - offWriteInt > cb + sizeof(INTNETHDR)) /* not >= ! */
426 {
427 uint32_t offNew = offWriteInt + cb + sizeof(INTNETHDR);
428 if (RT_UNLIKELY(!ASMAtomicCmpXchgU32(&pRingBuf->offWriteInt, offNew, offWriteInt)))
429 return VERR_WRONG_ORDER; /* race */
430 Log2(("INTNETRingWriteFrame: offWriteInt: %#x -> %#x (3)\n", offWriteInt, offNew));
431
432 PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pRingBuf + offWriteInt);
433 pHdr->u16Type = INTNETHDR_TYPE_FRAME;
434 pHdr->cbFrame = (uint16_t)cbFrame; Assert(pHdr->cbFrame == cbFrame);
435 pHdr->offFrame = sizeof(INTNETHDR);
436
437 memcpy(pHdr + 1, pvFrame, cbFrame);
438
439 Log2(("INTNETRingWriteFrame: offWriteCom: %#x -> %#x (3)\n", pRingBuf->offWriteCom, offNew));
440 ASMAtomicWriteU32(&pRingBuf->offWriteCom, offNew);
441 STAM_REL_COUNTER_ADD(&pRingBuf->cbStatWritten, cbFrame);
442 STAM_REL_COUNTER_INC(&pRingBuf->cStatFrames);
443 return VINF_SUCCESS;
444 }
445
446 /* (it didn't fit) */
447 STAM_REL_COUNTER_INC(&pRingBuf->cOverflows);
448 return VERR_BUFFER_OVERFLOW;
449}
450
451
452/**
453 * Reads the next frame in the buffer and moves the read cursor past it.
454 *
455 * @returns Size of the frame in bytes. 0 is returned if nothing in the buffer.
456 * @param pRingBuff The ring buffer to read from.
457 * @param pvFrameDst Where to put the frame. The caller is responsible for
458 * ensuring that there is sufficient space for the frame.
459 *
460 * @deprecated Bad interface, do NOT use it! Only for tstIntNetR0.
461 */
462DECLINLINE(uint32_t) INTNETRingReadAndSkipFrame(PINTNETRINGBUF pRingBuf, void *pvFrameDst)
463{
464 INTNETRINGBUF_ASSERT_SANITY(pRingBuf);
465
466 uint32_t offRead = ASMAtomicUoReadU32(&pRingBuf->offReadX);
467 uint32_t const offWriteCom = ASMAtomicUoReadU32(&pRingBuf->offWriteCom);
468 if (offRead == offWriteCom)
469 return 0;
470
471 PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pRingBuf + offRead);
472 INTNETHDR_ASSERT_SANITY(pHdr, pRingBuf);
473
474 uint32_t const cbFrame = pHdr->cbFrame;
475 int32_t const offFrame = pHdr->offFrame;
476 const void *pvFrameSrc = (uint8_t *)pHdr + offFrame;
477 memcpy(pvFrameDst, pvFrameSrc, cbFrame);
478#ifdef INTNET_POISON_READ_FRAMES
479 memset((void *)pvFrameSrc, 0xfe, RT_ALIGN_32(cbFrame, INTNETHDR_ALIGNMENT));
480 memset(pHdr, 0xef, sizeof(*pHdr));
481#endif
482
483 /* skip the frame */
484 offRead += offFrame + cbFrame;
485 offRead = RT_ALIGN_32(offRead, INTNETHDR_ALIGNMENT);
486 Assert(offRead <= pRingBuf->offEnd && offRead >= pRingBuf->offStart);
487 if (offRead >= pRingBuf->offEnd)
488 offRead = pRingBuf->offStart;
489 ASMAtomicWriteU32(&pRingBuf->offReadX, offRead);
490 return cbFrame;
491}
492
493
494
495/**
496 * Initializes a buffer structure.
497 *
498 * @param pIntBuf The internal networking interface buffer. This
499 * expected to be cleared prior to calling this
500 * function.
501 * @param cbBuf The size of the whole buffer.
502 * @param cbRecv The receive size.
503 * @param cbSend The send size.
504 */
505DECLINLINE(void) INTNETBufInit(PINTNETBUF pIntBuf, uint32_t cbBuf, uint32_t cbRecv, uint32_t cbSend)
506{
507 AssertCompileSizeAlignment(INTNETBUF, INTNETHDR_ALIGNMENT);
508 AssertCompileSizeAlignment(INTNETBUF, INTNETRINGBUF_ALIGNMENT);
509 Assert(cbBuf >= sizeof(INTNETBUF) + cbRecv + cbSend);
510 Assert(RT_ALIGN_32(cbRecv, INTNETRINGBUF_ALIGNMENT) == cbRecv);
511 Assert(RT_ALIGN_32(cbSend, INTNETRINGBUF_ALIGNMENT) == cbSend);
512 Assert(ASMMemIsAll8(pIntBuf, cbBuf, '\0') == NULL);
513
514 pIntBuf->u32Magic = INTNETBUF_MAGIC;
515 pIntBuf->cbBuf = cbBuf;
516 pIntBuf->cbRecv = cbRecv;
517 pIntBuf->cbSend = cbSend;
518
519 /* receive ring buffer. */
520 uint32_t offBuf = RT_ALIGN_32(sizeof(INTNETBUF), INTNETRINGBUF_ALIGNMENT) - RT_OFFSETOF(INTNETBUF, Recv);
521 pIntBuf->Recv.offStart = offBuf;
522 pIntBuf->Recv.offReadX = offBuf;
523 pIntBuf->Recv.offWriteInt = offBuf;
524 pIntBuf->Recv.offWriteCom = offBuf;
525 pIntBuf->Recv.offEnd = offBuf + cbRecv;
526
527 /* send ring buffer. */
528 offBuf += cbRecv + RT_OFFSETOF(INTNETBUF, Recv) - RT_OFFSETOF(INTNETBUF, Send);
529 pIntBuf->Send.offStart = offBuf;
530 pIntBuf->Send.offReadX = offBuf;
531 pIntBuf->Send.offWriteCom = offBuf;
532 pIntBuf->Send.offWriteInt = offBuf;
533 pIntBuf->Send.offEnd = offBuf + cbSend;
534 Assert(cbBuf >= offBuf + cbSend);
535}
536
537#endif
538
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette