VirtualBox

Changeset 107826 in vbox for trunk/src/VBox/Devices/Network


Ignore:
Timestamp:
Jan 16, 2025 4:38:32 PM (4 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
167002
Message:

DrvNAT-libslirp: Some cleanups. bugref:10268

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/DrvNATlibslirp.cpp

    r107821 r107826  
    219219    PDMNETWORKLINKSTATE     enmLinkStateWant;
    220220
    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
    222226    /** The write end of the control pipe. */
    223227    RTPIPE                  hPipeWrite;
    224228    /** The read end of the control pipe. */
    225229    RTPIPE                  hPipeRead;
    226 #else
    227     /* wakeup socket pair for NAT thread */
    228     SOCKET                  pWakeupSockPair[2];
    229230#endif
    230231    /* count of bytes sent to notify NAT thread */
     
    237238    PPDMTHREAD              pRecvThread;
    238239    /** event to wakeup the guest receive thread */
    239     RTSEMEVENT              EventRecv;
     240    RTSEMEVENT              hEventRecv;
    240241    /** Receive Req queue (deliver packets to the guest) */
    241242    RTREQQUEUE              hRecvReqQueue;
     
    293294        RTReqQueueProcess(pThis->hRecvReqQueue, 0);
    294295        if (ASMAtomicReadU32(&pThis->cPkts) == 0)
    295             RTSemEventWait(pThis->EventRecv, RT_INDEFINITE_WAIT);
     296            RTSemEventWait(pThis->hEventRecv, RT_INDEFINITE_WAIT);
    296297    }
    297298    return VINF_SUCCESS;
     
    305306    RT_NOREF(pThread);
    306307    PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
    307     int rc;
    308     rc = RTSemEventSignal(pThis->EventRecv);
     308    int rc = RTSemEventSignal(pThis->hEventRecv);
    309309
    310310    STAM_COUNTER_INC(&pThis->StatNATRecvWakeups);
     
    603603{
    604604    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
    607615    /* kick poll() */
    608616    size_t cbIgnored;
    609     rc = RTPipeWrite(pThis->hPipeWrite, "", 1, &cbIgnored);
     617    int rc = RTPipeWrite(pThis->hPipeWrite, "", 1, &cbIgnored);
     618    AssertRC(rc);
    610619    if (RT_SUCCESS(rc))
    611620    {
     
    613622        ASMAtomicIncU64(&pThis->cbWakeupNotifs);
    614623    }
    615 #else
    616     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     else
    622     {
    623         /* Count how many bites we send down the socket */
    624         ASMAtomicIncU64(&pThis->cbWakeupNotifs);
    625     }
    626624#endif
    627     AssertRC(rc);
    628625}
    629626
     
    722719{
    723720    PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
     721
     722    /* The first polling entry is for the control/wakeup pipe. */
    724723#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];
    727726#else
    728727    unsigned int cPollNegRet = 0;
     
    786785
    787786        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.   */
    790797        if (pThis->pNATState->polls[0].revents & (POLLRDNORM|POLLPRI|POLLRDBAND))   /* POLLPRI won't be seen with WSAPoll. */
    791798        {
    792             /* drain the pipe
    793              *
    794              * Note! drvNATSend decoupled so we don't know how many times
    795              * device's thread sends before we've entered multiplex,
    796              * so to avoid false alarm drain pipe here to the very end
    797              */
    798799            char ch[1024];
    799800            size_t cbRead;
    800801            uint64_t cbWakeupNotifs = ASMAtomicReadU64(&pThis->cbWakeupNotifs);
    801802#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);
    803804#else
    804805            RTPipeRead(pThis->hPipeRead, &ch[0], RT_MIN(cbWakeupNotifs, 1024), &cbRead);
     
    11951196 * Libslirp Callbacks
    11961197 */
     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. */
    11971200/**
    11981201 * Callback called by libslirp to send packet into guest.
    11991202 *
    1200  * @param   pBuf    Pointer to packet buffer.
     1203 * @param   pvBuf   Pointer to packet buffer.
    12011204 * @param   cb      Size of packet.
    1202  * @param   opaque  Pointer to NAT State context.
     1205 * @param   pvUser  Pointer to NAT State context.
    12031206 *
    12041207 * @returns Size of packet received or -1 on error.
     
    12061209 * @thread  ?
    12071210 */
    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;
     1211static DECLCALLBACK(ssize_t) drvNAT_SendPacketCb(const void *pvBuf, ssize_t cb, void *pvUser /* PDRVNAT */)
     1212{
     1213    PDRVNAT const pThis = (PDRVNAT)pvUser;
    12171214    Assert(pThis);
    12181215
    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));
    12221222
    12231223    /* don't queue new requests when the NAT thread is about to stop */
     
    12271227    ASMAtomicIncU32(&pThis->cPkts);
    12281228    int rc = RTReqQueueCallEx(pThis->hRecvReqQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
    1229                               (PFNRT)drvNATRecvWorker, 3, pThis, pNewBuf, cb);
    1230     AssertRC(rc);
     1229                              (PFNRT)drvNATRecvWorker, 3, pThis, pvNewBuf, cb);
     1230    AssertRCStmt(rc, RTMemFree(pvNewBuf));
    12311231    drvNATRecvWakeup(pThis->pDrvIns, pThis->pRecvThread);
     1232
     1233    /** @todo r=bird: explain why we wake up the other thread here? */
    12321234    drvNATNotifyNATThread(pThis, "drvNAT_SendPacketCb");
     1235
    12331236    STAM_COUNTER_INC(&pThis->StatQueuePktSent);
    12341237    LogFlowFuncLeave();
     
    12371240
    12381241/**
    1239  * Callback called by libslirp on an error from a guest.
     1242 * Callback called by libslirp when the guest does something wrong.
    12401243 *
    12411244 * @param   pMsg    Error message string.
    1242  * @param   opaque  Pointer to NAT State context.
     1245 * @param   pvUser  Pointer to NAT State context.
    12431246 *
    12441247 * @thread  ?
    12451248 */
    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));
     1249static 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);
    12541255}
    12551256
     
    12571258 * Callback called by libslirp to get the current timestamp in nanoseconds.
    12581259 *
    1259  * @param   opaque  Pointer to NAT State context.
     1260 * @param   pvUser  Pointer to NAT State context.
    12601261 *
    12611262 * @returns 64-bit signed integer representing time in nanoseconds.
    12621263 */
    1263 static DECLCALLBACK(int64_t) drvNAT_ClockGetNsCb(void *opaque)
    1264 {
    1265     PDRVNAT pThis = (PDRVNAT)opaque;
    1266     Assert(pThis);
    1267 
    1268     RT_NOREF(pThis);
    1269 
     1264static DECLCALLBACK(int64_t) drvNAT_ClockGetNsCb(void *pvUser)
     1265{
     1266    RT_NOREF(pvUser);
    12701267    return (int64_t)RTTimeNanoTS();
    12711268}
     
    14511448    if (pNATState)
    14521449    {
    1453         slirp_cleanup(pNATState->pSlirp);
     1450        if (pNATState->pSlirp)
     1451        {
     1452            slirp_cleanup(pNATState->pSlirp);
     1453            pNATState->pSlirp = NULL;
     1454        }
    14541455
    14551456#ifdef VBOX_WITH_STATISTICS
     
    14711472    pThis->hRecvReqQueue = NIL_RTREQQUEUE;
    14721473
    1473     RTSemEventDestroy(pThis->EventRecv);
    1474     pThis->EventRecv = NIL_RTSEMEVENT;
     1474    RTSemEventDestroy(pThis->hEventRecv);
     1475    pThis->hEventRecv = NIL_RTSEMEVENT;
    14751476
    14761477    if (RTCritSectIsInitialized(&pThis->DevAccessLock))
     
    14831484    RTPipeClose(pThis->hPipeRead);
    14841485    RTPipeClose(pThis->hPipeWrite);
     1486    pThis->hPipeRead = NIL_RTPIPE;
     1487    pThis->hPipeWrite = NIL_RTPIPE;
    14851488#endif
    14861489}
     
    15011504     */
    15021505    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
    15031513
    15041514    SlirpState * const pNATState = (SlirpState *)RTMemAllocZ(sizeof(*pNATState));
     
    15111521    AssertReturn(pNATState->polls, VERR_NO_MEMORY);
    15121522    pNATState->uPollCap                 = 64;
    1513 
    1514     pThis->hSlirpReqQueue               = NIL_RTREQQUEUE;
    1515     pThis->EventRecv                    = NIL_RTSEMEVENT;
    15161523
    15171524    /* IBase */
     
    15561563                                  , "PortForwarding");
    15571564
    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            ));
    15691576
    15701577    /*
     
    15721579     */
    15731580    int  rc;
     1581    /** @todo clean up the macros used here. S32 != int. Use defaults. ++  */
    15741582
    15751583    bool fPassDomain = true;
     
    15941602    int i32SoMaxConn = 10;
    15951603    GET_S32(rc, pDrvIns, pCfg, "SoMaxConnection", i32SoMaxConn);
     1604
    15961605    /*
    15971606     * Query the network port interface.
     
    16001609    if (!pThis->pIAboveNet)
    16011610        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"));
    16041612    pThis->pIAboveConfig = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMINETWORKCONFIG);
    16051613    if (!pThis->pIAboveConfig)
    16061614        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"));
    16091616
    16101617    /* Generate a network address for this network card. */
     
    16151622                                   pDrvIns->iInstance);
    16161623
    1617     RTNETADDRIPV4 Network, Netmask, Nettemp;
     1624    RTNETADDRIPV4 Network, Netmask;
    16181625    rc = RTCidrStrToIPv4(szNetwork, &Network, &Netmask);
    16191626    if (RT_FAILURE(rc))
     
    16221629                                   pDrvIns->iInstance, szNetwork);
    16231630
    1624     /* Construct Libslirp Config and Initialzie Slirp */
    1625 
     1631    /*
     1632     * Construct Libslirp Config.
     1633     */
    16261634    LogFlow(("Here is what is coming out of the vbox config (NAT#%d):\n"
    16271635             "  Network: %RTnaipv4\n"
     
    16291637             pDrvIns->iInstance, RT_H2BE_U32(Network.u), RT_H2BE_U32(Netmask.u)));
    16301638
     1639    /* IPv4: */
    16311640    struct in_addr vnetwork = RTNetIPv4AddrHEToInAddr(&Network);
    16321641    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);
    16391654
    16401655    SlirpConfig slirpCfg = { 0 };
     
    16491664    slirpCfg.in6_enabled = true;
    16501665
    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. */
    16581670    inet_pton(AF_INET6, "fd17:625c:f037:0::",  &slirpCfg.vprefix_addr6);
    16591671    inet_pton(AF_INET6, "fd17:625c:f037:0::2", &slirpCfg.vhost6);
     
    16831695    slirpCfg.iSoMaxConn = i32SoMaxConn;
    16841696
    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;
    16941706    slirpCallbacks.init_completed = NULL;
    16951707    slirpCallbacks.timer_new_opaque = NULL;
    16961708
    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;
    17031718
    17041719    rc = drvNATConstructRedir(pDrvIns->iInstance, pThis, pCfg, &Network);
     
    17181733    AssertRCReturn(rc, rc);
    17191734
    1720     rc = RTSemEventCreate(&pThis->EventRecv);
     1735    rc = RTSemEventCreate(&pThis->hEventRecv);
    17211736    AssertRCReturn(rc, rc);
    17221737
     
    17371752#endif
    17381753
    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);
    17421759    AssertRCReturn(rc, rc);
    17431760#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*/);
    17501763    AssertRCReturn(rc, rc);
    17511764#endif
Note: See TracChangeset for help on using the changeset viewer.

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