VirtualBox

Changeset 23462 in vbox for trunk/src


Ignore:
Timestamp:
Oct 1, 2009 5:42:19 AM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
53061
Message:

NAT: Big changeset:

  1. mbuf_zone has been inroduced.
  2. IPRT timers replaces Slirp's one making poll/WSAWaitForMultipleEvents blocking.
  3. UrgRecv(Thread,Req) introduced for transfering ICMP errors/ARP with highter priority.
Location:
trunk/src/VBox/Devices/Network
Files:
13 edited

Legend:

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

    r23163 r23462  
    166166    /** thread delivering packets for receiving by the guest */
    167167    PPDMTHREAD              pRecvThread;
     168    /** thread delivering urg packets for receiving by the guest */
     169    PPDMTHREAD              pUrgRecvThread;
    168170    /** event to wakeup the guest receive thread */
    169171    RTSEMEVENT              EventRecv;
     172    /** event to wakeup the guest urgent receive thread */
     173    RTSEMEVENT              EventUrgRecv;
    170174    /** Receive Req queue (deliver packets to the guest) */
    171175    PRTREQQUEUE             pRecvReqQueue;
     176    /** Receive Urgent Req queue (deliver packets to the guest) */
     177    PRTREQQUEUE             pUrgRecvReqQueue;
     178
     179    /* makes access to device func RecvAvail and Recv atomical */
     180    RTCRITSECT                csDevAccess;
     181    volatile uint32_t cUrgPkt;
     182    volatile uint32_t cPkt;
     183    PTMTIMERR3 pTmrSlow;
     184    PTMTIMERR3 pTmrFast;
    172185} DRVNAT;
    173186AssertCompileMemberAlignment(DRVNAT, StatNATRecvWakeups, 8);
     
    193206
    194207static void drvNATNotifyNATThread(PDRVNAT pThis);
     208static DECLCALLBACK(void) drvNATSlowTimer(PPDMDRVINS pDrvIns, PTMTIMER pTimer, void *pvUser);
     209static DECLCALLBACK(void) drvNATFast(PPDMDRVINS pDrvIns, PTMTIMER pTimer, void *pvUser);
    195210
    196211
     
    198213#define PDMINETWORKCONNECTOR_2_DRVNAT(pInterface)   ( (PDRVNAT)((uintptr_t)pInterface - RT_OFFSETOF(DRVNAT, INetworkConnector)) )
    199214
     215static DECLCALLBACK(void) drvNATSlowTimer(PPDMDRVINS pDrvIns, PTMTIMER pTimer, void *pvUser)
     216{
     217    Assert(pvUser);
     218    PDRVNAT pThis = (PDRVNAT)pvUser;
     219    drvNATNotifyNATThread(pThis);
     220}
     221
     222static DECLCALLBACK(void) drvNATFastTimer(PPDMDRVINS pDrvIns, PTMTIMER pTimer, void *pvUser)
     223{
     224    Assert(pvUser);
     225    PDRVNAT pThis = (PDRVNAT)pvUser;
     226    drvNATNotifyNATThread(pThis);
     227}
    200228
    201229
    202230static DECLCALLBACK(int) drvNATRecv(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
    203  {
     231{
    204232    PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
    205233
     
    210238    {
    211239        RTReqProcess(pThis->pRecvReqQueue, 0);
    212         RTSemEventWait(pThis->EventRecv, RT_INDEFINITE_WAIT);
     240        if (ASMAtomicReadU32(&pThis->cPkt) == 0)
     241            RTSemEventWait(pThis->EventRecv, RT_INDEFINITE_WAIT);
    213242    }
    214243    return VINF_SUCCESS;
     
    226255}
    227256
    228 
    229 static DECLCALLBACK(void) drvNATRecvWorker(PDRVNAT pThis, uint8_t *pu8Buf, int cb)
     257static DECLCALLBACK(int) drvNATUrgRecv(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
     258{
     259    PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
     260
     261    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
     262        return VINF_SUCCESS;
     263
     264    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
     265    {
     266        RTReqProcess(pThis->pUrgRecvReqQueue, 0);
     267        if (ASMAtomicReadU32(&pThis->cUrgPkt) == 0)
     268            RTSemEventWait(pThis->EventUrgRecv, RT_INDEFINITE_WAIT);
     269    }
     270    return VINF_SUCCESS;
     271}
     272static DECLCALLBACK(int) drvNATUrgRecvWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
     273{
     274    PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
     275    int rc = RTSemEventSignal(pThis->EventUrgRecv);
     276
     277    AssertReleaseRC(rc);
     278    return VINF_SUCCESS;
     279}
     280
     281static DECLCALLBACK(void) drvNATUrgRecvWorker(PDRVNAT pThis, uint8_t *pu8Buf, int cb, void *pvArg)
     282{
     283    int rc = RTCritSectEnter(&pThis->csDevAccess);
     284    AssertReleaseRC(rc);
     285    rc = pThis->pPort->pfnWaitReceiveAvail(pThis->pPort, RT_INDEFINITE_WAIT);
     286    if (RT_SUCCESS(rc))
     287    {
     288        rc = pThis->pPort->pfnReceive(pThis->pPort, pu8Buf, cb);
     289        rc = RTCritSectLeave(&pThis->csDevAccess);
     290        AssertReleaseRC(rc);
     291        slirp_ext_m_free(pThis->pNATState, pvArg);
     292    }
     293    else if (   RT_FAILURE(rc)
     294             && (  rc == VERR_TIMEOUT
     295                || rc == VERR_INTERRUPTED))
     296    {
     297        rc = RTCritSectLeave(&pThis->csDevAccess);
     298        slirp_ext_m_free(pThis->pNATState, pvArg);
     299    }
     300    else
     301    {
     302        rc = RTCritSectLeave(&pThis->csDevAccess);
     303        slirp_ext_m_free(pThis->pNATState, pvArg);
     304        AssertReleaseRC(rc);
     305    }
     306    if (ASMAtomicDecU32(&pThis->cUrgPkt) == 0)
     307    {
     308        drvNATRecvWakeup(pThis->pDrvIns, pThis->pRecvThread);
     309        drvNATNotifyNATThread(pThis);
     310    }
     311}
     312
     313
     314static DECLCALLBACK(void) drvNATRecvWorker(PDRVNAT pThis, uint8_t *pu8Buf, int cb, void *pvArg)
    230315{
    231316    STAM_PROFILE_START(&pThis->StatNATRecv, a);
    232317
    233318    STAM_PROFILE_START(&pThis->StatNATRecvWait, b);
    234     int rc = pThis->pPort->pfnWaitReceiveAvail(pThis->pPort, RT_INDEFINITE_WAIT);
    235     AssertMsgRC(rc, ("NAT: No RX available even on indefinite wait; rc=%Rrc", rc));
     319
     320    while(ASMAtomicReadU32(&pThis->cUrgPkt) != 0)
     321        RTSemEventWait(pThis->EventRecv, RT_INDEFINITE_WAIT);
     322
     323    int rc = RTCritSectEnter(&pThis->csDevAccess);
     324    rc = pThis->pPort->pfnWaitReceiveAvail(pThis->pPort, RT_INDEFINITE_WAIT);
     325    if (RT_SUCCESS(rc))
     326    {
     327        rc = pThis->pPort->pfnReceive(pThis->pPort, pu8Buf, cb);
     328        AssertReleaseRC(rc);
     329        rc = RTCritSectLeave(&pThis->csDevAccess);
     330        AssertReleaseRC(rc);
     331        slirp_ext_m_free(pThis->pNATState, pvArg);
     332    }
     333    else if (   RT_FAILURE(rc)
     334             && (  rc == VERR_TIMEOUT
     335                || rc == VERR_INTERRUPTED))
     336    {
     337        rc = RTCritSectLeave(&pThis->csDevAccess);
     338        AssertReleaseRC(rc);
     339        slirp_ext_m_free(pThis->pNATState, pvArg);
     340    }
     341    else
     342    {
     343        rc = RTCritSectLeave(&pThis->csDevAccess);
     344        slirp_ext_m_free(pThis->pNATState, pvArg);
     345        AssertReleaseRC(rc);
     346    }
     347    ASMAtomicDecU32(&pThis->cPkt);
     348
     349    drvNATNotifyNATThread(pThis);
    236350
    237351    STAM_PROFILE_STOP(&pThis->StatNATRecvWait, b);
    238 
    239     rc = pThis->pPort->pfnReceive(pThis->pPort, pu8Buf, cb);
    240     AssertRC(rc);
    241     RTMemFree(pu8Buf);
    242 
    243352    STAM_PROFILE_STOP(&pThis->StatNATRecv, a);
    244353}
     
    248357 * @thread "NAT" thread.
    249358 */
    250 static void drvNATSendWorker(PDRVNAT pThis, const void *pvBuf, size_t cb)
     359static void drvNATSendWorker(PDRVNAT pThis, void *pvBuf, size_t cb)
    251360{
    252361    Assert(pThis->enmLinkState == PDMNETWORKLINKSTATE_UP);
    253362    if (pThis->enmLinkState == PDMNETWORKLINKSTATE_UP)
    254         slirp_input(pThis->pNATState, (uint8_t *)pvBuf, cb);
     363        slirp_input(pThis->pNATState, pvBuf);
    255364}
    256365
     
    288397
    289398    /* @todo: Here we should get mbuf instead temporal buffer */
     399#if 0
    290400    buf = RTMemAlloc(cb);
    291401    if (buf == NULL)
     
    295405    }
    296406    memcpy(buf, pvBuf, cb);
     407#else
     408    void *pvmBuf = slirp_ext_m_get(pThis->pNATState);
     409    Assert(pvmBuf);
     410    slirp_ext_m_append(pThis->pNATState, pvmBuf, (uint8_t *)pvBuf, cb);
     411#endif
    297412
    298413    pReq->u.Internal.pfn      = (PFNRT)drvNATSendWorker;
    299     pReq->u.Internal.cArgs    = 3;
     414    pReq->u.Internal.cArgs    = 2;
    300415    pReq->u.Internal.aArgs[0] = (uintptr_t)pThis;
    301     pReq->u.Internal.aArgs[1] = (uintptr_t)buf;
    302     pReq->u.Internal.aArgs[2] = (uintptr_t)cb;
     416    pReq->u.Internal.aArgs[1] = (uintptr_t)pvmBuf;
    303417    pReq->fFlags              = RTREQFLAGS_VOID|RTREQFLAGS_NO_WAIT;
    304418
     
    459573        /* don't pass the managemant pipe */
    460574        slirp_select_fill(pThis->pNATState, &nFDs, &polls[1]);
     575#if 0
    461576        ms = slirp_get_timeout_ms(pThis->pNATState);
     577#else
     578        ms = 0;
     579#endif
    462580
    463581        polls[0].fd = pThis->PipeRead;
     
    509627#else /* RT_OS_WINDOWS */
    510628        slirp_select_fill(pThis->pNATState, &nFDs);
     629#if 0
    511630        ms = slirp_get_timeout_ms(pThis->pNATState);
     631#else
     632        ms = 0;
     633#endif
    512634        struct timeval tv = { 0, ms*1000 };
    513635        event = WSAWaitForMultipleEvents(nFDs, phEvents, FALSE, ms ? ms : WSA_INFINITE, FALSE);
     
    585707#endif /* VBOX_WITH_SLIRP_MT */
    586708
     709void slirp_arm_fast_timer(void *pvUser)
     710{
     711    PDRVNAT pThis = (PDRVNAT)pvUser;
     712    Assert(pThis);
     713    TMTimerSetMillies(pThis->pTmrFast, 2);
     714}
     715
     716void slirp_arm_slow_timer(void *pvUser)
     717{
     718    PDRVNAT pThis = (PDRVNAT)pvUser;
     719    Assert(pThis);
     720    TMTimerSetMillies(pThis->pTmrSlow, 500);
     721}
    587722
    588723/**
     
    596731}
    597732
    598 /**
    599  * Function called by slirp to feed incoming data to the network port.
    600  */
    601 void slirp_output(void *pvUser, void *pvArg, const uint8_t *pu8Buf, int cb)
     733void slirp_push_recv_thread(void *pvUser)
    602734{
    603735    PDRVNAT pThis = (PDRVNAT)pvUser;
    604736    Assert(pThis);
    605 
    606     LogFlow(("slirp_output BEGIN %x %d\n", pu8Buf, cb));
    607     Log2(("slirp_output: pu8Buf=%p cb=%#x (pThis=%p)\n%.*Rhxd\n", pu8Buf, cb, pThis, cb, pu8Buf));
     737    drvNATUrgRecvWakeup(pThis->pDrvIns, pThis->pUrgRecvThread);
     738}
     739
     740void slirp_urg_output(void *pvUser, void *pvArg, const uint8_t *pu8Buf, int cb)
     741{
     742    PDRVNAT pThis = (PDRVNAT)pvUser;
     743    Assert(pThis);
     744    ASMAtomicIncU32(&pThis->cUrgPkt);
    608745
    609746    PRTREQ pReq = NULL;
     
    613750        return;
    614751
    615     int rc = RTReqAlloc(pThis->pRecvReqQueue, &pReq, RTREQTYPE_INTERNAL);
     752    int rc = RTReqAlloc(pThis->pUrgRecvReqQueue, &pReq, RTREQTYPE_INTERNAL);
    616753    AssertReleaseRC(rc);
    617     pReq->u.Internal.pfn      = (PFNRT)drvNATRecvWorker;
    618     pReq->u.Internal.cArgs    = 3;
     754    pReq->u.Internal.pfn      = (PFNRT)drvNATUrgRecvWorker;
     755    pReq->u.Internal.cArgs    = 4;
    619756    pReq->u.Internal.aArgs[0] = (uintptr_t)pThis;
    620757    pReq->u.Internal.aArgs[1] = (uintptr_t)pu8Buf;
    621758    pReq->u.Internal.aArgs[2] = (uintptr_t)cb;
     759    pReq->u.Internal.aArgs[3] = (uintptr_t)pvArg;
     760    pReq->fFlags              = RTREQFLAGS_VOID|RTREQFLAGS_NO_WAIT;
     761    rc = RTReqQueue(pReq, 0);
     762    AssertReleaseRC(rc);
     763    drvNATUrgRecvWakeup(pThis->pDrvIns, pThis->pUrgRecvThread);
     764}
     765
     766/**
     767 * Function called by slirp to feed incoming data to the network port.
     768 */
     769void slirp_output(void *pvUser, void *pvArg, const uint8_t *pu8Buf, int cb)
     770{
     771    PDRVNAT pThis = (PDRVNAT)pvUser;
     772    Assert(pThis);
     773
     774    LogFlow(("slirp_output BEGIN %x %d\n", pu8Buf, cb));
     775    Log2(("slirp_output: pu8Buf=%p cb=%#x (pThis=%p)\n%.*Rhxd\n", pu8Buf, cb, pThis, cb, pu8Buf));
     776
     777    PRTREQ pReq = NULL;
     778
     779    /* don't queue new requests when the NAT thread is about to stop */
     780    if (pThis->pSlirpThread->enmState != PDMTHREADSTATE_RUNNING)
     781        return;
     782
     783    int rc = RTReqAlloc(pThis->pRecvReqQueue, &pReq, RTREQTYPE_INTERNAL);
     784    AssertReleaseRC(rc);
     785    ASMAtomicIncU32(&pThis->cPkt);
     786    pReq->u.Internal.pfn      = (PFNRT)drvNATRecvWorker;
     787    pReq->u.Internal.cArgs    = 4;
     788    pReq->u.Internal.aArgs[0] = (uintptr_t)pThis;
     789    pReq->u.Internal.aArgs[1] = (uintptr_t)pu8Buf;
     790    pReq->u.Internal.aArgs[2] = (uintptr_t)cb;
     791    pReq->u.Internal.aArgs[3] = (uintptr_t)pvArg;
    622792    pReq->fFlags              = RTREQFLAGS_VOID|RTREQFLAGS_NO_WAIT;
    623793    rc = RTReqQueue(pReq, 0);
     
    9511121                return rc;
    9521122            }
     1123            rc = RTReqCreateQueue(&pThis->pUrgRecvReqQueue);
     1124            if (RT_FAILURE(rc))
     1125            {
     1126                LogRel(("NAT: Can't create request queue\n"));
     1127                return rc;
     1128            }
    9531129            rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pRecvThread, pThis, drvNATRecv,
    9541130                                          drvNATRecvWakeup, 128 * _1K, RTTHREADTYPE_IO, "NATRX");
    9551131            AssertReleaseRC(rc);
    9561132            rc = RTSemEventCreate(&pThis->EventRecv);
     1133
     1134            rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pUrgRecvThread, pThis, drvNATUrgRecv,
     1135                                          drvNATUrgRecvWakeup, 128 * _1K, RTTHREADTYPE_IO, "NATURGRX");
     1136            AssertReleaseRC(rc);
     1137            rc = RTSemEventCreate(&pThis->EventRecv);
     1138            rc = RTSemEventCreate(&pThis->EventUrgRecv);
     1139            rc = RTCritSectInit(&pThis->csDevAccess);
     1140            rc = PDMDrvHlpTMTimerCreate(pThis->pDrvIns, TMCLOCK_REAL/*enmClock*/, drvNATSlowTimer,
     1141                    pThis, TMTIMER_FLAGS_NO_CRIT_SECT/*flags*/, "NATSlowTmr", &pThis->pTmrSlow);
     1142            rc = PDMDrvHlpTMTimerCreate(pThis->pDrvIns, TMCLOCK_REAL/*enmClock*/, drvNATFastTimer,
     1143                    pThis, TMTIMER_FLAGS_NO_CRIT_SECT/*flags*/, "NATFastTmr", &pThis->pTmrFast);
    9571144
    9581145#ifndef RT_OS_WINDOWS
  • trunk/src/VBox/Devices/Network/slirp/counters.h

    r23154 r23462  
    104104COUNTING_COUNTER(IOSBAppendSB_w_ge_r, "SB: AppendSB (sb_wptr >= sb_rptr)");
    105105COUNTING_COUNTER(IOSBAppendSB_w_alter, "SB: AppendSB (altering of sb_wptr)");
     106COUNTING_COUNTER(MBufAllocation,"MBUF::shows number of mbufs in used list");
    106107
    107108COUNTING_COUNTER(TCP_retransmit, "TCP::retransmit");
  • trunk/src/VBox/Devices/Network/slirp/if.c

    r23369 r23462  
    280280        }
    281281
    282         if_encap(pData, ETH_P_IP, ifm);
     282        if_encap(pData, ETH_P_IP, ifm, 0);
    283283
    284284        if (!if_queued)
  • trunk/src/VBox/Devices/Network/slirp/ip_icmp.c

    r23369 r23462  
    515515#endif
    516516
    517     if (type!=ICMP_UNREACH && type!=ICMP_TIMXCEED)
     517    if (type!=ICMP_UNREACH && type!=ICMP_TIMXCEED && type != ICMP_SOURCEQUENCH)
    518518        goto end_error;
    519519
     
    531531    }
    532532#endif
    533     if (ip->ip_off & IP_OFFMASK)
     533    if (ip->ip_off & IP_OFFMASK && type != ICMP_SOURCEQUENCH)
    534534        goto end_error;    /* Only reply to fragment 0 */
    535535
     
    657657    ip->ip_src = alias_addr;
    658658
    659     (void ) ip_output(pData, (struct socket *)NULL, m);
     659    (void ) ip_output0(pData, (struct socket *)NULL, m, 1);
    660660
    661661    icmpstat.icps_reflect++;
  • trunk/src/VBox/Devices/Network/slirp/ip_output.c

    r23369 r23462  
    8181ip_output(PNATState pData, struct socket *so, struct mbuf *m0)
    8282{
     83    return ip_output0(pData, so, m0, 0);
     84}
     85
     86int
     87ip_output0(PNATState pData, struct socket *so, struct mbuf *m0, int urg)
     88{
    8389    register struct ip *ip;
    8490    register struct mbuf *m = m0;
     
    200206        memcpy(eh->h_source, eth_dst, ETH_ALEN);
    201207
     208#ifdef VBOX_WITH_SLIRP_BSD_MBUF
    202209        if_output(pData, so, m);
     210#else
     211        if_encap(pData, ETH_P_IP, m, urg? ETH_ENCAP_URG : 0);
     212#endif
    203213        goto done;
    204214     }
     
    381391                memcpy(eh->h_source, eth_dst, ETH_ALEN);
    382392
     393#ifdef VBOX_WITH_SLIRP_BSD_MBUF
    383394                if_output(pData, so, m);
     395#else
     396                if_encap(pData, ETH_P_IP, m, 0);
     397#endif
    384398            }
    385399            else
  • trunk/src/VBox/Devices/Network/slirp/libslirp.h

    r23369 r23462  
    4848#endif /* !RT_OS_WINDOWS */
    4949
     50#ifdef VBOX_WITH_SLIRP_BSD_MBUF
    5051void slirp_input(PNATState pData, const uint8_t *pkt, int pkt_len);
     52#else
     53void slirp_input(PNATState pData, void *pvData);
     54#endif
    5155void slirp_set_ethaddr(PNATState pData, const uint8_t *ethaddr);
    5256
    5357/* you must provide the following functions: */
     58void slirp_arm_fast_timer(void *pvUser);
     59void slirp_arm_slow_timer(void *pvUser);
    5460int slirp_can_output(void * pvUser);
    5561void slirp_output(void * pvUser, void *pvArg, const uint8_t *pkt, int pkt_len);
     62void slirp_urg_output(void *pvUser, void *pvArg, const uint8_t *pu8Buf, int cb);
    5663void slirp_post_sent(PNATState pData, void *pvArg);
    5764
     
    111118void *slirp_get_queue(PNATState pData);
    112119#endif
     120#ifndef VBOX_WITH_SLIRP_BSD_MBUF
     121void *slirp_ext_m_get(PNATState pData);
     122void slirp_ext_m_free(PNATState pData, void *);
     123void slirp_ext_m_append(PNATState pData, void *, uint8_t *, size_t);
     124void slirp_push_recv_thread(void *pvUser);
     125#endif
    113126
    114127/*
  • trunk/src/VBox/Devices/Network/slirp/main.h

    r18902 r23462  
    99#include <sys/select.h>
    1010#endif
    11 
    12 void if_encap(PNATState pData, uint16_t eth_proto, struct mbuf *m);
     11#define ETH_ENCAP_URG 1
     12void if_encap(PNATState pData, uint16_t eth_proto, struct mbuf *m, int flags);
  • trunk/src/VBox/Devices/Network/slirp/mbuf.c

    r23369 r23462  
    1515 * the flags
    1616 */
    17 
    1817#include <slirp.h>
    1918
     19#define MBUF_ZONE_SIZE 100
     20static int mbuf_zone_init(PNATState pData)
     21{
     22    int limit;
     23    struct mbuf_zone *mzone;
     24    int i;
     25    struct mbuf *m;
     26    uint8_t *zone = RTMemAlloc(msize * MBUF_ZONE_SIZE); 
     27    if (zone == NULL)
     28    {
     29        LogRel(("NAT: can't allocate new zone\n"));
     30        return -1;
     31    }
     32    mzone = RTMemAllocZ(sizeof (struct mbuf_zone));
     33    if (mzone == NULL)
     34    {
     35        RTMemFree(zone);
     36        LogRel(("NAT: can't allocate zone descriptor\n"));
     37        return -1;
     38    }
     39
     40    for(i = 0; i < MBUF_ZONE_SIZE; ++i)
     41    {
     42        m = (struct mbuf *)((char *)zone + i*msize);
     43#ifdef M_BUF_DEBUG
     44        m->m_hdr.mh_id = pData->mbuf_zone_count * MBUF_ZONE_SIZE + i;
     45#endif
     46        insque(pData, m, &m_freelist);
     47    }
     48    mzone->mbuf_zone_base_addr = zone;
     49    LIST_INSERT_HEAD(&pData->mbuf_zone_head, mzone, list);
     50    pData->mbuf_zone_count++;
     51    pData->mbuf_water_line_limit = pData->mbuf_zone_count * MBUF_ZONE_SIZE;
     52    return 0;
     53}
     54
     55void m_fini(PNATState pData)
     56{
     57    struct mbuf_zone *mz;
     58    struct mbuf *m;
     59    int i;
     60    void *zone;
     61    while(!LIST_EMPTY(&pData->mbuf_zone_head))
     62    {
     63        mz = LIST_FIRST(&pData->mbuf_zone_head);
     64        zone = mz->mbuf_zone_base_addr;
     65        for(i = 0; i < MBUF_ZONE_SIZE; ++i)
     66        {
     67            m = (struct mbuf *)((char *)zone + i*msize);
     68            if (   (m->m_flags & M_EXT)
     69                && m->m_ext != NULL)
     70                RTMemFree(m->m_ext);
     71        }
     72        RTMemFree(zone);
     73        LIST_REMOVE(mz, list);
     74        RTMemFree(mz);
     75    }
     76}
    2077
    2178void
    2279m_init(PNATState pData)
    2380{
     81    int i;
     82    struct mbuf *m;
     83    int rc = 0;
    2484    m_freelist.m_next = m_freelist.m_prev = &m_freelist;
    2585    m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist;
    2686    mbuf_alloced = 0;
    2787    msize_init(pData);
     88#if 1
     89    rc = RTCritSectInit(&pData->cs_mbuf_zone);
     90    AssertReleaseRC(rc);
     91    rc = mbuf_zone_init(pData);
     92    Assert((rc == 0));
     93#endif
    2894}
    2995
     
    38104          + if_maxlinkhdr ;
    39105}
    40 
     106#ifdef m_get
     107# undef m_get
     108#endif
     109
     110#ifdef m_free
     111# undef m_free
     112#endif
    41113/*
    42114 * Get an mbuf from the free list, if there are none
     
    52124    register struct mbuf *m;
    53125    int flags = 0;
     126    int rc = 0;
    54127
    55128    DEBUG_CALL("m_get");
    56 
     129   
     130    rc = RTCritSectEnter(&pData->cs_mbuf_zone);
     131    AssertReleaseRC(rc);
     132
     133recheck_zone:
    57134    if (m_freelist.m_next == &m_freelist)
    58135    {
     136#if 1
     137        int rc = mbuf_zone_init(pData);
     138        if (rc == 0)
     139            goto recheck_zone;
     140        AssertMsgFailed(("No mbufs on free list\n"));
     141        return NULL;
     142#else
    59143        m = (struct mbuf *)RTMemAlloc(msize);
    60144        if (m == NULL)
     
    65149        if (mbuf_alloced > mbuf_max)
    66150            mbuf_max = mbuf_alloced;
     151#endif
    67152    }
    68153    else
     
    72157    }
    73158
     159    STAM_COUNTER_INC(&pData->StatMBufAllocation);
    74160    /* Insert it in the used list */
     161    mbuf_alloced++;
     162    if (mbuf_alloced >= MBUF_ZONE_SIZE/2)
     163    {
     164        pData->fmbuf_water_line = 1;
     165    }
    75166    insque(pData, m, &m_usedlist);
    76167    m->m_flags = (flags | M_USEDLIST);
     
    87178end_error:
    88179    DEBUG_ARG("m = %lx", (long )m);
     180    rc = RTCritSectLeave(&pData->cs_mbuf_zone);
     181    AssertReleaseRC(rc);
    89182    return m;
    90183}
     
    93186m_free(PNATState pData, struct mbuf *m)
    94187{
    95 
     188    int rc;
    96189    DEBUG_CALL("m_free");
    97190    DEBUG_ARG("m = %lx", (long )m);
    98191
     192    rc = RTCritSectEnter(&pData->cs_mbuf_zone);
     193    AssertReleaseRC(rc);
     194    mbuf_alloced--;
    99195    if(m)
    100196    {
     
    112208        if (m->m_flags & M_DOFREE)
    113209        {
     210#if 1
     211            if ((m->m_flags & M_EXT) == 0)
     212                memset(m->m_dat, 0, if_mtu);
     213            insque(pData, m, &m_freelist);
     214            m->m_flags = M_FREELIST; /* Clobber other flags */
     215#else
    114216            RTMemFree(m);
     217#endif
    115218            mbuf_alloced--;
    116219        }
     
    120223            m->m_flags = M_FREELIST; /* Clobber other flags */
    121224        }
     225        STAM_COUNTER_INC(&pData->StatMBufAllocation);
    122226    } /* if(m) */
    123 }
     227    rc = RTCritSectLeave(&pData->cs_mbuf_zone);
     228    AssertReleaseRC(rc);
     229}
     230
     231/* update macros for m_get/m_free*/
     232#undef m_get
     233#undef m_free
     234#include "mbuf.h"
    124235
    125236/*
     
    254365    return (struct mbuf *)0;
    255366}
     367#ifndef VBOX_WITH_SLIRP_BSD_MBUF
     368void *slirp_ext_m_get(PNATState pData)
     369{
     370    return (void *)m_get(pData);
     371}
     372
     373void slirp_ext_m_free(PNATState pData, void *arg)
     374{
     375    struct mbuf *m = (struct mbuf *)arg;
     376    m_free(pData, m);
     377}
     378void slirp_ext_m_append(PNATState pData, void *arg, uint8_t *pu8Buf, size_t cbBuf)
     379{
     380    char *c;
     381    struct mbuf *m = (struct mbuf *)arg;
     382    if (cbBuf > M_FREEROOM(m))
     383    {
     384        m_inc(m, cbBuf);
     385    }
     386    c = mtod(m, char *);
     387    memcpy(c, pu8Buf, cbBuf);
     388    m->m_len = cbBuf;
     389}
     390#endif
  • trunk/src/VBox/Devices/Network/slirp/mbuf.h

    r23154 r23462  
    3838#define _MBUF_H_
    3939#ifndef VBOX_WITH_SLIRP_BSD_MBUF
     40/* #define M_BUF_DEBUG */
    4041
    4142#define m_freem m_free
     
    7677    int     mh_len;            /* Amount of data in this mbuf */
    7778    struct libalias *mh_la;     /*Real freebsd store hocksin similar way*/
     79#ifdef M_BUF_DEBUG
     80    int mh_id;
     81    char *mh_allocation_at_file;
     82    int mh_allocation_at_line;
     83#endif
    7884};
    7985
     
    135141
    136142void m_init (PNATState);
     143void m_fini(PNATState pData);
    137144void msize_init (PNATState);
    138145struct mbuf * m_get (PNATState);
     
    150157
    151158#define MBUF_IP_HEADER(m) (caddr_t)(MBUF_HEAD(m) + if_maxlinkhdr)
    152 
    153159#else
    154160# include "bsd/sys/mbuf.h"
    155161#endif
    156162#endif
     163
     164#if defined(M_BUF_DEBUG) && !defined(RT_OS_WINDOWS)
     165# define m_get(x)                                                                                               \
     166({                                                                                                              \
     167    struct mbuf *mdb = m_get((x));                                                                              \
     168    if(mdb)                                                                                                     \
     169    {                                                                                                           \
     170        mdb->m_hdr.mh_allocation_at_file = __FILE__;                                                            \
     171        mdb->m_hdr.mh_allocation_at_line = __LINE__;                                                            \
     172    }                                                                                                           \
     173    LogRel(("NAT:m(id:%d, ptr: %p) allocated at: %s:%d\n", (mdb?mdb->m_hdr.mh_id:-1), mdb, __FILE__, __LINE__));\
     174    mdb;                                                                                                        \
     175})
     176
     177# define m_free(x, m)                                                                               \
     178({                                                                                                  \
     179    (m)->m_hdr.mh_allocation_at_file = NULL;                                                        \
     180    (m)->m_hdr.mh_allocation_at_line = 0;                                                           \
     181    LogRel(("NAT:m(id:%d, ptr: %p) freed at: %s:%d\n", (m)->m_hdr.mh_id, (m), __FILE__, __LINE__)); \
     182    m_free((x),(m));                                                                                \
     183})
     184#endif
  • trunk/src/VBox/Devices/Network/slirp/slirp.c

    r23369 r23462  
    697697    }
    698698    bootp_dhcp_fini(pData);
     699    m_fini(pData);
    699700#ifdef RT_OS_WINDOWS
    700701    WSACleanup();
     
    770771    if (!link_up)
    771772        goto done;
     773   
    772774    /*
    773775     * *_slowtimo needs calling if there are IP fragments
     
    785787            {
    786788                do_slowtimo = 1;
     789                slirp_arm_slow_timer(pData->pvUser);
    787790                break;
    788791            }
     
    799802        so->so_poll_index = -1;
    800803#endif
     804        if (pData->fmbuf_water_line == 1)
     805        {
     806            if (mbuf_alloced < pData->mbuf_water_line_limit/2)
     807            {
     808                pData->fmbuf_water_warn_sent = 0;
     809                pData->fmbuf_water_line = 0;
     810            }
     811#ifndef RT_OS_WINDOWS
     812            poll_index = 0;
     813#endif
     814            goto done;
     815        }
    801816        STAM_COUNTER_INC(&pData->StatTCP);
    802817
     
    807822                && so->so_tcpcb != NULL
    808823                && so->so_tcpcb->t_flags & TF_DELACK)
     824        {
    809825            time_fasttimo = curtime; /* Flag when we want a fasttimo */
     826            slirp_arm_fast_timer(pData->pvUser);
     827        }
    810828
    811829        /*
     
    867885    /* { */
    868886
     887        if (pData->fmbuf_water_line == 1)
     888        {
     889            if (mbuf_alloced < pData->mbuf_water_line_limit/2)
     890            {
     891                pData->fmbuf_water_line = 0;
     892                pData->fmbuf_water_warn_sent = 0;
     893            }
     894#ifndef RT_OS_WINDOWS
     895            poll_index = 0;
     896#endif
     897            goto done;
     898        }
    869899        STAM_COUNTER_INC(&pData->StatUDP);
    870900#if !defined(RT_OS_WINDOWS)
     
    892922            }
    893923            else
     924            {
    894925                do_slowtimo = 1; /* Let socket expire */
     926                slirp_arm_slow_timer(pData->pvUser);
     927            }
    895928        }
    896929
     
    9921025    QSOCKET_FOREACH(so, so_next, tcp)
    9931026    /* { */
     1027        if (pData->fmbuf_water_line == 1)
     1028        {
     1029            if (mbuf_alloced < pData->mbuf_water_line_limit/2)
     1030            {
     1031                pData->fmbuf_water_line = 0;
     1032                pData->fmbuf_water_warn_sent = 0;
     1033            }
     1034            goto done;
     1035        }
    9941036
    9951037#ifdef VBOX_WITH_SLIRP_MT
     
    12801322     QSOCKET_FOREACH(so, so_next, udp)
    12811323     /* { */
     1324        if (pData->fmbuf_water_line == 1)
     1325        {
     1326            if (mbuf_alloced < pData->mbuf_water_line_limit/2)
     1327            {
     1328                pData->fmbuf_water_line = 0;
     1329                pData->fmbuf_water_warn_sent = 0;
     1330            }
     1331            goto done;
     1332        }
    12821333#ifdef VBOX_WITH_SLIRP_MT
    12831334        if (   so->so_state & SS_NOFDREF
     
    13221373
    13231374done:
    1324 #ifndef VBOX_WITH_SLIRP_MT
     1375#if 0
    13251376    /*
    13261377     * See if we can start outputting
     
    14101461                    }
    14111462                }
     1463                m_free(pData, m);
     1464                m_free(pData, mr);
    14121465                return;
    14131466        arp_ok:
     
    14311484                memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
    14321485                memcpy(rah->ar_tip, ah->ar_sip, 4);
    1433                 if_encap(pData, ETH_P_ARP, mr);
     1486                if_encap(pData, ETH_P_ARP, mr, ETH_ENCAP_URG);
    14341487                m_free(pData, m);
    14351488            }
     
    14721525}
    14731526
     1527#ifdef VBOX_WITH_SLIRP_BSD_MBUF
    14741528void slirp_input(PNATState pData, const uint8_t *pkt, int pkt_len)
     1529#else
     1530void slirp_input(PNATState pData, void *pvArg)
     1531#endif
    14751532{
    14761533    struct mbuf *m;
    14771534    int proto;
    14781535    static bool fWarnedIpv6;
     1536#ifdef VBOX_WITH_SLIRP_BSD_MBUF
    14791537    struct ethhdr *eh = (struct ethhdr*)pkt;
    1480 #ifdef VBOX_WITH_SLIRP_BSD_MBUF
    14811538    int size = 0;
    1482 #endif
    1483 
     1539#else
     1540    struct ethhdr *eh;
     1541#endif
     1542
     1543#ifndef VBOX_WITH_SLIRP_BSD_MBUF
     1544    m = (struct mbuf *)pvArg;
     1545    if (m->m_len < ETH_HLEN)
     1546    {
     1547        LogRel(("NAT: packet having size %d has been ingnored\n", m->m_len));
     1548        m_free(pData, m);
     1549        return;
     1550    }
     1551    eh = mtod(m, struct ethhdr *);
     1552    proto = ntohs(eh->h_proto);
     1553#else
    14841554    Log2(("NAT: slirp_input %d\n", pkt_len));
    14851555    if (pkt_len < ETH_HLEN)
     
    14981568    }
    14991569
    1500 #ifndef VBOX_WITH_SLIRP_BSD_MBUF
    1501     m = m_get(pData);
    1502 #else
    15031570    if (pkt_len < MSIZE)
    15041571    {
     
    15221589    }
    15231590    m = m_getjcl(pData, M_NOWAIT, MT_HEADER, M_PKTHDR, size);
    1524 #endif
    15251591    if (!m)
    15261592    {
     
    15301596    }
    15311597
    1532     /* Note: we add to align the IP header */
    1533 
    1534 #ifndef VBOX_WITH_SLIRP_BSD_MBUF
    1535     if (M_FREEROOM(m) < pkt_len)
    1536        m_inc(m, pkt_len);
    1537 #endif
    1538 
    15391598    m->m_len = pkt_len ;
    15401599    memcpy(m->m_data, pkt, pkt_len);
     1600    proto = ntohs(*(uint16_t *)(pkt + 12));
     1601#endif
     1602    /* Note: we add to align the IP header */
     1603
    15411604
    15421605    if (pData->port_forwarding_activated == 0)
    15431606        activate_port_forwarding(pData, mtod(m, struct ethhdr *));
    15441607
    1545     proto = ntohs(*(uint16_t *)(pkt + 12));
    15461608    switch(proto)
    15471609    {
     
    15581620            m->m_pkthdr.header = mtod(m, void *);
    15591621#endif
     1622#if 1
     1623            if (   pData->fmbuf_water_line
     1624                && pData->fmbuf_water_warn_sent == 0
     1625                && (curtime - pData->tsmbuf_water_warn_sent) > 500)
     1626            {
     1627                icmp_error(pData, m, ICMP_SOURCEQUENCH, 0, 0, "Out of resources!!!");
     1628                pData->fmbuf_water_warn_sent = 1;
     1629                pData->tsmbuf_water_warn_sent = curtime;
     1630            }
     1631#endif
    15601632            ip_input(pData, m);
    15611633            break;
     
    15731645            break;
    15741646    }
     1647#ifdef VBOX_WITH_SLIRP_BSD_MBUF
    15751648    RTMemFree((void *)pkt);
     1649#endif
    15761650}
    15771651
    15781652/* output the IP packet to the ethernet device */
    1579 void if_encap(PNATState pData, uint16_t eth_proto, struct mbuf *m)
     1653void if_encap(PNATState pData, uint16_t eth_proto, struct mbuf *m, int flags)
    15801654{
    15811655    struct ethhdr *eh;
     
    16161690#else
    16171691    mlen = m_length(m, NULL);
    1618 #endif
    16191692    buf = RTMemAlloc(mlen);
    16201693    if (buf == NULL)
     
    16231696        goto done;
    16241697    }
     1698#endif
    16251699    eh->h_proto = htons(eth_proto);
    1626 #ifndef VBOX_WITH_SLIRP_BSD_MBUF
    1627     memcpy(buf, mtod(m, uint8_t *), mlen);
     1700#ifdef VBOX_WITH_SLIRP_BSD_MBUF
     1701    m_copydata(m, 0, mlen, (char *)buf);
    16281702#else
    1629     m_copydata(m, 0, mlen, (char *)buf);
    1630 #endif
    1631     slirp_output(pData->pvUser, NULL, buf, mlen);
     1703    if (flags & ETH_ENCAP_URG)
     1704        slirp_urg_output(pData->pvUser, m, mtod(m, char *), mlen);
     1705    else
     1706        slirp_output(pData->pvUser, m, mtod(m, char *), mlen);
     1707#endif
    16321708done:
    16331709    STAM_PROFILE_STOP(&pData->StatIF_encap, a);
     1710#ifdef VBOX_WITH_SLIRP_BSD_MBUF
    16341711    m_free(pData, m);
     1712#endif
    16351713}
    16361714
     
    20282106    m->m_len = sizeof(struct arphdr) + ETH_HLEN;
    20292107#endif
    2030     if_encap(pData, ETH_P_ARP, m);
     2108    if_encap(pData, ETH_P_ARP, m, ETH_ENCAP_URG);
    20312109    Log(("NAT: ARP request sent\n"));
    20322110}
  • trunk/src/VBox/Devices/Network/slirp/slirp.h

    r23369 r23462  
    286286/* ip_output.c */
    287287int ip_output (PNATState, struct socket *, struct mbuf *);
     288int ip_output0 (PNATState, struct socket *, struct mbuf *, int urg);
    288289
    289290/* tcp_input.c */
  • trunk/src/VBox/Devices/Network/slirp/slirp_state.h

    r23369 r23462  
    2323
    2424#include <iprt/req.h>
     25#include <iprt/critsect.h>
    2526
    2627#define COUNTERS_INIT
     
    9394};
    9495LIST_HEAD(port_forward_rule_list, port_forward_rule);
     96
     97#ifndef VBOX_WITH_SLIRP_BSD_MBUF
     98struct mbuf_zone
     99{
     100    LIST_ENTRY(mbuf_zone) list;
     101    uint8_t *mbuf_zone_base_addr;
     102};
     103LIST_HEAD(mbuf_zone_list, mbuf_zone);
     104#endif
     105
    95106
    96107/* forward declaration */
     
    133144    int msize;
    134145    struct mbuf m_freelist, m_usedlist;
     146#ifndef VBOX_WITH_SLIRP_BSD_MBUF
     147    struct mbuf_zone_list mbuf_zone_head;
     148    RTCRITSECT cs_mbuf_zone;
     149    int fmbuf_water_line;
     150    int mbuf_water_line_limit;
     151    int mbuf_zone_count;
     152    int fmbuf_water_warn_sent;
     153    uint32_t tsmbuf_water_warn_sent;
     154#endif
    135155    /* Stuff from slirp.c */
    136156    void *pvUser;
  • trunk/src/VBox/Devices/Network/slirp/tcp_output.c

    r23369 r23462  
    686686        }
    687687#endif
     688        if (m != NULL)
     689            m_free(pData, m);
    688690        return (error);
    689691    }
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