Changeset 28156 in vbox
- Timestamp:
- Apr 10, 2010 1:14:10 AM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 59887
- Location:
- trunk
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/pdmnetinline.h
r28153 r28156 158 158 * @param cbPayload The amount of payload. 159 159 * @param cbHdrs The size of all the headers. 160 * @param fPayloadChecksum Whether to checksum the payload or not. 160 161 * @internal 161 162 */ 162 163 DECLINLINE(void) pdmNetGsoUpdateUdpHdr(uint32_t u32PseudoSum, uint8_t *pbSegHdrs, uint8_t offUdpHdr, 163 uint8_t const *pbPayload, uint32_t cbPayload, uint8_t cbHdrs )164 uint8_t const *pbPayload, uint32_t cbPayload, uint8_t cbHdrs, bool fPayloadChecksum) 164 165 { 165 166 PRTNETUDP pUdpHdr = (PRTNETUDP)&pbSegHdrs[offUdpHdr]; 166 167 pUdpHdr->uh_ulen = cbPayload + cbHdrs - offUdpHdr; 167 pUdpHdr->uh_sum = RTNetUDPChecksum(u32PseudoSum, pUdpHdr);168 pUdpHdr->uh_sum = fPayloadChecksum ? RTNetUDPChecksum(u32PseudoSum, pUdpHdr) : 0; 168 169 } 169 170 … … 182 183 * @param cbHdrs The size of all the headers. 183 184 * @param fLastSeg Set if this is the last segment. 185 * @param fPayloadChecksum Whether to checksum the payload or not. 184 186 * @internal 185 187 */ 186 188 DECLINLINE(void) pdmNetGsoUpdateTcpHdr(uint32_t u32PseudoSum, uint8_t *pbSegHdrs, uint8_t offTcpHdr, 187 uint8_t const *pbPayload, uint32_t cbPayload, uint32_t offPayload, uint8_t cbHdrs, bool fLastSeg) 189 uint8_t const *pbPayload, uint32_t cbPayload, uint32_t offPayload, uint8_t cbHdrs, 190 bool fLastSeg, bool fPayloadChecksum) 188 191 { 189 192 PRTNETTCP pTcpHdr = (PRTNETTCP)&pbSegHdrs[offTcpHdr]; … … 191 194 if (!fLastSeg) 192 195 pTcpHdr->th_flags &= ~(RTNETTCP_F_FIN | RTNETTCP_F_PSH); 193 pTcpHdr->th_sum = RTNetTCPChecksum(u32PseudoSum, pTcpHdr, pbPayload, cbPayload);196 pTcpHdr->th_sum = fPayloadChecksum ? RTNetTCPChecksum(u32PseudoSum, pTcpHdr, pbPayload, cbPayload) : 0; 194 197 } 195 198 … … 298 301 pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, pGso->cbHdrs), 299 302 pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg, 300 pGso->cbHdrs, iSeg + 1 == cSegs );303 pGso->cbHdrs, iSeg + 1 == cSegs, true); 301 304 break; 302 305 case PDMNETWORKGSOTYPE_IPV4_UDP: 303 306 pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, pGso->cbHdrs), 304 pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs );307 pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, true); 305 308 break; 306 309 case PDMNETWORKGSOTYPE_IPV6_TCP: … … 308 311 pGso->offHdr2, RTNETIPV4_PROT_TCP), 309 312 pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg, 310 pGso->cbHdrs, iSeg + 1 == cSegs );313 pGso->cbHdrs, iSeg + 1 == cSegs, true); 311 314 break; 312 315 case PDMNETWORKGSOTYPE_IPV6_UDP: 313 316 pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, pGso->cbHdrs, 314 317 pGso->offHdr2, RTNETIPV4_PROT_UDP), 315 pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs );318 pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, true); 316 319 break; 317 320 case PDMNETWORKGSOTYPE_IPV4_IPV6_TCP: … … 320 323 cbSegPayload, pGso->cbHdrs, pGso->offHdr2, RTNETIPV4_PROT_TCP), 321 324 pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg, 322 pGso->cbHdrs, iSeg + 1 == cSegs );325 pGso->cbHdrs, iSeg + 1 == cSegs, true); 323 326 break; 324 327 case PDMNETWORKGSOTYPE_IPV4_IPV6_UDP: … … 326 329 pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pgmNetGsoCalcIpv6Offset(pbSegHdrs, pGso->offHdr1), 327 330 cbSegPayload, pGso->cbHdrs, pGso->offHdr2, RTNETIPV4_PROT_UDP), 328 pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs );331 pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, true); 329 332 break; 330 333 case PDMNETWORKGSOTYPE_INVALID: … … 391 394 pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, pGso->cbHdrs), 392 395 pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg, 393 pGso->cbHdrs, iSeg + 1 == cSegs );396 pGso->cbHdrs, iSeg + 1 == cSegs, true); 394 397 break; 395 398 case PDMNETWORKGSOTYPE_IPV4_UDP: 396 399 pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, pGso->cbHdrs), 397 pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs );400 pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, true); 398 401 break; 399 402 case PDMNETWORKGSOTYPE_IPV6_TCP: … … 401 404 pGso->offHdr2, RTNETIPV4_PROT_TCP), 402 405 pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg, 403 pGso->cbHdrs, iSeg + 1 == cSegs );406 pGso->cbHdrs, iSeg + 1 == cSegs, true); 404 407 break; 405 408 case PDMNETWORKGSOTYPE_IPV6_UDP: 406 409 pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, pGso->cbHdrs, 407 410 pGso->offHdr2, RTNETIPV4_PROT_UDP), 408 pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs );411 pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, true); 409 412 break; 410 413 case PDMNETWORKGSOTYPE_IPV4_IPV6_TCP: … … 413 416 cbSegPayload, pGso->cbHdrs, pGso->offHdr2, RTNETIPV4_PROT_TCP), 414 417 pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg, 415 pGso->cbHdrs, iSeg + 1 == cSegs );418 pGso->cbHdrs, iSeg + 1 == cSegs, true); 416 419 break; 417 420 case PDMNETWORKGSOTYPE_IPV4_IPV6_UDP: … … 419 422 pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pgmNetGsoCalcIpv6Offset(pbSegHdrs, pGso->offHdr1), 420 423 cbSegPayload, pGso->cbHdrs, pGso->offHdr2, RTNETIPV4_PROT_UDP), 421 pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs );424 pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrs, true); 422 425 break; 423 426 case PDMNETWORKGSOTYPE_INVALID: … … 432 435 433 436 434 435 436 DECLINLINE(void) PDMNetGsoPrepForDirectUse(PCPDMNETWORKGSO pGso, void *pvFrame, size_t cbFrame, 437 bool fHeaderChecskum, bool fPayloadChecksum) 438 { 439 /** @todo Need to implement this eventually, not important yet as it's only use 440 * by DHCP where GSO isn't normally used. */ 437 /** 438 * Prepares the GSO frame for direct use without any segmenting. 439 * 440 * @param pGso The GSO context. 441 * @param pvFrame The frame to prepare. 442 * @param cbFrame The frame size. 443 * @param fPayloadChecksum Whether to checksum payload. 444 */ 445 DECLINLINE(void) PDMNetGsoPrepForDirectUse(PCPDMNETWORKGSO pGso, void *pvFrame, size_t cbFrame, bool fPayloadChecksum) 446 { 447 /* 448 * Figure out where the payload is and where the header starts before we 449 * do the protocol bits. 450 */ 451 uint8_t * const pbHdrs = (uint8_t *)pvFrame; 452 uint8_t * const pbPayload = pbHdrs + pGso->cbHdrs; 453 size_t const cbPayload = cbFrame - pGso->cbHdrs; 454 455 /* 456 * Check assumptions (doing it after declaring the variables because of C). 457 */ 458 Assert(PDMNetGsoIsValid(pGso, sizeof(*pGso), cbFrame)); 459 460 /* 461 * Get down to busienss. 462 */ 463 switch ((PDMNETWORKGSOTYPE)pGso->u8Type) 464 { 465 case PDMNETWORKGSOTYPE_IPV4_TCP: 466 pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv4Hdr(pbHdrs, pGso->offHdr1, cbFrame - pGso->cbHdrs, 0, pGso->cbHdrs), 467 pbHdrs, pGso->offHdr2, pbPayload, cbPayload, 0, pGso->cbHdrs, true, fPayloadChecksum); 468 break; 469 case PDMNETWORKGSOTYPE_IPV4_UDP: 470 pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv4Hdr(pbHdrs, pGso->offHdr1, cbFrame - pGso->cbHdrs, 0, pGso->cbHdrs), 471 pbHdrs, pGso->offHdr2, pbPayload, cbPayload, pGso->cbHdrs, fPayloadChecksum); 472 break; 473 case PDMNETWORKGSOTYPE_IPV6_TCP: 474 pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv6Hdr(pbHdrs, pGso->offHdr1, cbPayload, pGso->cbHdrs, 475 pGso->offHdr2, RTNETIPV4_PROT_TCP), 476 pbHdrs, pGso->offHdr2, pbPayload, cbPayload, 0, pGso->cbHdrs, true, fPayloadChecksum); 477 break; 478 case PDMNETWORKGSOTYPE_IPV6_UDP: 479 pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbHdrs, pGso->offHdr1, cbPayload, pGso->cbHdrs, 480 pGso->offHdr2, RTNETIPV4_PROT_UDP), 481 pbHdrs, pGso->offHdr2, pbPayload, cbPayload, pGso->cbHdrs, fPayloadChecksum); 482 break; 483 case PDMNETWORKGSOTYPE_IPV4_IPV6_TCP: 484 pdmNetGsoUpdateIPv4Hdr(pbHdrs, pGso->offHdr1, cbPayload, 0, pGso->cbHdrs); 485 pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv6Hdr(pbHdrs, pgmNetGsoCalcIpv6Offset(pbHdrs, pGso->offHdr1), 486 cbPayload, pGso->cbHdrs, pGso->offHdr2, RTNETIPV4_PROT_TCP), 487 pbHdrs, pGso->offHdr2, pbPayload, cbPayload, 0, pGso->cbHdrs, true, fPayloadChecksum); 488 break; 489 case PDMNETWORKGSOTYPE_IPV4_IPV6_UDP: 490 pdmNetGsoUpdateIPv4Hdr(pbHdrs, pGso->offHdr1, cbPayload, 0, pGso->cbHdrs); 491 pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbHdrs, pgmNetGsoCalcIpv6Offset(pbHdrs, pGso->offHdr1), 492 cbPayload, pGso->cbHdrs, pGso->offHdr2, RTNETIPV4_PROT_UDP), 493 pbHdrs, pGso->offHdr2, pbPayload, cbPayload, pGso->cbHdrs, fPayloadChecksum); 494 break; 495 case PDMNETWORKGSOTYPE_INVALID: 496 case PDMNETWORKGSOTYPE_END: 497 /* no default! wnat gcc warnings. */ 498 break; 499 } 441 500 } 442 501 -
trunk/src/VBox/Devices/Network/SrvIntNetR0.cpp
r28120 r28156 1641 1641 if (fDst == INTNETTRUNKDIR_WIRE) 1642 1642 return !!(pThis->fGsoCapabilitesWire & fMask); 1643 Assert(fDst == (INTNETTRUNKDIR_WIRE ==INTNETTRUNKDIR_HOST));1643 Assert(fDst == (INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST)); 1644 1644 return !!(pThis->fGsoCapabilitesHost & pThis->fGsoCapabilitesWire & fMask); 1645 1645 } … … 3318 3318 for (unsigned iBit = PDMNETWORKGSOTYPE_END; iBit < 32; iBit++) 3319 3319 Assert(!(fGsoCapabilities & RT_BIT_32(iBit))); 3320 Assert( fDst & ~INTNETTRUNKDIR_VALID_MASK);3320 Assert(!(fDst & ~INTNETTRUNKDIR_VALID_MASK)); 3321 3321 Assert(fDst); 3322 3322 -
trunk/src/VBox/HostDrivers/Support/linux/Makefile
r26180 r28156 100 100 r0drv/linux/timer-r0drv-linux.o \ 101 101 r0drv/generic/semspinmutex-r0drv-generic.o \ 102 common/checksum/ipv4.o \ 103 common/checksum/ipv6.o \ 102 104 common/err/RTErrConvertFromErrno.o \ 103 105 common/err/RTErrConvertToErrno.o \ -
trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv
r26180 r28156 76 76 ${PATH_ROOT}/src/VBox/HostDrivers/Support/SUPDrvInternal.h=>SUPDrvInternal.h \ 77 77 ${PATH_ROOT}/src/VBox/Runtime/common/alloc/heapsimple.cpp=>alloc/heapsimple.c \ 78 ${PATH_ROOT}/src/VBox/Runtime/common/checksum/ipv4.cpp=>common/checksum/ipv4.c \ 79 ${PATH_ROOT}/src/VBox/Runtime/common/checksum/ipv6.cpp=>common/checksum/ipv6.c \ 78 80 ${PATH_ROOT}/src/VBox/Runtime/common/err/RTErrConvertFromErrno.cpp=>common/err/RTErrConvertFromErrno.c \ 79 81 ${PATH_ROOT}/src/VBox/Runtime/common/err/RTErrConvertToErrno.cpp=>common/err/RTErrConvertToErrno.c \ -
trunk/src/VBox/HostDrivers/VBoxNetFlt/linux/Makefile
r25097 r28156 70 70 SUPR0IdcClient.o \ 71 71 SUPR0IdcClientComponent.o \ 72 SUPR0IdcClient-linux.o \72 SUPR0IdcClient-linux.o 73 73 74 74 ifeq ($(BUILD_TARGET_ARCH),x86) -
trunk/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c
r28153 r28156 84 84 #endif 85 85 86 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)87 /** Indicates that the linux kernel may send us GSO frames. */88 # define VBOXNETFLT_WITH_GSO 189 #endif90 91 86 #ifndef NET_IP_ALIGN 92 87 # define NET_IP_ALIGN 2 … … 97 92 * linearize the socket buffer before creating the internal networking SG. */ 98 93 # define VBOXNETFLT_SG_SUPPORT 1 94 #endif 95 96 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) 97 /** Indicates that the linux kernel may send us GSO frames. */ 98 # define VBOXNETFLT_WITH_GSO 1 99 100 /** This enables or disables the transmitting of GSO frame from the internal 101 * network and to the host. */ 102 # define VBOXNETFLT_WITH_GSO_XMIT_HOST 1 103 104 # if 0 /** @todo This is currently disable because it causes performance loss of 5-10%. */ 105 /** This enables or disables the transmitting of GSO frame from the internal 106 * network and to the wire. */ 107 # define VBOXNETFLT_WITH_GSO_XMIT_WIRE 1 108 # endif 109 99 110 #endif 100 111 … … 292 303 * @param pThis The instance. 293 304 * @param pSG The (scatter/)gather list. 305 * @param fDstWire Set if the destination is the wire. 294 306 */ 295 307 static struct sk_buff *vboxNetFltLinuxSkBufFromSG(PVBOXNETFLTINS pThis, PINTNETSG pSG, bool fDstWire) … … 297 309 struct sk_buff *pPkt; 298 310 struct net_device *pDev; 311 unsigned fGsoType = 0; 299 312 300 313 if (pSG->cbTotal == 0) … … 304 317 } 305 318 319 /** @todo We should use fragments mapping the SG buffers with large packets. 320 * 256 bytes seems to be the a threshold used a lot for this. It 321 * requires some nasty work on the intnet side though... */ 306 322 /* 307 323 * Allocate a packet and copy over the data. 308 324 */ 309 325 pDev = (struct net_device *)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev); 310 pPkt = dev_alloc_skb(pSG->cbTotal + NET_IP_ALIGN); 311 if (RT_UNLIKELY(!pPkt)) 312 { 313 Log(("vboxNetFltLinuxSkBufFromSG: Failed to allocate sk_buff(%u).\n", pSG->cbTotal)); 314 pSG->pvUserData = NULL; 315 return NULL; 316 } 317 318 pPkt->dev = pDev; 319 320 /* Align IP header on 16-byte boundary: 2 + 14 (ethernet hdr size). */ 321 skb_reserve(pPkt, NET_IP_ALIGN); 322 323 /* Copy the segments. */ 324 skb_put(pPkt, pSG->cbTotal); 325 INTNETSgRead(pSG, pPkt->data); 326 327 /* Set protocol and packet_type fields. */ 326 #if 0 /* trying to figure out why submitting GSOs is so darn slow. */ 327 if ( pSG->GsoCtx.u8Type != PDMNETWORKGSOTYPE_INVALID 328 && pSG->cbTotal > 4096 329 && fDstWire 330 && pDev 331 && (pDev->features & NETIF_F_SG) 332 ) 333 { 334 uint32_t off = 0; 335 uint32_t cbLeft = pSG->cbTotal; 336 uint32_t iFrag = 0; 337 338 pPkt = dev_alloc_skb(pSG->GsoCtx.cbHdrs + NET_IP_ALIGN + 64); 339 if (RT_UNLIKELY(!pPkt)) 340 { 341 Log(("vboxNetFltLinuxSkBufFromSG: Failed to allocate sk_buff(%u).\n", pSG->cbTotal)); 342 pSG->pvUserData = NULL; 343 return NULL; 344 } 345 pPkt->dev = pDev; 346 pPkt->ip_summed = CHECKSUM_NONE; 347 348 /* Align IP header on 16-byte boundary: 2 + 14 (ethernet hdr size). */ 349 skb_reserve(pPkt, NET_IP_ALIGN); 350 351 /* Copy the headers. */ 352 skb_put(pPkt, pSG->GsoCtx.cbHdrs); 353 INTNETSgReadEx(pSG, off, pSG->GsoCtx.cbHdrs, pPkt->data); 354 off += pSG->GsoCtx.cbHdrs; 355 cbLeft -= off; 356 357 /* Copy the payload into fragments. */ 358 while (cbLeft) 359 { 360 void *pvPage; 361 uint32_t cbUsed = RT_MIN(cbLeft, PAGE_SIZE); 362 struct page *pPage = alloc_page(GFP_ATOMIC); 363 if (!pPage) 364 { 365 dev_kfree_skb(pPkt); 366 return NULL; 367 } 368 369 skb_fill_page_desc(pPkt, iFrag, pPage, 0, cbUsed); 370 371 pvPage = kmap(pPage); 372 INTNETSgReadEx(pSG, off, cbUsed, pvPage); 373 kunmap(pPage); 374 375 /* advance */ 376 iFrag += 1; 377 pPkt->len += cbUsed; 378 pPkt->data_len += cbUsed; 379 pPkt->truesize += cbUsed; 380 off += cbUsed; 381 cbLeft -= cbUsed; 382 } 383 } 384 else 385 #endif 386 { 387 pPkt = dev_alloc_skb(pSG->cbTotal + NET_IP_ALIGN); 388 if (RT_UNLIKELY(!pPkt)) 389 { 390 Log(("vboxNetFltLinuxSkBufFromSG: Failed to allocate sk_buff(%u).\n", pSG->cbTotal)); 391 pSG->pvUserData = NULL; 392 return NULL; 393 } 394 pPkt->dev = pDev; 395 pPkt->ip_summed = CHECKSUM_NONE; 396 397 /* Align IP header on 16-byte boundary: 2 + 14 (ethernet hdr size). */ 398 skb_reserve(pPkt, NET_IP_ALIGN); 399 400 /* Copy the segments. */ 401 skb_put(pPkt, pSG->cbTotal); 402 INTNETSgRead(pSG, pPkt->data); 403 } 404 405 #if defined(VBOXNETFLT_WITH_GSO_XMIT_WIRE) || defined(VBOXNETFLT_WITH_GSO_XMIT_HOST) 406 /* 407 * Setup GSO if used by this packet. 408 */ 409 switch ((PDMNETWORKGSOTYPE)pSG->GsoCtx.u8Type) 410 { 411 default: 412 AssertMsgFailed(("%u (%s)\n", pSG->GsoCtx.u8Type, PDMNetGsoTypeName((PDMNETWORKGSOTYPE)pSG->GsoCtx.u8Type) )); 413 /* fall thru */ 414 case PDMNETWORKGSOTYPE_INVALID: 415 fGsoType = 0; 416 break; 417 case PDMNETWORKGSOTYPE_IPV4_TCP: 418 fGsoType = SKB_GSO_TCPV4; 419 break; 420 case PDMNETWORKGSOTYPE_IPV4_UDP: 421 fGsoType = SKB_GSO_UDP; 422 break; 423 case PDMNETWORKGSOTYPE_IPV6_TCP: 424 fGsoType = SKB_GSO_TCPV6; 425 break; 426 } 427 if (fGsoType) 428 { 429 struct skb_shared_info *pShInfo = skb_shinfo(pPkt); 430 431 if (!fDstWire) 432 fGsoType |= SKB_GSO_DODGY; 433 pShInfo->gso_type = fGsoType; 434 pShInfo->gso_size = pSG->GsoCtx.cbMaxSeg; 435 pShInfo->gso_segs = PDMNetGsoCalcSegmentCount(&pSG->GsoCtx, pSG->cbTotal); 436 437 /** @todo figure out the checksum bit... We're checksumming way too much here 438 * I hope. */ 439 if (fDstWire) 440 { 441 /** @todo check skb_partial_csum_set status code. */ 442 if (fGsoType & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) 443 skb_partial_csum_set(pPkt, pSG->GsoCtx.offHdr2, RT_OFFSETOF(RTNETTCP, th_sum)); 444 else 445 skb_partial_csum_set(pPkt, pSG->GsoCtx.offHdr2, RT_OFFSETOF(RTNETUDP, uh_sum)); 446 } 447 else 448 { 449 pPkt->ip_summed = CHECKSUM_UNNECESSARY; 450 PDMNetGsoPrepForDirectUse(&pSG->GsoCtx, pPkt->data, pSG->cbTotal, false /*fPayloadChecksum*/); 451 } 452 } 453 #endif /* VBOXNETFLT_WITH_GSO_XMIT_WIRE || VBOXNETFLT_WITH_GSO_XMIT_HOST */ 454 455 /* 456 * Finish up the socket buffer. 457 */ 328 458 pPkt->protocol = eth_type_trans(pPkt, pDev); 329 pPkt->ip_summed = CHECKSUM_NONE;330 459 if (fDstWire) 331 460 { 332 461 VBOX_SKB_RESET_NETWORK_HDR(pPkt); 462 333 463 /* Restore ethernet header back. */ 334 skb_push(pPkt, ETH_HLEN); 464 skb_push(pPkt, ETH_HLEN); /** @todo VLAN: +4 if VLAN? */ 335 465 VBOX_SKB_RESET_MAC_HDR(pPkt); 336 466 } … … 557 687 } 558 688 559 #ifndef LOG_ENABLED 560 # define VBOXNETFLT_DUMP_PACKET(a, b, c, d) do {} while (0) 561 #else 689 #ifdef LOG_ENABLED 690 /** 691 * Logging helper. 692 */ 562 693 static void vboxNetFltDumpPacket(PINTNETSG pSG, bool fEgress, const char *pszWhere, int iIncrement) 563 694 { … … 583 714 Log3(("%.*Rhxd\n", pSG->aSegs[0].cb, pSG->aSegs[0].pv)); 584 715 } 585 #endif /* LOG_ENABLED */ 716 #else 717 # define vboxNetFltDumpPacket(a, b, c, d) do {} while (0) 718 #endif 586 719 587 720 #ifdef VBOXNETFLT_WITH_GSO … … 975 1108 976 1109 /** 977 * Internal worker for vboxNetFltOsInitInstance and vboxNetFltOsMaybeRediscovered. 1110 * Reports the GSO capabilites of the hardware NIC. 1111 * 1112 * @param pThis The net filter instance. The caller hold a 1113 * reference to this. 1114 */ 1115 static void vboxNetFltLinuxReportNicGsoCapabilities(PVBOXNETFLTINS pThis) 1116 { 1117 #ifdef VBOXNETFLT_WITH_GSO_XMIT_WIRE 1118 struct net_device *pDev; 1119 PINTNETTRUNKSWPORT pSwitchPort; 1120 unsigned int fFeatures; 1121 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; 1122 1123 RTSpinlockAcquire(pThis->hSpinlock, &Tmp); 1124 1125 pSwitchPort = pThis->pSwitchPort; /* this doesn't need to be here, but it doesn't harm. */ 1126 pDev = (struct net_device *)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev); 1127 if (pDev) 1128 fFeatures = pDev->features; 1129 else 1130 fFeatures = 0; 1131 1132 RTSpinlockRelease(pThis->hSpinlock, &Tmp); 1133 1134 if (pThis->pSwitchPort) 1135 { 1136 /* Set/update the GSO capabilities of the NIC. */ 1137 uint32_t fGsoCapabilites = 0; 1138 if (fFeatures & NETIF_F_TSO) 1139 fGsoCapabilites |= RT_BIT_32(PDMNETWORKGSOTYPE_IPV4_TCP); 1140 if (fFeatures & NETIF_F_TSO6) 1141 fGsoCapabilites |= RT_BIT_32(PDMNETWORKGSOTYPE_IPV6_TCP); 1142 # if 0 /** @todo GSO: Test UDP offloading (UFO) on linux. */ 1143 if (fFeatures & NETIF_F_UFO) 1144 fGsoCapabilites |= RT_BIT_32(PDMNETWORKGSOTYPE_IPV4_UDP); 1145 if (fFeatures & NETIF_F_UFO) 1146 fGsoCapabilites |= RT_BIT_32(PDMNETWORKGSOTYPE_IPV6_UDP); 1147 # endif 1148 pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, fGsoCapabilites, INTNETTRUNKDIR_WIRE); 1149 } 1150 #endif /* VBOXNETFLT_WITH_GSO_XMIT_WIRE */ 1151 } 1152 1153 /** 1154 * Internal worker for vboxNetFltLinuxNotifierCallback. 978 1155 * 979 1156 * @returns VBox status code. … … 984 1161 static int vboxNetFltLinuxAttachToInterface(PVBOXNETFLTINS pThis, struct net_device *pDev) 985 1162 { 986 struct packet_type *pt;987 1163 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; 988 989 1164 LogFlow(("vboxNetFltLinuxAttachToInterface: pThis=%p (%s)\n", pThis, pThis->szName)); 990 1165 991 if (!pDev) 992 { 993 Log(("VBoxNetFlt: failed to find device '%s'\n", pThis->szName)); 994 return VERR_INTNET_FLT_IF_NOT_FOUND; 995 } 996 1166 /* 1167 * Retain and store the device. 1168 */ 997 1169 dev_hold(pDev); 1170 998 1171 RTSpinlockAcquire(pThis->hSpinlock, &Tmp); 999 1172 ASMAtomicUoWritePtr((void * volatile *)&pThis->u.s.pDev, pDev); … … 1002 1175 Log(("vboxNetFltLinuxAttachToInterface: Device %p(%s) retained. ref=%d\n", pDev, pDev->name, atomic_read(&pDev->refcnt))); 1003 1176 Log(("vboxNetFltLinuxAttachToInterface: Got pDev=%p pThis=%p pThis->u.s.pDev=%p\n", pDev, pThis, ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev))); 1004 /* 1005 * Get the mac address while we still have a valid ifnet reference. 1006 */ 1177 1178 /* Get the mac address while we still have a valid net_device reference. */ 1007 1179 memcpy(&pThis->u.s.Mac, pDev->dev_addr, sizeof(pThis->u.s.Mac)); 1008 1180 1009 pt = &pThis->u.s.PacketType; 1010 pt->type = __constant_htons(ETH_P_ALL); 1011 pt->dev = pDev; 1012 pt->func = vboxNetFltLinuxPacketHandler; 1013 dev_add_pack(pt); 1181 /* 1182 * Install a packet filter for this device with a protocol wildcard (ETH_P_ALL). 1183 */ 1184 pThis->u.s.PacketType.type = __constant_htons(ETH_P_ALL); 1185 pThis->u.s.PacketType.dev = pDev; 1186 pThis->u.s.PacketType.func = vboxNetFltLinuxPacketHandler; 1187 dev_add_pack(&pThis->u.s.PacketType); 1188 1189 /* 1190 * Set indicators that require the spinlock. Be abit paranoid about racing 1191 * the device notification handle. 1192 */ 1014 1193 RTSpinlockAcquire(pThis->hSpinlock, &Tmp); 1015 1194 pDev = (struct net_device *)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev); … … 1023 1202 Log(("vboxNetFltLinuxAttachToInterface: this=%p: Packet handler installed.\n", pThis)); 1024 1203 1025 /* Release the interface on failure. */ 1026 if (pDev) 1204 /* 1205 * If the above succeeded report GSO capabilites, if not undo and 1206 * release the device. 1207 */ 1208 if (!pDev) 1209 vboxNetFltLinuxReportNicGsoCapabilities(pThis); 1210 else 1027 1211 { 1028 1212 RTSpinlockAcquire(pThis->hSpinlock, &Tmp); … … 1088 1272 } 1089 1273 1090 static int vboxNetFltLinuxNotifierCallback(struct notifier_block *self, unsigned long ulEventType, void *ptr) 1091 1092 { 1093 int rc = NOTIFY_OK; 1094 #ifdef DEBUG 1095 char *pszEvent = "<unknown>"; 1096 #endif 1097 struct net_device *pDev = (struct net_device *)ptr; 1098 PVBOXNETFLTINS pThis = VBOX_FLT_NB_TO_INST(self); 1099 1100 #ifdef DEBUG 1274 #ifdef LOG_ENABLED 1275 /** Stringify the NETDEV_XXX constants. */ 1276 static const char *vboxNetFltLinuxGetNetDevEventName(unsigned long ulEventType) 1277 { 1278 const char *pszEvent = "NETDRV_<unknown>"; 1101 1279 switch (ulEventType) 1102 1280 { … … 1111 1289 case NETDEV_CHANGEADDR: pszEvent = "NETDEV_CHANGEADDR"; break; 1112 1290 case NETDEV_GOING_DOWN: pszEvent = "NETDEV_GOING_DOWN"; break; 1113 } 1291 # ifdef NETDEV_FEAT_CHANGE 1292 case NETDEV_FEAT_CHANGE: pszEvent = "NETDEV_FEAT_CHANGE"; break; 1293 # endif 1294 } 1295 return pszEvent; 1296 } 1297 #endif /* LOG_ENABLED */ 1298 1299 /** 1300 * Callback for listening to netdevice events. 1301 * 1302 * This works the rediscovery, clean up on unregistration, promiscuity on 1303 * up/down, and GSO feature changes from ethtool. 1304 * 1305 * @returns NOTIFY_OK 1306 * @param self Pointer to our notifier registration block. 1307 * @param ulEventType The event. 1308 * @param ptr Event specific, but it is usually the device it 1309 * relates to. 1310 */ 1311 static int vboxNetFltLinuxNotifierCallback(struct notifier_block *self, unsigned long ulEventType, void *ptr) 1312 1313 { 1314 PVBOXNETFLTINS pThis = VBOX_FLT_NB_TO_INST(self); 1315 struct net_device *pDev = (struct net_device *)ptr; 1316 int rc = NOTIFY_OK; 1317 1114 1318 Log(("VBoxNetFlt: got event %s(0x%lx) on %s, pDev=%p pThis=%p pThis->u.s.pDev=%p\n", 1115 pszEvent, ulEventType, pDev->name, pDev, pThis, ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev)));1116 #endif 1117 if (ulEventType == NETDEV_REGISTER&& !strcmp(pDev->name, pThis->szName))1319 vboxNetFltLinuxGetNetDevEventName(ulEventType), ulEventType, pDev->name, pDev, pThis, ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev))); 1320 if ( ulEventType == NETDEV_REGISTER 1321 && !strcmp(pDev->name, pThis->szName)) 1118 1322 { 1119 1323 vboxNetFltLinuxAttachToInterface(pThis, pDev); … … 1122 1326 { 1123 1327 pDev = (struct net_device *)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pDev); 1124 if (pDev != ptr) 1125 return NOTIFY_OK; 1126 rc = NOTIFY_OK; 1127 switch (ulEventType) 1128 { 1129 case NETDEV_UNREGISTER: 1130 rc = vboxNetFltLinuxUnregisterDevice(pThis, pDev); 1131 break; 1132 case NETDEV_UP: 1133 rc = vboxNetFltLinuxDeviceIsUp(pThis, pDev); 1134 break; 1135 case NETDEV_GOING_DOWN: 1136 rc = vboxNetFltLinuxDeviceGoingDown(pThis, pDev); 1137 break; 1138 case NETDEV_CHANGENAME: 1139 break; 1328 if (pDev == ptr) 1329 { 1330 switch (ulEventType) 1331 { 1332 case NETDEV_UNREGISTER: 1333 rc = vboxNetFltLinuxUnregisterDevice(pThis, pDev); 1334 break; 1335 case NETDEV_UP: 1336 rc = vboxNetFltLinuxDeviceIsUp(pThis, pDev); 1337 break; 1338 case NETDEV_GOING_DOWN: 1339 rc = vboxNetFltLinuxDeviceGoingDown(pThis, pDev); 1340 break; 1341 case NETDEV_CHANGENAME: 1342 break; 1343 #ifdef NETDEV_FEAT_CHANGE 1344 case NETDEV_FEAT_CHANGE: 1345 vboxNetFltLinuxReportNicGsoCapabilities(pThis); 1346 break; 1347 #endif 1348 } 1140 1349 } 1141 1350 } … … 1300 1509 int vboxNetFltOsConnectIt(PVBOXNETFLTINS pThis) 1301 1510 { 1302 /* Nothing to do here. */ 1511 /* 1512 * Report the GSO capabilities of the host and device (if connected). 1513 */ 1514 #if defined(VBOXNETFLT_WITH_GSO_XMIT_HOST) 1515 pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 1516 0 1517 | RT_BIT_32(PDMNETWORKGSOTYPE_IPV4_TCP) 1518 | RT_BIT_32(PDMNETWORKGSOTYPE_IPV6_TCP) 1519 # if 0 /** @todo GSO: Test UDP offloading (UFO) on linux. */ 1520 | RT_BIT_32(PDMNETWORKGSOTYPE_IPV4_UDP) 1521 | RT_BIT_32(PDMNETWORKGSOTYPE_IPV6_UDP) 1522 # endif 1523 , INTNETTRUNKDIR_HOST); 1524 1525 #endif 1526 vboxNetFltLinuxReportNicGsoCapabilities(pThis); 1527 1303 1528 return VINF_SUCCESS; 1304 1529 } -
trunk/src/VBox/NetworkServices/NetLib/VBoxNetUDP.cpp
r28025 r28156 127 127 */ 128 128 if (pGso) 129 PDMNetGsoPrepForDirectUse(pGso, (void *)pvFrame, cbFrame, false /*f HeaderChecskum*/, false /*fPayloadChecksum*/);129 PDMNetGsoPrepForDirectUse(pGso, (void *)pvFrame, cbFrame, false /*fPayloadChecksum*/); 130 130 131 131 /*
Note:
See TracChangeset
for help on using the changeset viewer.