VirtualBox

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


Ignore:
Timestamp:
Nov 7, 2008 9:38:53 AM (16 years ago)
Author:
vboxsync
Message:

pseudo-timers moved to timers
polling select is notified via pipe (!!! on UNIX) about attaching new socket (to make it sleeping rather then polling)
writing part of slirp_select _fill/_poll are called on drvNATSend
pessimistic queue locking is in process to be tollerant to heavy model and to polling-less Slirp functioning

Location:
trunk/src/VBox/Devices/Network
Files:
7 edited

Legend:

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

    r13840 r13940  
    5959
    6060#ifdef VBOX_WITH_SYNC_SLIRP
     61#include <unistd.h> /* should be in UNix version only*/
    6162#include <iprt/semaphore.h>
     63#include <errno.h>
    6264#endif
    6365
     
    9698    /*used for wakep of poling thread*/
    9799    RTSEMEVENT               semIOmutex;
     100    PTMTIMER                 pNATFastTimer;
     101    PTMTIMER                 pNATSlowTimer;
     102    /** The write end of the control pipe. */
     103    RTFILE                  PipeWrite;
     104    /** The read end of the control pipe. */
     105    RTFILE                  PipeRead;
    98106#endif
    99107} DRVNAT, *PDRVNAT;
     
    168176#ifndef VBOX_WITH_SYNC_SLIRP
    169177    RTCritSectLeave(&pThis->CritSect);
     178#else
     179    int ndfds = 0;
     180    fd_set writefds;
     181    FD_ZERO(&writefds);
     182    slirp_send_fill(pThis->pNATState, &ndfds, &writefds);
     183    struct timeval tv = {0,0}; /* no wait */
     184
     185    int cWriteFDs = select(ndfds + 1, NULL, &writefds, NULL, &tv);
     186    if (cWriteFDs >= 0)
     187        slirp_send_trigger(pThis->pNATState, &ndfds, &writefds);
    170188#endif
    171189    LogFlow(("drvNATSend: end\n"));
     
    275293#else
    276294
     295static DECLCALLBACK(void) drvNATFastTimer(PPDMDRVINS pDrvIns, PTMTIMER pTimer)
     296{
     297    PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
     298    if (pThis->enmLinkState  == PDMNETWORKLINKSTATE_UP)
     299        slirp_fasttmr(pThis->pNATState);
     300    TMTimerSetMicro(pTimer, 2);
     301}
     302
     303static DECLCALLBACK(void) drvNATSlowTimer(PPDMDRVINS pDrvIns, PTMTIMER pTimer)
     304{
     305    PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
     306    if (pThis->enmLinkState  == PDMNETWORKLINKSTATE_UP)
     307        slirp_slowtmr(pThis->pNATState);
     308    TMTimerSetMicro(pTimer, 500);
     309}
    277310static DECLCALLBACK(int) drvNATAsyncIoThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
    278311{
     
    301334        slirp_select_fill(pThis->pNATState, &cFDs, &ReadFDs, &WriteFDs, &XcptFDs);
    302335
    303         struct timeval tv = {0, 0}; /* no wait */
    304 
    305         int cReadFDs = select(cFDs + 1, &ReadFDs, &WriteFDs, &XcptFDs, &tv);
    306 
    307         if (cReadFDs >= 0)
     336        struct timeval tv = {1, 0}; /* no wait */
     337
     338        FD_SET(pThis->PipeRead, &ReadFDs); /*Linux only*/
     339        cFDs = (pThis->PipeRead < cFDs ? cFDs:pThis->PipeRead);
     340        int cReadFDs = select(cFDs + 1, &ReadFDs, NULL, &XcptFDs, &tv);
     341
     342        if (cReadFDs >= 0) {
    308343            slirp_select_poll(pThis->pNATState, &ReadFDs, &WriteFDs, &XcptFDs);
    309344
     345            if (FD_ISSET(pThis->PipeRead, &ReadFDs)) {
     346                /* drain the pipe */
     347                char ch;
     348                size_t cbRead;
     349                RTFileRead(pThis->PipeRead, &ch, 1, &cbRead);
     350            }
     351        }
    310352#if 0
    311353        if (cReadFDs == 0) {
     
    335377}
    336378
     379/*Callback from slirp to exit from select*/
     380void slirp_socket_created(void* pvUser)
     381{
     382    PDRVNAT pThis = (PDRVNAT)pvUser;
     383    int rc = RTFileWrite(pThis->PipeWrite, "", 1, NULL);
     384    AssertRC(rc);
     385}
    337386#endif
    338387
     
    682731                    rc = RTSemEventCreate(&pThis->semIOmutex);
    683732                    AssertReleaseRC(rc);
     733
     734                    /*
     735                     * Create the control pipe.
     736                     * XXX: Linux only
     737                     */
     738                    int fds[2];
     739                    if (pipe(&fds[0]) != 0) /** @todo RTPipeCreate() or something... */
     740                    {
     741                        int rc = RTErrConvertFromErrno(errno);
     742                        AssertRC(rc);
     743                        return rc;
     744                    }
     745                    pThis->PipeRead = fds[0];
     746                    pThis->PipeWrite = fds[1];
     747
    684748                    rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pThread, pThis, drvNATAsyncIoThread, drvNATAsyncIoWakeup, 128 * _1K, RTTHREADTYPE_IO, "NAT");
    685749                    AssertReleaseRC(rc);
     750                    rc = PDMDrvHlpTMTimerCreate(pDrvIns, TMCLOCK_REAL, drvNATFastTimer, "NAT_fast_timer", &pThis->pNATFastTimer);
     751                    AssertReleaseRC(rc);
     752                    TMTimerSetMicro(pThis->pNATFastTimer, 1);
     753                    rc = PDMDrvHlpTMTimerCreate(pDrvIns, TMCLOCK_REAL, drvNATSlowTimer, "NAT_slow_timer", &pThis->pNATSlowTimer);
     754                    AssertReleaseRC(rc);
     755                    TMTimerSetMicro(pThis->pNATSlowTimer, 500);
    686756#endif
    687757
  • trunk/src/VBox/Devices/Network/slirp/libslirp.h

    r8285 r13940  
    4949                   int guest_port);
    5050
    51 
     51#ifdef VBOX_WITH_SYNC_SLIRP
     52void slirp_fasttmr(PNATState pData);
     53void slirp_slowtmr(PNATState pData);
     54/*selects open and ready sockets for write*/
     55void slirp_send_fill(PNATState pData, int *pnfds, fd_set *writeds);
     56/*triggers socket output */
     57void slirp_send_trigger(PNATState pData, int *pnfds, fd_set *writeds);
     58/*should be implemented by client*/
     59void slirp_socket_created(void* pvUser);
     60#endif
    5261#ifdef __cplusplus
    5362}
  • trunk/src/VBox/Devices/Network/slirp/mbuf.c

    r13897 r13940  
    8080                        mbuf_max = mbuf_alloced;
    8181                VBOX_SLIRP_UNLOCK(pData->mbuf_alloced_mutex);
     82                VBOX_SLIRP_LOCK_CREATE(&m->m_mutex);
     83                VBOX_SLIRP_LOCK(m->m_mutex);
    8284        } else {
    8385                m = m_freelist.m_next;
     86                VBOX_SLIRP_LOCK(m->m_mutex);
     87                struct mbuf *n = m->m_next;
     88                if (n != NULL)
     89                    VBOX_SLIRP_LOCK(n->m_mutex);
    8490                remque(pData, m);
     91                if (m->m_next != NULL)
     92                    VBOX_SLIRP_UNLOCK(n->m_mutex);
    8593        }
    8694
     
    8997        VBOX_SLIRP_LOCK(pData->m_usedlist_mutex);
    9098        /* Insert it in the used list */
     99        struct mbuf *n = m_usedlist.m_next;
     100        if (n != &m_usedlist)
     101            VBOX_SLIRP_LOCK(n->m_mutex);
    91102        insque(pData, m,&m_usedlist);
    92         VBOX_SLIRP_UNLOCK(pData->m_usedlist_mutex);
     103        if (n != &m_usedlist)
     104            VBOX_SLIRP_LOCK(n->m_mutex);
     105        VBOX_SLIRP_UNLOCK(m->m_mutex);
    93106
    94107        m->m_flags = (flags | M_USEDLIST);
     
    117130        if (m->m_flags & M_USEDLIST) {
    118131           VBOX_SLIRP_LOCK(pData->m_usedlist_mutex);
     132           struct mbuf *p, *n;
     133           p = (m->m_prev);
     134           n = (m->m_next);
     135                VBOX_SLIRP_LOCK(m->m_next);
     136           if (n != NULL)
     137                VBOX_SLIRP_LOCK(n->m_next);
     138           if (p != NULL)
     139                VBOX_SLIRP_UNLOCK(p->m_next);
    119140           remque(pData, m);
     141           if (n != NULL)
     142                VBOX_SLIRP_UNLOCK(n->m_next);
     143           if (p != NULL)
     144                VBOX_SLIRP_LOCK(p->m_next);
    120145           VBOX_SLIRP_UNLOCK(pData->m_usedlist_mutex);
    121146        }
     
    130155        if (m->m_flags & M_DOFREE) {
    131156                u32ptr_done(pData, ptr_to_u32(pData, m), m);
     157                VBOX_SLIRP_UNLOCK(m->m_mutex);
     158                VBOX_SLIRP_LOCK_DESTROY(m->m_mutex);
    132159                free(m);
    133160#ifdef VBOX_WITH_SYNC_SLIRP
  • trunk/src/VBox/Devices/Network/slirp/mbuf.h

    r13897 r13940  
    7676        caddr_t mh_data;                /* Location of data */
    7777        int     mh_len;                 /* Amount of data in this mbuf */
     78#ifdef VBOX_WITH_SYNC_SLIRP
     79        RTSEMFASTMUTEX  mh_mutex;
     80#endif
    7881};
    7982
  • trunk/src/VBox/Devices/Network/slirp/slirp.c

    r13897 r13940  
    362362         * First, TCP sockets
    363363         */
     364#ifndef VBOX_WITH_SYNC_SLIRP
    364365        do_slowtimo = 0;
     366#endif
    365367        if (link_up) {
    366368                /*
     
    369371                 */
    370372                VBOX_SLIRP_LOCK(pData->tcb_mutex);
     373#ifndef VBOX_WITH_SYNC_SLIRP
    371374                do_slowtimo = ((tcb.so_next != &tcb) ||
    372375                               ((struct ipasfrag *)&ipq != u32_to_ptr(pData, ipq.next, struct ipasfrag *)));
     376#endif
    373377
    374378                so = tcb.so_next;
     
    389393                         * See if we need a tcp_fasttimo
    390394                         */
     395#ifndef VBOX_SLIRP_UNLOCK
    391396                        if (time_fasttimo == 0
    392397                            && so->so_tcpcb
    393398                            &&  so->so_tcpcb->t_flags & TF_DELACK)
    394399                           time_fasttimo = curtime; /* Flag when we want a fasttimo */
     400#endif
    395401
    396402                        /*
     
    409415                                goto before_loop_ends;
    410416                        }
    411 
     417#ifndef VBOX_WITH_SYNC_SLIRP
    412418                        /*
    413419                         * Set for writing sockets which are connecting
     
    427433                                UPD_NFDS(so->s);
    428434                        }
     435#endif
    429436
    430437                        /*
     
    465472                         * See if it's timed out
    466473                         */
     474#ifndef VBOX_WITH_SYNC_SLIRP
    467475                        if (so->so_expire) {
    468476                                if (so->so_expire <= curtime) {
     
    472480                                        do_slowtimo = 1; /* Let socket expire */
    473481                        }
     482#endif
    474483
    475484                        /*
     
    499508         */
    500509
     510#ifndef VBOX_WITH_SYNC_SLIRP
    501511        /*
    502512         * First, see the timeout needed by *timo
     
    528538                }
    529539        }
     540#endif
    530541        *pnfds = nfds;
    531542}
     
    542553         * See if anything has timed out
    543554         */
     555#ifndef VBOX_WITH_SYNC_SLIRP
    544556        if (link_up) {
    545557                if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
     
    553565                }
    554566        }
     567#endif
    555568
    556569        /*
     
    610623                        }
    611624
     625#ifndef VBOX_WITH_SYNC_SLIRP
    612626                        /*
    613627                         * Check sockets for writing
     
    655669                           */
    656670                        }
     671#endif
    657672
    658673                        /*
     
    914929    memcpy(client_ethaddr, ethaddr, ETH_ALEN);
    915930}
     931
     932#ifdef VBOX_WITH_SYNC_SLIRP
     933void slirp_fasttmr(PNATState pData)
     934{
     935        struct socket *so, *so_next;
     936        updtime(pData);
     937        time_fasttimo = 0;
     938#if 1
     939        VBOX_SLIRP_LOCK(pData->tcb_mutex);
     940        so = tcb.so_next;
     941        while(1) {
     942            if (so == &tcb) {
     943                VBOX_SLIRP_UNLOCK(pData->tcb_mutex);
     944                break;
     945            }
     946            so_next = so->so_next;
     947            VBOX_SLIRP_UNLOCK(pData->tcb_mutex);
     948                if (time_fasttimo == 0
     949                    && so->so_tcpcb
     950                    &&  so->so_tcpcb->t_flags & TF_DELACK)
     951                   time_fasttimo = curtime; /* Flag when we want a fasttimo */
     952            VBOX_SLIRP_LOCK(pData->tcb_mutex);
     953            so = so_next;
     954        }
     955#endif
     956        if (time_fasttimo) {
     957            tcp_fasttimo(pData);
     958            time_fasttimo = 0;
     959        }
     960}
     961
     962void slirp_slowtmr(PNATState pData)
     963{
     964        struct socket *so, *so_next;
     965        updtime(pData);
     966        do_slowtimo = 0;
     967#if 1
     968        VBOX_SLIRP_LOCK(pData->tcb_mutex);
     969        do_slowtimo = ((tcb.so_next != &tcb) ||
     970                               ((struct ipasfrag *)&ipq != u32_to_ptr(pData, ipq.next, struct ipasfrag *)));
     971
     972        VBOX_SLIRP_UNLOCK(pData->tcb_mutex);
     973
     974        VBOX_SLIRP_LOCK(pData->udb_mutex);
     975        so = udb.so_next;
     976        while(1) {
     977            if (so == &udb) {
     978                VBOX_SLIRP_UNLOCK(pData->udb_mutex);
     979                break;
     980            }
     981            so_next = so->so_next;
     982            VBOX_SLIRP_UNLOCK(pData->udb_mutex);
     983
     984            if (so->so_expire) {
     985                 if (so->so_expire <= curtime) {
     986                    udp_detach(pData, so);
     987                    goto before_loop_ends;
     988                 }
     989                do_slowtimo = 1;
     990            }
     991            before_loop_ends:
     992            VBOX_SLIRP_LOCK(pData->udb_mutex);
     993            so = so_next;
     994        }
     995#endif
     996        if (do_slowtimo) {
     997            tcp_slowtimo(pData);
     998            ip_slowtimo(pData);
     999            last_slowtimo = curtime;
     1000        }
     1001}
     1002
     1003/*selects open and ready sockets for write*/
     1004void slirp_send_fill(PNATState pData, int *pnfds, fd_set *writefds)
     1005{
     1006    struct socket *so, *so_next;
     1007    int nfds = *pnfds;
     1008
     1009    if (link_up == 0) return;
     1010
     1011    VBOX_SLIRP_LOCK(pData->tcb_mutex);
     1012    so = tcb.so_next;
     1013    while (1) {
     1014        if (so == &tcb) {
     1015            VBOX_SLIRP_UNLOCK(pData->tcb_mutex);
     1016            break;
     1017        }
     1018        so_next = so->so_next;
     1019        VBOX_SLIRP_UNLOCK(pData->tcb_mutex);
     1020
     1021        if (so->so_state & SS_NOFDREF || so->s == -1)
     1022               goto before_loop_ends;
     1023
     1024        if (so->so_state & SS_ISFCONNECTING) {
     1025                FD_SET(so->s, writefds);
     1026                UPD_NFDS(so->s);
     1027                goto before_loop_ends;
     1028        }
     1029
     1030        if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
     1031                FD_SET(so->s, writefds);
     1032                UPD_NFDS(so->s);
     1033        }
     1034
     1035        before_loop_ends:
     1036        VBOX_SLIRP_LOCK(pData->tcb_mutex);
     1037        so = so_next;
     1038    }
     1039    *pnfds = nfds;
     1040}
     1041/*triggers socket output */
     1042void slirp_send_trigger(PNATState pData, int *pnfds, fd_set *writefds)
     1043{
     1044    struct socket *so, *so_next;
     1045    int nfds = *pnfds;
     1046    int ret;
     1047
     1048    if (link_up == 0) return;
     1049
     1050    VBOX_SLIRP_LOCK(pData->tcb_mutex);
     1051    so = tcb.so_next;
     1052    while (1) {
     1053        if (so == &tcb) {
     1054            VBOX_SLIRP_UNLOCK(pData->tcb_mutex);
     1055            break;
     1056        }
     1057        so_next = so->so_next;
     1058        VBOX_SLIRP_UNLOCK(pData->tcb_mutex);
     1059        /*
     1060         * Check sockets for writing
     1061         */
     1062        if (FD_ISSET(so->s, writefds)) {
     1063          /*
     1064           * Check for non-blocking, still-connecting sockets
     1065           */
     1066          if (so->so_state & SS_ISFCONNECTING) {
     1067            /* Connected */
     1068            so->so_state &= ~SS_ISFCONNECTING;
     1069
     1070        /*
     1071         * This should be probably guarded by PROBE_CONN too. Anyway,
     1072         * we disable it on OS/2 because the below send call returns
     1073         * EFAULT which causes the opened TCP socket to close right
     1074         * after it has been opened and connected.
     1075         */
     1076#ifndef RT_OS_OS2
     1077        ret = send(so->s, (const char *)&ret, 0, 0);
     1078        if (ret < 0) {
     1079          /* XXXXX Must fix, zero bytes is a NOP */
     1080          if (errno == EAGAIN || errno == EWOULDBLOCK ||
     1081              errno == EINPROGRESS || errno == ENOTCONN)
     1082                    goto before_loop_ends;
     1083
     1084          /* else failed */
     1085          so->so_state = SS_NOFDREF;
     1086        }
     1087        /* else so->so_state &= ~SS_ISFCONNECTING; */
     1088#endif
     1089
     1090          /*
     1091           * Continue tcp_input
     1092           */
     1093          tcp_input(pData, (struct mbuf *)NULL, sizeof(struct ip), so);
     1094          /* continue; */
     1095        } else
     1096          ret = sowrite(pData, so);
     1097        /*
     1098         * XXXXX If we wrote something (a lot), there
     1099         * could be a need for a window update.
     1100         * In the worst case, the remote will send
     1101         * a window probe to get things going again
     1102         */
     1103        }
     1104
     1105        before_loop_ends:
     1106        VBOX_SLIRP_LOCK(pData->tcb_mutex);
     1107        so = so_next;
     1108    }
     1109}
     1110#endif
  • trunk/src/VBox/Devices/Network/slirp/tcp_subr.c

    r13783 r13940  
    541541        /*we use this field to identify cache socket to lock/unlock*/
    542542        so->so_type = IPPROTO_TCP;
     543        slirp_socket_created(pData->pvUser);
    543544#endif
    544545
  • trunk/src/VBox/Devices/Network/slirp/udp.c

    r13783 r13940  
    385385#ifdef VBOX_WITH_SYNC_SLIRP
    386386  so->so_type = IPPROTO_UDP;
     387  slirp_socket_created(pData->pvUser);
    387388#endif
    388389  return(so->s);
     
    708709
    709710        so->so_state = SS_ISFCONNECTED;
    710 
     711#ifdef VBOX_WITH_SYNC_SLIRP
     712        slirp_socket_created(pData->pvUser);
     713#endif
    711714        return so;
    712715}
Note: See TracChangeset for help on using the changeset viewer.

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