Changeset 24123 in vbox for trunk/src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c
- Timestamp:
- Oct 28, 2009 2:46:59 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c
r23526 r24123 44 44 #include <sys/sockio.h> 45 45 #include <sys/syscallsubr.h> 46 #include <sys/queue.h> 47 #include <sys/taskqueue.h> 46 48 47 49 #include <net/if.h> … … 79 81 static ng_disconnect_t ng_vboxnetflt_disconnect; 80 82 static int ng_vboxnetflt_mod_event(module_t mod, int event, void *data); 81 static int ng_vboxnetflt_rcv_in(hook_p node, item_p item);82 static int ng_vboxnetflt_rcv_out(hook_p node, item_p item);83 83 84 84 /** Netgraph node type */ … … 113 113 .version = NG_ABI_VERSION, 114 114 .name = NG_VBOXNETFLT_NODE_TYPE, 115 .mod_event = vboxnetflt_modevent, 116 .constructor = ng_vboxnetflt_constructor, 115 .mod_event = vboxnetflt_modevent, 116 .constructor = ng_vboxnetflt_constructor, 117 117 .rcvmsg = ng_vboxnetflt_rcvmsg, 118 118 .shutdown = ng_vboxnetflt_shutdown, … … 268 268 { 269 269 #if __FreeBSD_version >= 800000 270 NG_HOOK_SET_RCVDATA(hook, ng_vboxnetflt_rcv_in);271 270 NG_HOOK_SET_TO_INBOUND(hook); 272 271 #endif … … 275 274 else if (strcmp(name, NG_VBOXNETFLT_HOOK_OUT) == 0) 276 275 { 277 #if __FreeBSD_version >= 800000278 NG_HOOK_SET_RCVDATA(hook, ng_vboxnetflt_rcv_out);279 #endif280 276 pThis->u.s.output = hook; 281 277 } … … 311 307 /** 312 308 * Handle data on netgraph hooks. 309 * Frames processing is deferred to a taskqueue because this might 310 * be called with non-sleepable locks held and code paths inside 311 * the virtual switch might sleep. 313 312 */ 314 313 static int ng_vboxnetflt_rcvdata(hook_p hook, item_p item) 315 314 { 316 const node_p node = NG_HOOK_NODE(hook);317 PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);318 struct mbuf *m;319 320 if (pThis->u.s.input == hook)321 return ng_vboxnetflt_rcv_in(hook, item);322 else if (pThis->u.s.output == hook)323 return ng_vboxnetflt_rcv_out(hook, item);324 else325 {326 NGI_GET_M(item, m);327 NG_FREE_ITEM(item);328 }329 return (0);330 }331 332 /**333 * Handle incoming hook. This is connected to the334 * input path of the interface, thus handling incoming frames.335 */336 static int ng_vboxnetflt_rcv_in(hook_p hook, item_p item)337 {338 struct mbuf *m, *m0;339 struct m_tag *mtag;340 315 const node_p node = NG_HOOK_NODE(hook); 341 316 PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node); 342 317 struct ifnet *ifp = pThis->u.s.ifp; 343 bool fActive, fDropIt = false; 344 unsigned int cSegs = 0; 345 PINTNETSG pSG; 318 struct mbuf *m; 319 struct m_tag *mtag; 320 bool fActive; 321 322 fActive = ASMAtomicUoReadBool(&pThis->fActive); 346 323 347 324 NGI_GET_M(item, m); 348 325 NG_FREE_ITEM(item); 349 326 350 fActive = ASMAtomicUoReadBool(&pThis->fActive); 351 if (!fActive) 352 goto out; 353 327 /* Locate tag to see if processing should be skipped for this frame */ 354 328 mtag = m_tag_locate(m, MTAG_VBOX, PACKET_TAG_VBOX, NULL); 355 329 if (mtag != NULL) … … 357 331 m_tag_unlink(m, mtag); 358 332 m_tag_free(mtag); 359 goto out; 360 } 361 vboxNetFltRetain(pThis, true /* fBusy */); 362 363 for (m0 = m; m0 != NULL; m0 = m0->m_next) 364 { 365 if (m0->m_len > 0) 366 cSegs++; 367 } 368 369 #ifdef PADD_RUNT_FRAMES_FROM_HOST 370 if (m_length(m, NULL) < 60) 371 cSegs++; 372 #endif 373 374 /* Create a copy of the mbuf and hand it to the virtual switch */ 375 pSG = RTMemTmpAlloc(RT_OFFSETOF(INTNETSG, aSegs[cSegs])); 376 vboxNetFltFreeBSDMBufToSG(pThis, m, pSG, cSegs, 0); 377 fDropIt = pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, pSG, INTNETTRUNKDIR_WIRE); 378 RTMemTmpFree(pSG); 379 vboxNetFltRelease(pThis, true /* fBusy */); 380 381 out: 382 /* Only deliver it to the host stack if the destination weren't a guest */ 383 if (fDropIt) 333 } 334 335 /* 336 * Handle incoming hook. This is connected to the 337 * input path of the interface, thus handling incoming frames. 338 */ 339 if (pThis->u.s.input == hook) 340 { 341 if (mtag != NULL || !fActive) 342 { 343 ether_demux(ifp, m); 344 return (0); 345 } 346 mtx_lock_spin(&pThis->u.s.inq.ifq_mtx); 347 _IF_ENQUEUE(&pThis->u.s.inq, m); 348 mtx_unlock_spin(&pThis->u.s.inq.ifq_mtx); 349 taskqueue_enqueue_fast(taskqueue_fast, &pThis->u.s.tskin); 350 } 351 /** 352 * Handle mbufs on the outgoing hook, frames going to the interface 353 */ 354 else if (pThis->u.s.output == hook) 355 { 356 if (mtag != NULL || !fActive) 357 return ether_output_frame(ifp, m); 358 mtx_lock_spin(&pThis->u.s.outq.ifq_mtx); 359 _IF_ENQUEUE(&pThis->u.s.outq, m); 360 mtx_unlock_spin(&pThis->u.s.outq.ifq_mtx); 361 taskqueue_enqueue_fast(taskqueue_fast, &pThis->u.s.tskout); 362 } 363 else 384 364 { 385 365 m_freem(m); 386 return (0); 387 } 388 ether_demux(ifp, m); 366 } 389 367 return (0); 390 }391 392 /**393 * Handle mbufs on the outgoing hook, frames going to the interface394 */395 static int ng_vboxnetflt_rcv_out(hook_p hook, item_p item)396 {397 struct mbuf *m, *m0;398 struct m_tag *mtag;399 const node_p node = NG_HOOK_NODE(hook);400 PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);401 struct ifnet *ifp = pThis->u.s.ifp;402 unsigned int cSegs = 0;403 bool fDropIt = false, fActive;404 PINTNETSG pSG;405 406 NGI_GET_M(item, m);407 NG_FREE_ITEM(item);408 409 fActive = ASMAtomicUoReadBool(&pThis->fActive);410 if (!fActive)411 return ether_output_frame(ifp, m);412 413 vboxNetFltRetain(pThis, true /* fBusy */);414 /* Pass directly to interface if the packet originated from us */415 mtag = m_tag_locate(m, MTAG_VBOX, PACKET_TAG_VBOX, NULL);416 if (mtag != NULL)417 {418 m_tag_unlink(m, mtag);419 m_tag_free(mtag);420 goto out;421 }422 423 for (m0 = m; m0 != NULL; m0 = m0->m_next)424 {425 if (m0->m_len > 0)426 cSegs++;427 }428 429 #ifdef PADD_RUNT_FRAMES_FROM_HOST430 if (m_length(m, NULL) < 60)431 cSegs++;432 #endif433 /* Create a copy and deliver to the virtual switch */434 pSG = RTMemTmpAlloc(RT_OFFSETOF(INTNETSG, aSegs[cSegs]));435 vboxNetFltFreeBSDMBufToSG(pThis, m, pSG, cSegs, 0);436 fDropIt = pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, pSG, INTNETTRUNKDIR_HOST);437 RTMemTmpFree(pSG);438 439 out:440 vboxNetFltRelease(pThis, true /* fBusy */);441 if (fDropIt)442 {443 m_freem(m);444 return (0);445 }446 447 return ether_output_frame(ifp, m);448 368 } 449 369 … … 464 384 { 465 385 return (0); 386 } 387 388 /** 389 * Input processing task, handles incoming frames 390 */ 391 static void vboxNetFltFreeBSDinput(void *arg, int pending) 392 { 393 PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)arg; 394 struct mbuf *m, *m0; 395 struct ifnet *ifp = pThis->u.s.ifp; 396 unsigned int cSegs = 0; 397 bool fDropIt = false, fActive; 398 PINTNETSG pSG; 399 400 vboxNetFltRetain(pThis, true /* fBusy */); 401 for (;;) 402 { 403 mtx_lock_spin(&pThis->u.s.inq.ifq_mtx); 404 _IF_DEQUEUE(&pThis->u.s.inq, m); 405 mtx_unlock_spin(&pThis->u.s.inq.ifq_mtx); 406 if (m == NULL) 407 break; 408 409 for (m0 = m; m0 != NULL; m0 = m0->m_next) 410 if (m0->m_len > 0) 411 cSegs++; 412 413 #ifdef PADD_RUNT_FRAMES_FROM_HOST 414 if (m_length(m, NULL) < 60) 415 cSegs++; 416 #endif 417 418 /* Create a copy and deliver to the virtual switch */ 419 pSG = RTMemTmpAlloc(RT_OFFSETOF(INTNETSG, aSegs[cSegs])); 420 vboxNetFltFreeBSDMBufToSG(pThis, m, pSG, cSegs, 0); 421 fDropIt = pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, pSG, INTNETTRUNKDIR_HOST); 422 RTMemTmpFree(pSG); 423 if (fDropIt) 424 m_freem(m); 425 else 426 ether_demux(ifp, m); 427 } 428 vboxNetFltRelease(pThis, true /* fBusy */); 429 } 430 431 /** 432 * Output processing task, handles outgoing frames 433 */ 434 static void vboxNetFltFreeBSDoutput(void *arg, int pending) 435 { 436 PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)arg; 437 struct mbuf *m, *m0; 438 struct ifnet *ifp = pThis->u.s.ifp; 439 unsigned int cSegs = 0; 440 bool fDropIt = false, fActive; 441 PINTNETSG pSG; 442 443 vboxNetFltRetain(pThis, true /* fBusy */); 444 for (;;) 445 { 446 mtx_lock_spin(&pThis->u.s.outq.ifq_mtx); 447 _IF_DEQUEUE(&pThis->u.s.outq, m); 448 mtx_unlock_spin(&pThis->u.s.outq.ifq_mtx); 449 if (m == NULL) 450 break; 451 452 for (m0 = m; m0 != NULL; m0 = m0->m_next) 453 if (m0->m_len > 0) 454 cSegs++; 455 456 #ifdef PADD_RUNT_FRAMES_FROM_HOST 457 if (m_length(m, NULL) < 60) 458 cSegs++; 459 #endif 460 /* Create a copy and deliver to the virtual switch */ 461 pSG = RTMemTmpAlloc(RT_OFFSETOF(INTNETSG, aSegs[cSegs])); 462 vboxNetFltFreeBSDMBufToSG(pThis, m, pSG, cSegs, 0); 463 fDropIt = pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, pSG, INTNETTRUNKDIR_HOST); 464 RTMemTmpFree(pSG); 465 466 if (fDropIt) 467 m_freem(m); 468 else 469 ether_output_frame(ifp, m); 470 } 471 vboxNetFltRelease(pThis, true /* fBusy */); 466 472 } 467 473 … … 537 543 /* Create a new netgraph node for this instance */ 538 544 if (ng_make_node_common(&ng_vboxnetflt_typestruct, &node) != 0) 539 return VERR_INTERNAL_ERROR; 545 return VERR_INTERNAL_ERROR; 540 546 541 547 RTSpinlockAcquire(pThis->hSpinlock, &Tmp); … … 544 550 bcopy(IF_LLADDR(ifp), &pThis->u.s.Mac, ETHER_ADDR_LEN); 545 551 ASMAtomicUoWriteBool(&pThis->fDisconnectedFromHost, false); 552 /* Initialize deferred input queue */ 553 bzero(&pThis->u.s.inq, sizeof(struct ifqueue)); 554 mtx_init(&pThis->u.s.inq.ifq_mtx, "vboxnetflt inq", NULL, MTX_SPIN); 555 TASK_INIT(&pThis->u.s.tskin, 0, vboxNetFltFreeBSDinput, pThis); 556 557 /* Initialize deferred output queue */ 558 bzero(&pThis->u.s.outq, sizeof(struct ifqueue)); 559 mtx_init(&pThis->u.s.outq.ifq_mtx, "vboxnetflt outq", NULL, MTX_SPIN); 560 TASK_INIT(&pThis->u.s.tskout, 0, vboxNetFltFreeBSDoutput, pThis); 561 546 562 RTSpinlockRelease(pThis->hSpinlock, &Tmp); 547 563 … … 572 588 573 589 if (ifp0 != NULL) 590 { 591 vboxNetFltOsDeleteInstance(pThis); 574 592 vboxNetFltOsInitInstance(pThis, NULL); 593 } 575 594 576 595 return !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost); … … 579 598 void vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis) 580 599 { 600 601 taskqueue_drain(taskqueue_fast, &pThis->u.s.tskin); 602 taskqueue_drain(taskqueue_fast, &pThis->u.s.tskout); 603 604 mtx_destroy(&pThis->u.s.inq.ifq_mtx); 605 mtx_destroy(&pThis->u.s.outq.ifq_mtx); 581 606 582 607 if (pThis->u.s.node != NULL)
Note:
See TracChangeset
for help on using the changeset viewer.