Changeset 107826 in vbox for trunk/src/VBox/Devices/Network
- Timestamp:
- Jan 16, 2025 4:38:32 PM (4 months ago)
- svn:sync-xref-src-repo-rev:
- 167002
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DrvNATlibslirp.cpp
r107821 r107826 219 219 PDMNETWORKLINKSTATE enmLinkStateWant; 220 220 221 #ifndef RT_OS_WINDOWS 221 #ifdef RT_OS_WINDOWS 222 /** Wakeup socket pair for NAT thread. 223 * Entry #0 is write, entry #1 is read. */ 224 SOCKET ahWakeupSockPair[2]; 225 #else 222 226 /** The write end of the control pipe. */ 223 227 RTPIPE hPipeWrite; 224 228 /** The read end of the control pipe. */ 225 229 RTPIPE hPipeRead; 226 #else227 /* wakeup socket pair for NAT thread */228 SOCKET pWakeupSockPair[2];229 230 #endif 230 231 /* count of bytes sent to notify NAT thread */ … … 237 238 PPDMTHREAD pRecvThread; 238 239 /** event to wakeup the guest receive thread */ 239 RTSEMEVENT EventRecv;240 RTSEMEVENT hEventRecv; 240 241 /** Receive Req queue (deliver packets to the guest) */ 241 242 RTREQQUEUE hRecvReqQueue; … … 293 294 RTReqQueueProcess(pThis->hRecvReqQueue, 0); 294 295 if (ASMAtomicReadU32(&pThis->cPkts) == 0) 295 RTSemEventWait(pThis-> EventRecv, RT_INDEFINITE_WAIT);296 RTSemEventWait(pThis->hEventRecv, RT_INDEFINITE_WAIT); 296 297 } 297 298 return VINF_SUCCESS; … … 305 306 RT_NOREF(pThread); 306 307 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT); 307 int rc; 308 rc = RTSemEventSignal(pThis->EventRecv); 308 int rc = RTSemEventSignal(pThis->hEventRecv); 309 309 310 310 STAM_COUNTER_INC(&pThis->StatNATRecvWakeups); … … 603 603 { 604 604 RT_NOREF(pszWho); 605 int rc = 0; 606 #ifndef RT_OS_WINDOWS 605 #ifdef RT_OS_WINDOWS 606 int cbWritten = send(pThis->ahWakeupSockPair[0], "", 1, NULL); 607 if (RT_LIKELY(cbWritten != SOCKET_ERROR)) 608 { 609 /* Count how many bites we send down the socket */ 610 ASMAtomicIncU64(&pThis->cbWakeupNotifs); 611 } 612 else 613 Log4(("Notify NAT Thread Error %d\n", WSAGetLastError())); 614 #else 607 615 /* kick poll() */ 608 616 size_t cbIgnored; 609 rc = RTPipeWrite(pThis->hPipeWrite, "", 1, &cbIgnored); 617 int rc = RTPipeWrite(pThis->hPipeWrite, "", 1, &cbIgnored); 618 AssertRC(rc); 610 619 if (RT_SUCCESS(rc)) 611 620 { … … 613 622 ASMAtomicIncU64(&pThis->cbWakeupNotifs); 614 623 } 615 #else616 int cbWritten = send(pThis->pWakeupSockPair[0], "", 1, NULL);617 if (cbWritten == SOCKET_ERROR)618 {619 Log4(("Notify NAT Thread Error %d\n", WSAGetLastError()));620 }621 else622 {623 /* Count how many bites we send down the socket */624 ASMAtomicIncU64(&pThis->cbWakeupNotifs);625 }626 624 #endif 627 AssertRC(rc);628 625 } 629 626 … … 722 719 { 723 720 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT); 721 722 /* The first polling entry is for the control/wakeup pipe. */ 724 723 #ifdef RT_OS_WINDOWS 725 drvNAT_AddPollCb(pThis-> pWakeupSockPair[1], SLIRP_POLL_IN | SLIRP_POLL_HUP, pThis);726 pThis->pNATState->polls[0].fd = pThis-> pWakeupSockPair[1];724 drvNAT_AddPollCb(pThis->ahWakeupSockPair[1], SLIRP_POLL_IN | SLIRP_POLL_HUP, pThis); 725 pThis->pNATState->polls[0].fd = pThis->ahWakeupSockPair[1]; 727 726 #else 728 727 unsigned int cPollNegRet = 0; … … 786 785 787 786 Log4(("%s: poll\n", __FUNCTION__)); 788 slirp_pollfds_poll(pThis->pNATState->pSlirp, cChangedFDs < 0, drvNAT_GetREventsCb /* SlirpGetREventsCb */, pThis /* opaque */); 789 787 slirp_pollfds_poll(pThis->pNATState->pSlirp, cChangedFDs < 0, drvNAT_GetREventsCb, pThis /* opaque */); 788 789 /* 790 * Drain the control pipe if necessary. 791 * 792 * Note! drvNATSend decoupled so we don't know how many times 793 * device's thread sends before we've entered multiplex, 794 * so to avoid false alarm drain pipe here to the very end 795 */ 796 /** @todo revise the above note. */ 790 797 if (pThis->pNATState->polls[0].revents & (POLLRDNORM|POLLPRI|POLLRDBAND)) /* POLLPRI won't be seen with WSAPoll. */ 791 798 { 792 /* drain the pipe793 *794 * Note! drvNATSend decoupled so we don't know how many times795 * device's thread sends before we've entered multiplex,796 * so to avoid false alarm drain pipe here to the very end797 */798 799 char ch[1024]; 799 800 size_t cbRead; 800 801 uint64_t cbWakeupNotifs = ASMAtomicReadU64(&pThis->cbWakeupNotifs); 801 802 #ifdef RT_OS_WINDOWS 802 cbRead = recv(pThis-> pWakeupSockPair[1], &ch[0], RT_MIN(cbWakeupNotifs, 1024), NULL);803 cbRead = recv(pThis->ahWakeupSockPair[1], &ch[0], RT_MIN(cbWakeupNotifs, 1024), NULL); 803 804 #else 804 805 RTPipeRead(pThis->hPipeRead, &ch[0], RT_MIN(cbWakeupNotifs, 1024), &cbRead); … … 1195 1196 * Libslirp Callbacks 1196 1197 */ 1198 /** @todo r=bird: None of these require DECLCALLBACK as such, since the libslirp 1199 * structure they're used with doesn't use DECLCALLBACKMEMBER or similar. */ 1197 1200 /** 1198 1201 * Callback called by libslirp to send packet into guest. 1199 1202 * 1200 * @param p BufPointer to packet buffer.1203 * @param pvBuf Pointer to packet buffer. 1201 1204 * @param cb Size of packet. 1202 * @param opaquePointer to NAT State context.1205 * @param pvUser Pointer to NAT State context. 1203 1206 * 1204 1207 * @returns Size of packet received or -1 on error. … … 1206 1209 * @thread ? 1207 1210 */ 1208 static DECLCALLBACK(ssize_t) drvNAT_SendPacketCb(const void *pBuf, ssize_t cb, void *opaque /* PDRVNAT */) 1209 { 1210 char *pNewBuf = (char *)RTMemAlloc(cb); 1211 if (pNewBuf == NULL) 1212 return -1; 1213 1214 memcpy(pNewBuf, pBuf, cb); 1215 1216 PDRVNAT pThis = (PDRVNAT)opaque; 1211 static DECLCALLBACK(ssize_t) drvNAT_SendPacketCb(const void *pvBuf, ssize_t cb, void *pvUser /* PDRVNAT */) 1212 { 1213 PDRVNAT const pThis = (PDRVNAT)pvUser; 1217 1214 Assert(pThis); 1218 1215 1219 LogFlow(("slirp_output BEGIN %p %d\n", pNewBuf, cb)); 1220 Log6(("slirp_output: pNewBuf=%p cb=%#x (pThis=%p)\n" 1221 "%.*Rhxd\n", pNewBuf, cb, pThis, cb, pNewBuf)); 1216 void * const pvNewBuf = RTMemDup(pvBuf, cb); 1217 AssertReturn(pvNewBuf, -1); 1218 1219 LogFlow(("slirp_output BEGIN %p %d\n", pvNewBuf, cb)); 1220 Log6(("slirp_output: pvNewBuf=%p cb=%#x (pThis=%p)\n" 1221 "%.*Rhxd\n", pvNewBuf, cb, pThis, cb, pvNewBuf)); 1222 1222 1223 1223 /* don't queue new requests when the NAT thread is about to stop */ … … 1227 1227 ASMAtomicIncU32(&pThis->cPkts); 1228 1228 int rc = RTReqQueueCallEx(pThis->hRecvReqQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT, 1229 (PFNRT)drvNATRecvWorker, 3, pThis, p NewBuf, cb);1230 AssertRC (rc);1229 (PFNRT)drvNATRecvWorker, 3, pThis, pvNewBuf, cb); 1230 AssertRCStmt(rc, RTMemFree(pvNewBuf)); 1231 1231 drvNATRecvWakeup(pThis->pDrvIns, pThis->pRecvThread); 1232 1233 /** @todo r=bird: explain why we wake up the other thread here? */ 1232 1234 drvNATNotifyNATThread(pThis, "drvNAT_SendPacketCb"); 1235 1233 1236 STAM_COUNTER_INC(&pThis->StatQueuePktSent); 1234 1237 LogFlowFuncLeave(); … … 1237 1240 1238 1241 /** 1239 * Callback called by libslirp on an error from a guest.1242 * Callback called by libslirp when the guest does something wrong. 1240 1243 * 1241 1244 * @param pMsg Error message string. 1242 * @param opaquePointer to NAT State context.1245 * @param pvUser Pointer to NAT State context. 1243 1246 * 1244 1247 * @thread ? 1245 1248 */ 1246 static DECLCALLBACK(void) drvNAT_GuestErrorCb(const char *pMsg, void *opaque) 1247 { 1248 PDRVNAT pThis = (PDRVNAT)opaque; 1249 Assert(pThis); 1250 1251 PDMDRV_SET_ERROR(pThis->pDrvIns, VERR_PDM_UNKNOWN_DRVREG_VERSION, 1252 N_("Unknown error: ")); 1253 LogRel((pMsg)); 1249 static DECLCALLBACK(void) drvNAT_GuestErrorCb(const char *pszMsg, void *pvUser) 1250 { 1251 /* Note! This is _just_ libslirp complaining about odd guest behaviour. 1252 It is nothing we need to create popup messages in the GUI about. */ 1253 LogRelMax(250, ("NAT Guest Error: %s\n", pszMsg)); 1254 RT_NOREF(pvUser); 1254 1255 } 1255 1256 … … 1257 1258 * Callback called by libslirp to get the current timestamp in nanoseconds. 1258 1259 * 1259 * @param opaquePointer to NAT State context.1260 * @param pvUser Pointer to NAT State context. 1260 1261 * 1261 1262 * @returns 64-bit signed integer representing time in nanoseconds. 1262 1263 */ 1263 static DECLCALLBACK(int64_t) drvNAT_ClockGetNsCb(void *opaque) 1264 { 1265 PDRVNAT pThis = (PDRVNAT)opaque; 1266 Assert(pThis); 1267 1268 RT_NOREF(pThis); 1269 1264 static DECLCALLBACK(int64_t) drvNAT_ClockGetNsCb(void *pvUser) 1265 { 1266 RT_NOREF(pvUser); 1270 1267 return (int64_t)RTTimeNanoTS(); 1271 1268 } … … 1451 1448 if (pNATState) 1452 1449 { 1453 slirp_cleanup(pNATState->pSlirp); 1450 if (pNATState->pSlirp) 1451 { 1452 slirp_cleanup(pNATState->pSlirp); 1453 pNATState->pSlirp = NULL; 1454 } 1454 1455 1455 1456 #ifdef VBOX_WITH_STATISTICS … … 1471 1472 pThis->hRecvReqQueue = NIL_RTREQQUEUE; 1472 1473 1473 RTSemEventDestroy(pThis-> EventRecv);1474 pThis-> EventRecv = NIL_RTSEMEVENT;1474 RTSemEventDestroy(pThis->hEventRecv); 1475 pThis->hEventRecv = NIL_RTSEMEVENT; 1475 1476 1476 1477 if (RTCritSectIsInitialized(&pThis->DevAccessLock)) … … 1483 1484 RTPipeClose(pThis->hPipeRead); 1484 1485 RTPipeClose(pThis->hPipeWrite); 1486 pThis->hPipeRead = NIL_RTPIPE; 1487 pThis->hPipeWrite = NIL_RTPIPE; 1485 1488 #endif 1486 1489 } … … 1501 1504 */ 1502 1505 pThis->pDrvIns = pDrvIns; 1506 pThis->hSlirpReqQueue = NIL_RTREQQUEUE; 1507 pThis->hEventRecv = NIL_RTSEMEVENT; 1508 pThis->hRecvReqQueue = NIL_RTREQQUEUE; 1509 #ifndef RT_OS_WINDOWS 1510 pThis->hPipeRead = NIL_RTPIPE; 1511 pThis->hPipeWrite = NIL_RTPIPE; 1512 #endif 1503 1513 1504 1514 SlirpState * const pNATState = (SlirpState *)RTMemAllocZ(sizeof(*pNATState)); … … 1511 1521 AssertReturn(pNATState->polls, VERR_NO_MEMORY); 1512 1522 pNATState->uPollCap = 64; 1513 1514 pThis->hSlirpReqQueue = NIL_RTREQQUEUE;1515 pThis->EventRecv = NIL_RTSEMEVENT;1516 1523 1517 1524 /* IBase */ … … 1556 1563 , "PortForwarding"); 1557 1564 1558 LogRel((" These CFGM parameters are currently not supported when using NAT:\n"1559 "DNSProxy\n"1560 "UseHostResolver\n"1561 "AliasMode\n"1562 "SockRcv\n"1563 "SockSnd\n"1564 "TcpRcv\n"1565 "TcpSnd\n"1566 "ICMPCacheLimit\n"1567 "HostResolverMappings\n"1568 ));1565 LogRel(("NAT: These CFGM parameters are currently not supported when using NAT:\n" 1566 " DNSProxy\n" 1567 " UseHostResolver\n" 1568 " AliasMode\n" 1569 " SockRcv\n" 1570 " SockSnd\n" 1571 " TcpRcv\n" 1572 " TcpSnd\n" 1573 " ICMPCacheLimit\n" 1574 " HostResolverMappings\n" 1575 )); 1569 1576 1570 1577 /* … … 1572 1579 */ 1573 1580 int rc; 1581 /** @todo clean up the macros used here. S32 != int. Use defaults. ++ */ 1574 1582 1575 1583 bool fPassDomain = true; … … 1594 1602 int i32SoMaxConn = 10; 1595 1603 GET_S32(rc, pDrvIns, pCfg, "SoMaxConnection", i32SoMaxConn); 1604 1596 1605 /* 1597 1606 * Query the network port interface. … … 1600 1609 if (!pThis->pIAboveNet) 1601 1610 return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE, 1602 N_("Configuration error: the above device/driver didn't " 1603 "export the network port interface")); 1611 N_("Configuration error: the above device/driver didn't export the network port interface")); 1604 1612 pThis->pIAboveConfig = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMINETWORKCONFIG); 1605 1613 if (!pThis->pIAboveConfig) 1606 1614 return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE, 1607 N_("Configuration error: the above device/driver didn't " 1608 "export the network config interface")); 1615 N_("Configuration error: the above device/driver didn't export the network config interface")); 1609 1616 1610 1617 /* Generate a network address for this network card. */ … … 1615 1622 pDrvIns->iInstance); 1616 1623 1617 RTNETADDRIPV4 Network, Netmask , Nettemp;1624 RTNETADDRIPV4 Network, Netmask; 1618 1625 rc = RTCidrStrToIPv4(szNetwork, &Network, &Netmask); 1619 1626 if (RT_FAILURE(rc)) … … 1622 1629 pDrvIns->iInstance, szNetwork); 1623 1630 1624 /* Construct Libslirp Config and Initialzie Slirp */ 1625 1631 /* 1632 * Construct Libslirp Config. 1633 */ 1626 1634 LogFlow(("Here is what is coming out of the vbox config (NAT#%d):\n" 1627 1635 " Network: %RTnaipv4\n" … … 1629 1637 pDrvIns->iInstance, RT_H2BE_U32(Network.u), RT_H2BE_U32(Netmask.u))); 1630 1638 1639 /* IPv4: */ 1631 1640 struct in_addr vnetwork = RTNetIPv4AddrHEToInAddr(&Network); 1632 1641 struct in_addr vnetmask = RTNetIPv4AddrHEToInAddr(&Netmask); 1633 Nettemp = Network; Nettemp.u |= 2; /* Usually 10.0.2.2 */ 1634 struct in_addr vhost = RTNetIPv4AddrHEToInAddr(&Nettemp); 1635 Nettemp = Network; Nettemp.u |= 15; /* Usually 10.0.2.15 */ 1636 struct in_addr vdhcp_start = RTNetIPv4AddrHEToInAddr(&Nettemp); 1637 Nettemp = Network; Nettemp.u |= 3; /* Usually 10.0.2.3 */ 1638 struct in_addr vnameserver = RTNetIPv4AddrHEToInAddr(&Nettemp); 1642 1643 RTNETADDRIPV4 NetTemp = Network; 1644 NetTemp.u |= 2; /* Usually 10.0.2.2 */ 1645 struct in_addr vhost = RTNetIPv4AddrHEToInAddr(&NetTemp); 1646 1647 NetTemp = Network; 1648 NetTemp.u |= 15; /* Usually 10.0.2.15 */ 1649 struct in_addr vdhcp_start = RTNetIPv4AddrHEToInAddr(&NetTemp); 1650 1651 NetTemp = Network; 1652 NetTemp.u |= 3; /* Usually 10.0.2.3 */ 1653 struct in_addr vnameserver = RTNetIPv4AddrHEToInAddr(&NetTemp); 1639 1654 1640 1655 SlirpConfig slirpCfg = { 0 }; … … 1649 1664 slirpCfg.in6_enabled = true; 1650 1665 1651 /* 1652 * Use the same prefix as the NAT Network default: 1653 * [fd17:625c:f037:XXXX::/64] - RFC 4193 (ULA) Locally Assigned 1654 * Global ID where XXXX, 16 bit Subnet ID, are two bytes from the 1655 * middle of the IPv4 address, e.g. :0002: for 10.0.2.1. 1656 */ 1657 1666 /* IPv6: Use the same prefix as the NAT Network default: 1667 [fd17:625c:f037:XXXX::/64] - RFC 4193 (ULA) Locally Assigned 1668 Global ID where XXXX, 16 bit Subnet ID, are two bytes from the 1669 middle of the IPv4 address, e.g. :0002: for 10.0.2.1. */ 1658 1670 inet_pton(AF_INET6, "fd17:625c:f037:0::", &slirpCfg.vprefix_addr6); 1659 1671 inet_pton(AF_INET6, "fd17:625c:f037:0::2", &slirpCfg.vhost6); … … 1683 1695 slirpCfg.iSoMaxConn = i32SoMaxConn; 1684 1696 1685 slirpCallbacks.send_packet = &drvNAT_SendPacketCb;1686 slirpCallbacks.guest_error = &drvNAT_GuestErrorCb;1687 slirpCallbacks.clock_get_ns = &drvNAT_ClockGetNsCb;1688 slirpCallbacks.timer_new = &drvNAT_TimerNewCb;1689 slirpCallbacks.timer_free = &drvNAT_TimerFreeCb;1690 slirpCallbacks.timer_mod = &drvNAT_TimerModCb;1691 slirpCallbacks.register_poll_fd = &drvNAT_RegisterPoll;1692 slirpCallbacks.unregister_poll_fd = &drvNAT_UnregisterPoll;1693 slirpCallbacks.notify = &drvNAT_NotifyCb;1697 slirpCallbacks.send_packet = drvNAT_SendPacketCb; 1698 slirpCallbacks.guest_error = drvNAT_GuestErrorCb; 1699 slirpCallbacks.clock_get_ns = drvNAT_ClockGetNsCb; 1700 slirpCallbacks.timer_new = drvNAT_TimerNewCb; 1701 slirpCallbacks.timer_free = drvNAT_TimerFreeCb; 1702 slirpCallbacks.timer_mod = drvNAT_TimerModCb; 1703 slirpCallbacks.register_poll_fd = drvNAT_RegisterPoll; 1704 slirpCallbacks.unregister_poll_fd = drvNAT_UnregisterPoll; 1705 slirpCallbacks.notify = drvNAT_NotifyCb; 1694 1706 slirpCallbacks.init_completed = NULL; 1695 1707 slirpCallbacks.timer_new_opaque = NULL; 1696 1708 1697 Slirp *pSlirp = slirp_new(/* cfg */ &slirpCfg, /* callbacks */ &slirpCallbacks, /* opaque */ pThis); 1698 1699 if (pSlirp == NULL) 1700 return VERR_INVALID_POINTER; 1701 1702 pThis->pNATState->pSlirp = pSlirp; 1709 /* 1710 * Initialize Slirp 1711 */ 1712 Slirp * const pSlirp = slirp_new(/* cfg */ &slirpCfg, /* callbacks */ &slirpCallbacks, /* opaque */ pThis); 1713 if (!pSlirp) 1714 return PDMDRV_SET_ERROR(pDrvIns, VERR_INTERNAL_ERROR_4, 1715 N_("Configuration error: libslirp failed to create new instance - probably misconfiguration")); 1716 1717 pNATState->pSlirp = pSlirp; 1703 1718 1704 1719 rc = drvNATConstructRedir(pDrvIns->iInstance, pThis, pCfg, &Network); … … 1718 1733 AssertRCReturn(rc, rc); 1719 1734 1720 rc = RTSemEventCreate(&pThis-> EventRecv);1735 rc = RTSemEventCreate(&pThis->hEventRecv); 1721 1736 AssertRCReturn(rc, rc); 1722 1737 … … 1737 1752 #endif 1738 1753 1739 #ifndef RT_OS_WINDOWS 1740 // Create the control pipe. 1741 rc = RTPipeCreate(&pThis->hPipeRead, &pThis->hPipeWrite, 0 /*fFlags*/); 1754 #ifdef RT_OS_WINDOWS 1755 /* Create the wakeup socket pair (idx=0 is write, idx=1 is read). */ 1756 pThis->ahWakeupSockPair[0] = INVALID_SOCKET; 1757 pThis->ahWakeupSockPair[1] = INVALID_SOCKET; 1758 rc = RTWinSocketPair(AF_INET, SOCK_DGRAM, 0, pThis->ahWakeupSockPair); 1742 1759 AssertRCReturn(rc, rc); 1743 1760 #else 1744 // Create the wakeup socket pair. 1745 pThis->pWakeupSockPair[0] = NULL; 1746 pThis->pWakeupSockPair[1] = NULL; 1747 1748 /* idx=0 is write, idx=1 is read */ 1749 rc = RTWinSocketPair(AF_INET, SOCK_DGRAM, 0, pThis->pWakeupSockPair); 1761 /* Create the control pipe. */ 1762 rc = RTPipeCreate(&pThis->hPipeRead, &pThis->hPipeWrite, 0 /*fFlags*/); 1750 1763 AssertRCReturn(rc, rc); 1751 1764 #endif
Note:
See TracChangeset
for help on using the changeset viewer.