VirtualBox

Changeset 28711 in vbox


Ignore:
Timestamp:
Apr 25, 2010 7:01:24 PM (15 years ago)
Author:
vboxsync
Message:

IntNet,++: Implemented sending frames in ring-0 (disabled).

Location:
trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/intnet.h

    r28706 r28711  
    860860/**
    861861 * Request buffer for IntNetR0IfGetRing3BufferReq /
    862  * VMMR0_DO_INTNET_IF_GET_RING3_BUFFER.
     862 * VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS.
    863863 * @see IntNetR0IfGetRing3Buffer.
    864864 */
    865 typedef struct INTNETIFGETRING3BUFFERREQ
     865typedef struct INTNETIFGETBUFFERPTRSREQ
    866866{
    867867    /** The request header. */
     
    872872    /** Handle to the interface. */
    873873    INTNETIFHANDLE  hIf;
    874     /** The pointer to the ring3 buffer. (output) */
     874    /** The pointer to the ring-3 buffer. (output) */
    875875    R3PTRTYPE(PINTNETBUF)   pRing3Buf;
    876 } INTNETIFGETRING3BUFFERREQ;
     876    /** The pointer to the ring-0 buffer. (output) */
     877    R0PTRTYPE(PINTNETBUF)   pRing0Buf;
     878} INTNETIFGETBUFFERPTRSREQ;
    877879/** Pointer to an IntNetR0IfGetRing3BufferReq /
    878  *  VMMR0_DO_INTNET_IF_GET_RING3_BUFFER request buffer. */
    879 typedef INTNETIFGETRING3BUFFERREQ *PINTNETIFGETRING3BUFFERREQ;
    880 
    881 INTNETR0DECL(int) IntNetR0IfGetRing3BufferReq(PSUPDRVSESSION pSession, PINTNETIFGETRING3BUFFERREQ pReq);
     880 *  VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS request buffer. */
     881typedef INTNETIFGETBUFFERPTRSREQ *PINTNETIFGETBUFFERPTRSREQ;
     882
     883INTNETR0DECL(int) IntNetR0IfGetBufferPtrsReq(PSUPDRVSESSION pSession, PINTNETIFGETBUFFERPTRSREQ pReq);
    882884
    883885
     
    10071009INTNETR0DECL(uint32_t) IntNetR0GetNetworkCount(void);
    10081010
    1009 INTNETR0DECL(int) IntNetR0IfClose(             INTNETIFHANDLE hIf, PSUPDRVSESSION pSession);
    1010 INTNETR0DECL(int) IntNetR0IfGetRing0Buffer(    INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, PINTNETBUF *ppRing0Buf);
    1011 INTNETR0DECL(int) IntNetR0IfGetRing3Buffer(    INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, R3PTRTYPE(PINTNETBUF) *ppRing3Buf);
    1012 INTNETR0DECL(int) IntNetR0IfSetPromiscuousMode(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, bool fPromiscuous);
    1013 INTNETR0DECL(int) IntNetR0IfSetMacAddress(     INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, PCRTMAC pMac);
    1014 INTNETR0DECL(int) IntNetR0IfSetActive(         INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, bool fActive);
    1015 INTNETR0DECL(int) IntNetR0IfSend(              INTNETIFHANDLE hIf, PSUPDRVSESSION pSession);
    1016 INTNETR0DECL(int) IntNetR0IfWait(              INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, uint32_t cMillies);
     1011INTNETR0DECL(int)       IntNetR0IfClose(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession);
     1012INTNETR0DECL(int)       IntNetR0IfGetBufferPtrs(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession,
     1013                                                R3PTRTYPE(PINTNETBUF) *ppRing3Buf, R0PTRTYPE(PINTNETBUF) *ppRing0Buf);
     1014INTNETR0DECL(int)       IntNetR0IfSetPromiscuousMode(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, bool fPromiscuous);
     1015INTNETR0DECL(int)       IntNetR0IfSetMacAddress(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, PCRTMAC pMac);
     1016INTNETR0DECL(int)       IntNetR0IfSetActive(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, bool fActive);
     1017INTNETR0DECL(int)       IntNetR0IfSend(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession);
     1018INTNETR0DECL(int)       IntNetR0IfWait(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, uint32_t cMillies);
    10171019
    10181020/** @} */
  • trunk/include/VBox/vmm.h

    r28706 r28711  
    329329    /** Call IntNetR0IfClose(). */
    330330    VMMR0_DO_INTNET_IF_CLOSE,
    331     /** Call IntNetR0IfGetRing3Buffer(). */
    332     VMMR0_DO_INTNET_IF_GET_RING3_BUFFER,
     331    /** Call IntNetR0IfGetBufferPtrs(). */
     332    VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS,
    333333    /** Call IntNetR0IfSetPromiscuousMode(). */
    334334    VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE,
  • trunk/src/VBox/Devices/Network/DrvIntNet.cpp

    r28339 r28711  
    8585     * Can (in theory at least) be NULL. */
    8686    R3PTRTYPE(PPDMINETWORKCONFIG)   pIAboveConfigR3;
    87     /** Pointer to the driver instance. */
     87    /** Pointer to the driver instance (ring-3). */
    8888    PPDMDRVINSR3                    pDrvInsR3;
    89     /** Pointer to the communication buffer. */
     89    /** Pointer to the communication buffer (ring-3). */
    9090    R3PTRTYPE(PINTNETBUF)           pBufR3;
    9191    /** Ring-3 base interface for the ring-0 context. */
     
    9797    /** The network interface for the ring-0 context. */
    9898    PDMINETWORKUPR0                 INetworkUpR0;
    99     /** Pointer to the driver instance. */
     99    /** Pointer to the driver instance (ring-0). */
    100100    PPDMDRVINSR0                    pDrvInsR0;
    101     RTR0PTR                         R0PtrAlignment;
     101    /** Pointer to the communication buffer (ring-0). */
     102    R0PTRTYPE(PINTNETBUF)           pBufR0;
    102103
    103104    /** The network interface for the raw-mode context. */
     
    132133    /** Set if the transmit thread the one busy transmitting. */
    133134    bool volatile                   fXmitOnXmitThread;
     135    /** The xmit thread should process the ring ASAP. */
     136    bool                            fXmitProcessRing;
    134137    /** Set if data transmission should start immediately and deactivate
    135138     * as late as possible. */
    136139    bool                            fActivateEarlyDeactivateLate;
    137140    /** Padding. */
    138     bool                            afReserved[HC_ARCH_BITS == 64 ? 4 : 4];
     141    bool                            afReserved[HC_ARCH_BITS == 64 ? 3 : 3];
     142    /** Scratch space for holding the ring-0 scatter / gather descriptor.
     143     * The PDMSCATTERGATHER::fFlags member is used to indicate whether it is in
     144     * use or not.  Always accessed while owning the XmitLock. */
     145    union
     146    {
     147        PDMSCATTERGATHER            Sg;
     148        uint8_t                     padding[8 * sizeof(RTUINTPTR)];
     149    }                               u;
    139150    /** The network name. */
    140151    char                            szNetwork[INTNET_MAX_NETWORK_NAME];
     
    144155    /** Number of GSO packets recevied. */
    145156    STAMCOUNTER                     StatReceivedGso;
     157    /** Number of packets send from ring-0. */
     158    STAMCOUNTER                     StatSentR0;
    146159#ifdef VBOX_WITH_STATISTICS
    147160    /** Profiling packet transmit runs. */
     
    149162    /** Profiling packet receive runs. */
    150163    STAMPROFILEADV                  StatReceive;
     164    /** The number of times we've had to wake up the xmit thread to contine the
     165     *  ring-0 job. */
     166    STAMCOUNTER                     StatXmitWakeupR0;
     167    /** The number of times we've had to wake up the xmit thread to contine the
     168     *  ring-3 job. */
     169    STAMCOUNTER                     StatXmitWakeupR3;
     170    /** The times the xmit thread has been told to process the ring. */
     171    STAMCOUNTER                     StatXmitProcessRing;
    151172#endif /* VBOX_WITH_STATISTICS */
    152173#ifdef LOG_ENABLED
     
    225246
    226247/**
     248 * Helper for signalling the xmit thread.
     249 *
     250 * @returns VERR_TRY_AGAIN (convenience).
     251 * @param   pThis               The instance data..
     252 */
     253DECLINLINE(int) drvIntNetSignalXmit(PDRVINTNET pThis)
     254{
     255    /// @todo if (!ASMAtomicXchgBool(&pThis->fXmitSignalled, true)) - needs careful optimizing.
     256    {
     257        int rc = SUPSemEventSignal(pThis->pSupDrvSession, pThis->hXmitEvt);
     258        AssertRC(rc);
     259        STAM_COUNTER_INC(&pThis->CTX_SUFF(StatXmitWakeup));
     260    }
     261    return VERR_TRY_AGAIN;
     262}
     263
     264
     265/**
     266 * Helper for processing the ring-0 consumer side of the xmit ring.
     267 *
     268 * The caller MUST own the xmit lock.
     269 *
     270 * @returns Status code from IntNetR0IfSend, except for VERR_TRY_AGAIN.
     271 * @param   pThis               The instance data..
     272 */
     273DECLINLINE(int) drvIntNetProcessXmit(PDRVINTNET pThis)
     274{
     275    Assert(PDMCritSectIsOwner(&pThis->XmitLock));
     276
     277#ifdef IN_RING3
     278    INTNETIFSENDREQ SendReq;
     279    SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     280    SendReq.Hdr.cbReq = sizeof(SendReq);
     281    SendReq.pSession = NIL_RTR0PTR;
     282    SendReq.hIf = pThis->hIf;
     283    int rc = PDMDrvHlpSUPCallVMMR0Ex(pThis->pDrvInsR3, VMMR0_DO_INTNET_IF_SEND, &SendReq, sizeof(SendReq));
     284#else
     285    int rc = IntNetR0IfSend(pThis->hIf, pThis->pSupDrvSession);
     286    if (rc == VERR_TRY_AGAIN)
     287    {
     288        ASMAtomicUoWriteBool(&pThis->fXmitProcessRing, true);
     289        drvIntNetSignalXmit(pThis);
     290        rc = VINF_SUCCESS;
     291    }
     292#endif
     293    return rc;
     294}
     295
     296
     297
     298/**
    227299 * @interface_method_impl{PDMINETWORKUP,pfnBeginXmit}
    228300 */
     
    230302{
    231303    PDRVINTNET pThis = RT_FROM_MEMBER(pInterface, DRVINTNET, CTX_SUFF(INetworkUp));
    232 #if !defined(IN_RING3)
    233     int rc = VERR_SEM_BUSY;
     304#ifndef IN_RING3
    234305    Assert(!fOnWorkerThread);
    235 #elif 1
     306#endif
     307
    236308    int rc = PDMCritSectTryEnter(&pThis->XmitLock);
    237 #else
    238     int rc = fOnWorkerThread ? PDMCritSectTryEnter(&pThis->XmitLock) : VERR_SEM_BUSY;
    239 #endif
    240309    if (RT_SUCCESS(rc))
    241310    {
     
    249318    {
    250319        /** @todo Does this actually make sense if the other dude is an EMT and so
    251          *        forth?  I seriously think this is ring-0 only... */
     320         *        forth?  I seriously think this is ring-0 only...
     321         * We might end up waking up the xmit thread unnecessarily here, even when in
     322         * ring-0... This needs some more thought and opitmizations when the ring-0 bits
     323         * are working. */
     324#ifdef IN_RING3
    252325        if (    !fOnWorkerThread
    253326            /*&&  !ASMAtomicUoReadBool(&pThis->fXmitOnXmitThread)
     
    258331        }
    259332        rc = VERR_TRY_AGAIN;
     333#else  /* IN_RING0 */
     334        rc = drvIntNetSignalXmit(pThis);
     335#endif /* IN_RING0 */
    260336    }
    261337    return rc;
     
    274350    Assert(PDMCritSectIsOwner(&pThis->XmitLock));
    275351
     352    /*
     353     * Allocate a S/G descriptor.
     354     * This shouldn't normally fail as the NICs usually won't allocate more
     355     * than one buffer at a time and the SG gets freed on sending.
     356     */
    276357#ifdef IN_RING3
    277     /*
    278      * Allocate a S/G buffer.
    279      */
    280358    PPDMSCATTERGATHER pSgBuf = (PPDMSCATTERGATHER)RTMemCacheAlloc(pThis->hSgCache);
    281     if (pSgBuf)
    282     {
    283         PINTNETHDR pHdr;
     359    if (!pSgBuf)
     360        return VERR_NO_MEMORY;
     361#else
     362    PPDMSCATTERGATHER pSgBuf = &pThis->u.Sg;
     363    if (RT_UNLIKELY(pSgBuf->fFlags != 0))
     364        return drvIntNetSignalXmit(pThis);
     365#endif
     366
     367    /*
     368     * Allocate room in the ring buffer.
     369     *
     370     * In ring-3 we may have to process the xmit ring before there is
     371     * sufficient buffer space since we might've stacked up a few frames to the
     372     * trunk while in ring-0.  (There is not point of doing this in ring-0.)
     373     */
     374    PINTNETHDR pHdr;
     375    if (pGso)
     376        rc = INTNETRingAllocateGsoFrame(&pThis->CTX_SUFF(pBuf)->Send, (uint32_t)cbMin, pGso,
     377                                        &pHdr, &pSgBuf->aSegs[0].pvSeg);
     378    else
     379        rc = INTNETRingAllocateFrame(&pThis->CTX_SUFF(pBuf)->Send, (uint32_t)cbMin,
     380                                     &pHdr, &pSgBuf->aSegs[0].pvSeg);
     381#ifdef IN_RING3
     382    if (    RT_FAILURE(rc)
     383        &&  pThis->CTX_SUFF(pBuf)->cbSend >= cbMin * 2 + sizeof(INTNETHDR))
     384    {
     385        drvIntNetProcessXmit(pThis);
    284386        if (pGso)
    285             rc = INTNETRingAllocateGsoFrame(&pThis->pBufR3->Send, (uint32_t)cbMin, pGso,
     387            rc = INTNETRingAllocateGsoFrame(&pThis->CTX_SUFF(pBuf)->Send, (uint32_t)cbMin, pGso,
    286388                                            &pHdr, &pSgBuf->aSegs[0].pvSeg);
    287389        else
    288             rc = INTNETRingAllocateFrame(&pThis->pBufR3->Send, (uint32_t)cbMin,
     390            rc = INTNETRingAllocateFrame(&pThis->CTX_SUFF(pBuf)->Send, (uint32_t)cbMin,
    289391                                         &pHdr, &pSgBuf->aSegs[0].pvSeg);
    290 
    291 #if 1 /** @todo implement VERR_TRY_AGAIN once this moves to EMT?  -- Not needed unless we make the consumer side (ring-0) asynchronous.  */
    292         if (    RT_FAILURE(rc)
    293             &&  pThis->pBufR3->cbSend >= cbMin * 2 + sizeof(INTNETHDR))
    294         {
    295             INTNETIFSENDREQ SendReq;
    296             SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
    297             SendReq.Hdr.cbReq = sizeof(SendReq);
    298             SendReq.pSession = NIL_RTR0PTR;
    299             SendReq.hIf = pThis->hIf;
    300             PDMDrvHlpSUPCallVMMR0Ex(pThis->pDrvInsR3, VMMR0_DO_INTNET_IF_SEND, &SendReq, sizeof(SendReq));
    301 
    302             if (pGso)
    303                 rc = INTNETRingAllocateGsoFrame(&pThis->pBufR3->Send, (uint32_t)cbMin, pGso,
    304                                                 &pHdr, &pSgBuf->aSegs[0].pvSeg);
    305             else
    306                 rc = INTNETRingAllocateFrame(&pThis->pBufR3->Send, (uint32_t)cbMin,
    307                                              &pHdr, &pSgBuf->aSegs[0].pvSeg);
    308         }
     392    }
    309393#endif
    310         if (RT_SUCCESS(rc))
    311         {
    312             pSgBuf->fFlags          = PDMSCATTERGATHER_FLAGS_MAGIC | PDMSCATTERGATHER_FLAGS_OWNER_1;
    313             pSgBuf->cbUsed          = 0;
    314             pSgBuf->cbAvailable     = cbMin;
    315             pSgBuf->pvAllocator     = pHdr;
    316             pSgBuf->pvUser          = pGso ? (PPDMNETWORKGSO)pSgBuf->aSegs[0].pvSeg - 1 : NULL;
    317             pSgBuf->cSegs           = 1;
    318             pSgBuf->aSegs[0].cbSeg  = cbMin;
    319 
    320             *ppSgBuf = pSgBuf;
    321             return VINF_SUCCESS;
    322         }
    323 
     394    if (RT_SUCCESS(rc))
     395    {
    324396        /*
    325          * Arm the try again stuff.
     397         * Set up the S/G descriptor and return successfully.
    326398         */
    327 /** @todo        if (pThis->pBufR3->cbSend >= cbMin * 2 + sizeof(INTNETHDR))
    328             rc = VERR_TRY_AGAIN;
    329         else */
    330             rc = VERR_NO_MEMORY;
    331 
    332         RTMemCacheFree(pThis->hSgCache, pSgBuf);
     399        pSgBuf->fFlags          = PDMSCATTERGATHER_FLAGS_MAGIC | PDMSCATTERGATHER_FLAGS_OWNER_1;
     400        pSgBuf->cbUsed          = 0;
     401        pSgBuf->cbAvailable     = cbMin;
     402        pSgBuf->pvAllocator     = pHdr;
     403        pSgBuf->pvUser          = pGso ? (PPDMNETWORKGSO)pSgBuf->aSegs[0].pvSeg - 1 : NULL;
     404        pSgBuf->cSegs           = 1;
     405        pSgBuf->aSegs[0].cbSeg  = cbMin;
     406
     407        *ppSgBuf = pSgBuf;
     408        return VINF_SUCCESS;
     409    }
     410
     411#ifdef IN_RING3
     412    /*
     413     * If the above fails, then we're really out of space.  There are nobody
     414     * competing with us here because of the xmit lock.
     415     */
     416    rc = VERR_NO_MEMORY;
     417    RTMemCacheFree(pThis->hSgCache, pSgBuf);
     418
     419#else  /* IN_RING0 */
     420    /*
     421     * If the request is reasonable, kick the xmit thread and tell it to
     422     * process the xmit ring ASAP.
     423     */
     424    if (pThis->CTX_SUFF(pBuf)->cbSend >= cbMin * 2 + sizeof(INTNETHDR))
     425    {
     426        pThis->fXmitProcessRing = true;
     427        rc = drvIntNetSignalXmit(pThis);
    333428    }
    334429    else
    335430        rc = VERR_NO_MEMORY;
    336     /** @todo implement VERR_TRY_AGAIN  */
     431    pSgBuf->fFlags = 0;
     432#endif /* IN_RING0 */
    337433    return rc;
    338 
    339 #else   /* !IN_RING3 */
    340     rc = VERR_TRY_AGAIN;
    341     return rc;
    342 #endif  /* !IN_RING3 */
    343434}
    344435
     
    351442    PDRVINTNET  pThis = RT_FROM_MEMBER(pInterface, DRVINTNET, CTX_SUFF(INetworkUp));
    352443    PINTNETHDR  pHdr  = (PINTNETHDR)pSgBuf->pvAllocator;
     444#ifdef IN_RING0
     445    Assert(pSgBuf == &pThis->u.Sg);
     446#endif
    353447    Assert(pSgBuf->fFlags == (PDMSCATTERGATHER_FLAGS_MAGIC | PDMSCATTERGATHER_FLAGS_OWNER_1));
    354448    Assert(pSgBuf->cbUsed <= pSgBuf->cbAvailable);
     
    357451    Assert(PDMCritSectIsOwner(&pThis->XmitLock));
    358452
    359 #ifdef IN_RING3
    360453    /** @todo LATER: try unalloc the frame. */
    361454    pHdr->u16Type = INTNETHDR_TYPE_PADDING;
    362     INTNETRingCommitFrame(&pThis->pBufR3->Send, pHdr);
    363 
     455    INTNETRingCommitFrame(&pThis->CTX_SUFF(pBuf)->Send, pHdr);
     456
     457#ifdef IN_RING3
    364458    RTMemCacheFree(pThis->hSgCache, pSgBuf);
     459#else
     460    pSgBuf->fFlags = 0;
     461#endif
    365462    return VINF_SUCCESS;
    366 #else
    367     return VERR_INTERNAL_ERROR_5;
    368 #endif
    369463}
    370464
     
    386480        STAM_COUNTER_INC(&pThis->StatSentGso);
    387481
     482    /*
     483     * Commit the frame and push it thru the switch.
     484     */
     485    PINTNETHDR pHdr = (PINTNETHDR)pSgBuf->pvAllocator;
     486    INTNETRingCommitFrameEx(&pThis->CTX_SUFF(pBuf)->Send, pHdr, pSgBuf->cbUsed);
     487    int rc = drvIntNetProcessXmit(pThis);
     488    STAM_PROFILE_STOP(&pThis->StatTransmit, a);
     489
     490    /*
     491     * Free the descriptor and return.
     492     */
    388493#ifdef IN_RING3
    389     /*
    390      * Commit the frame and push it thru the switch.
    391      */
    392     PINTNETHDR pHdr = (PINTNETHDR)pSgBuf->pvAllocator;
    393     INTNETRingCommitFrameEx(&pThis->pBufR3->Send, pHdr, pSgBuf->cbUsed);
    394 
    395     INTNETIFSENDREQ SendReq;
    396     SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
    397     SendReq.Hdr.cbReq = sizeof(SendReq);
    398     SendReq.pSession = NIL_RTR0PTR;
    399     SendReq.hIf = pThis->hIf;
    400     PDMDrvHlpSUPCallVMMR0Ex(pThis->pDrvInsR3, VMMR0_DO_INTNET_IF_SEND, &SendReq, sizeof(SendReq));
    401 
    402494    RTMemCacheFree(pThis->hSgCache, pSgBuf);
    403 
    404     STAM_PROFILE_STOP(&pThis->StatTransmit, a);
    405     return VINF_SUCCESS;
    406495#else
    407     return VERR_INTERNAL_ERROR_4;
     496    STAM_REL_COUNTER_INC(&pThis->StatSentR0);
     497    pSgBuf->fFlags = 0;
    408498#endif
     499    return rc;
    409500}
    410501
     
    427518{
    428519    PDRVINTNET pThis = RT_FROM_MEMBER(pInterface, DRVINTNET, CTX_SUFF(INetworkUp));
     520
    429521#ifdef IN_RING3
    430522    INTNETIFSETPROMISCUOUSMODEREQ Req;
     
    435527    Req.fPromiscuous    = fPromiscuous;
    436528    int rc = PDMDrvHlpSUPCallVMMR0Ex(pThis->pDrvInsR3, VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE, &Req, sizeof(Req));
     529#else  /* IN_RING0 */
     530    int rc = IntNetR0IfSetPromiscuousMode(pThis->hIf, pThis->pSupDrvSession, fPromiscuous);
     531#endif /* IN_RING0 */
     532
    437533    LogFlow(("drvIntNetUp_SetPromiscuousMode: fPromiscuous=%RTbool\n", fPromiscuous));
    438534    AssertRC(rc);
    439 #else
    440     /** @todo  */
    441     AssertFailed();
    442 #endif
    443535}
    444536
     
    485577    {
    486578        /*
     579         * Transmit any pending packets.
     580         */
     581        /** @todo Optimize this. We shouldn't call pfnXmitPending unless asked for.
     582         *        Also there is no need to call drvIntNetProcessXmit if we also
     583         *        called pfnXmitPending and send one or more frames. */
     584        if (ASMAtomicXchgBool(&pThis->fXmitProcessRing, false))
     585        {
     586            STAM_COUNTER_INC(&pThis->StatXmitProcessRing);
     587            PDMCritSectEnter(&pThis->XmitLock, VERR_IGNORED);
     588            drvIntNetProcessXmit(pThis);
     589            PDMCritSectLeave(&pThis->XmitLock);
     590        }
     591
     592        pThis->pIAboveNet->pfnXmitPending(pThis->pIAboveNet);
     593
     594        if (ASMAtomicXchgBool(&pThis->fXmitProcessRing, false))
     595        {
     596            STAM_COUNTER_INC(&pThis->StatXmitProcessRing);
     597            PDMCritSectEnter(&pThis->XmitLock, VERR_IGNORED);
     598            drvIntNetProcessXmit(pThis);
     599            PDMCritSectLeave(&pThis->XmitLock);
     600        }
     601
     602        /*
    487603         * Block until we've got something to send or is supposed
    488604         * to leave the running state.
     
    493609            break;
    494610
    495         /*
    496          * Transmit any pending packets.
    497          */
    498         pThis->pIAboveNet->pfnXmitPending(pThis->pIAboveNet);
    499611   }
    500612
     
    551663     */
    552664    STAM_PROFILE_ADV_START(&pThis->StatReceive, a);
    553     PINTNETBUF      pBuf     = pThis->pBufR3;
     665    PINTNETBUF      pBuf     = pThis->CTX_SUFF(pBuf);
    554666    PINTNETRINGBUF  pRingBuf = &pBuf->Recv;
    555667    for (;;)
     
    14041516     * Get default buffer.
    14051517     */
    1406     INTNETIFGETRING3BUFFERREQ GetRing3BufferReq;
    1407     GetRing3BufferReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
    1408     GetRing3BufferReq.Hdr.cbReq = sizeof(GetRing3BufferReq);
    1409     GetRing3BufferReq.pSession = NIL_RTR0PTR;
    1410     GetRing3BufferReq.hIf = pThis->hIf;
    1411     GetRing3BufferReq.pRing3Buf = NULL;
    1412     rc = PDMDrvHlpSUPCallVMMR0Ex(pDrvIns, VMMR0_DO_INTNET_IF_GET_RING3_BUFFER, &GetRing3BufferReq, sizeof(GetRing3BufferReq));
     1518    INTNETIFGETBUFFERPTRSREQ GetBufferPtrsReq;
     1519    GetBufferPtrsReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     1520    GetBufferPtrsReq.Hdr.cbReq = sizeof(GetBufferPtrsReq);
     1521    GetBufferPtrsReq.pSession = NIL_RTR0PTR;
     1522    GetBufferPtrsReq.hIf = pThis->hIf;
     1523    GetBufferPtrsReq.pRing3Buf = NULL;
     1524    GetBufferPtrsReq.pRing0Buf = NULL;
     1525    rc = PDMDrvHlpSUPCallVMMR0Ex(pDrvIns, VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS, &GetBufferPtrsReq, sizeof(GetBufferPtrsReq));
    14131526    if (RT_FAILURE(rc))
    14141527        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
    14151528                                   N_("Failed to get ring-3 buffer for the newly created interface to '%s'"), pThis->szNetwork);
    1416     AssertRelease(VALID_PTR(GetRing3BufferReq.pRing3Buf));
    1417     pThis->pBufR3 = GetRing3BufferReq.pRing3Buf;
     1529    AssertRelease(VALID_PTR(GetBufferPtrsReq.pRing3Buf));
     1530    pThis->pBufR3 = GetBufferPtrsReq.pRing3Buf;
     1531    pThis->pBufR0 = GetBufferPtrsReq.pRing0Buf;
    14181532
    14191533    /*
     
    14281542    PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatReceivedGso,            "Packets/Received-Gso", STAMUNIT_COUNT, "The GSO portion of the received packets.");
    14291543    PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatSentGso,                "Packets/Sent-Gso",     STAMUNIT_COUNT, "The GSO portion of the sent packets.");
     1544    PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatSentR0,                 "Packets/Sent-R0",      STAMUNIT_COUNT, "The ring-0 portion of the sent packets.");
    14301545
    14311546    PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->pBufR3->cStatLost,          "Packets/Lost",         STAMUNIT_COUNT, "Number of lost packets.");
     
    14361551    PDMDrvHlpSTAMRegProfileAdv(pDrvIns, &pThis->StatReceive,             "Receive",     STAMUNIT_TICKS_PER_CALL, "Profiling packet receive runs.");
    14371552    PDMDrvHlpSTAMRegProfile(pDrvIns, &pThis->StatTransmit,               "Transmit",    STAMUNIT_TICKS_PER_CALL, "Profiling packet transmit runs.");
     1553    PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitWakeupR0,           "XmitWakeup-R0",        STAMUNIT_COUNT, "Xmit thread wakeups from ring-0.");
     1554    PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitWakeupR3,           "XmitWakeup-R3",        STAMUNIT_COUNT, "Xmit thread wakeups from ring-3.");
     1555    PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitProcessRing,        "XmitProcessRing",      STAMUNIT_COUNT, "Time xmit thread was told to process the ring.");
    14381556#endif
    14391557
  • trunk/src/VBox/Devices/Network/SrvIntNetR0.cpp

    r28706 r28711  
    33703370 * @param   hIf             The interface handle.
    33713371 * @param   pSession        The caller's session.
    3372  * @param   ppRing3Buf      Where to store the address of the ring-3 mapping.
    3373  */
    3374 INTNETR0DECL(int) IntNetR0IfGetRing3Buffer(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, R3PTRTYPE(PINTNETBUF) *ppRing3Buf)
    3375 {
    3376     LogFlow(("IntNetR0IfGetRing3Buffer: hIf=%RX32 ppRing3Buf=%p\n", hIf, ppRing3Buf));
     3372 * @param   ppRing3Buf      Where to store the address of the ring-3 mapping
     3373 *                          (optional).
     3374 * @param   ppRing0Buf      Where to store the address of the ring-0 mapping
     3375 *                          (optional).
     3376 */
     3377INTNETR0DECL(int)       IntNetR0IfGetBufferPtrs(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession,
     3378                                                R3PTRTYPE(PINTNETBUF) *ppRing3Buf, R0PTRTYPE(PINTNETBUF) *ppRing0Buf)
     3379{
     3380    LogFlow(("IntNetR0IfGetBufferPtrs: hIf=%RX32 ppRing3Buf=%p ppRing0Buf=%p\n", hIf, ppRing3Buf, ppRing0Buf));
    33773381
    33783382    /*
     
    33833387    AssertReturn(pIntNet->u32Magic, VERR_INVALID_MAGIC);
    33843388
    3385     AssertPtrReturn(ppRing3Buf, VERR_INVALID_PARAMETER);
    3386     *ppRing3Buf = 0;
     3389    AssertPtrNullReturn(ppRing3Buf, VERR_INVALID_PARAMETER);
     3390    AssertPtrNullReturn(ppRing0Buf, VERR_INVALID_PARAMETER);
     3391    if (ppRing3Buf)
     3392        *ppRing3Buf = 0;
     3393    if (ppRing0Buf)
     3394        *ppRing0Buf = 0;
     3395
    33873396    PINTNETIF pIf = (PINTNETIF)RTHandleTableLookupWithCtx(pIntNet->hHtIfs, hIf, pSession);
    33883397    if (!pIf)
     
    33973406    if (RT_SUCCESS(rc))
    33983407    {
    3399         *ppRing3Buf = pIf->pIntBufR3;
     3408        if (ppRing3Buf)
     3409            *ppRing3Buf = pIf->pIntBufR3;
     3410        if (ppRing0Buf)
     3411            *ppRing0Buf = (R0PTRTYPE(PINTNETBUF))pIf->pIntBuf; /* tstIntNetR0 mess */
    34003412
    34013413        rc = RTSemMutexRelease(pIntNet->hMtxCreateOpenDestroy);
     
    34033415
    34043416    intnetR0IfRelease(pIf, pSession);
    3405     LogFlow(("IntNetR0IfGetRing3Buffer: returns %Rrc *ppRing3Buf=%p\n", rc, *ppRing3Buf));
     3417    LogFlow(("IntNetR0IfGetBufferPtrs: returns %Rrc *ppRing3Buf=%p *ppRing0Buf=%p\n",
     3418             rc, ppRing3Buf ? *ppRing3Buf : NULL, ppRing0Buf ? *ppRing0Buf : NULL));
    34063419    return rc;
    34073420}
     
    34093422
    34103423/**
    3411  * VMMR0 request wrapper for IntNetR0IfGetRing3Buffer.
     3424 * VMMR0 request wrapper for IntNetR0IfGetBufferPtrs.
    34123425 *
    34133426 * @returns see IntNetR0IfGetRing3Buffer.
     
    34153428 * @param   pReq            The request packet.
    34163429 */
    3417 INTNETR0DECL(int) IntNetR0IfGetRing3BufferReq(PSUPDRVSESSION pSession, PINTNETIFGETRING3BUFFERREQ pReq)
     3430INTNETR0DECL(int) IntNetR0IfGetBufferPtrsReq(PSUPDRVSESSION pSession, PINTNETIFGETBUFFERPTRSREQ pReq)
    34183431{
    34193432    if (RT_UNLIKELY(pReq->Hdr.cbReq != sizeof(*pReq)))
    34203433        return VERR_INVALID_PARAMETER;
    3421     return IntNetR0IfGetRing3Buffer(pReq->hIf, pSession, &pReq->pRing3Buf);
    3422 }
    3423 
    3424 
    3425 /**
    3426  * Gets the ring-0 address of the current buffer.
    3427  *
    3428  * @returns VBox status code.
    3429  * @param   hIf             The interface handle.
    3430  * @param   pSession        The caller's session.
    3431  * @param   ppRing0Buf      Where to store the address of the ring-3 mapping.
    3432  */
    3433 INTNETR0DECL(int) IntNetR0IfGetRing0Buffer(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, PINTNETBUF *ppRing0Buf)
    3434 {
    3435     LogFlow(("IntNetR0IfGetRing0Buffer: hIf=%RX32 ppRing0Buf=%p\n", hIf, ppRing0Buf));
    3436 
    3437     /*
    3438      * Validate input.
    3439      */
    3440     PINTNET pIntNet = g_pIntNet;
    3441     AssertPtrReturn(pIntNet, VERR_INVALID_PARAMETER);
    3442     AssertReturn(pIntNet->u32Magic, VERR_INVALID_MAGIC);
    3443 
    3444     AssertPtrReturn(ppRing0Buf, VERR_INVALID_PARAMETER);
    3445     *ppRing0Buf = NULL;
    3446     PINTNETIF pIf = (PINTNETIF)RTHandleTableLookupWithCtx(pIntNet->hHtIfs, hIf, pSession);
    3447     if (!pIf)
    3448         return VERR_INVALID_HANDLE;
    3449 
    3450     /*
    3451      * Grab the lock and get the data.
    3452      * ASSUMES that the handle isn't closed while we're here.
    3453      */
    3454     int rc = RTSemMutexRequest(pIntNet->hMtxCreateOpenDestroy, RT_INDEFINITE_WAIT);
    3455     if (RT_SUCCESS(rc))
    3456     {
    3457         *ppRing0Buf = pIf->pIntBuf;
    3458 
    3459         rc = RTSemMutexRelease(pIntNet->hMtxCreateOpenDestroy);
    3460     }
    3461     intnetR0IfRelease(pIf, pSession);
    3462     LogFlow(("IntNetR0IfGetRing0Buffer: returns %Rrc *ppRing0Buf=%p\n", rc, *ppRing0Buf));
    3463     return rc;
     3434    return IntNetR0IfGetBufferPtrs(pReq->hIf, pSession, &pReq->pRing3Buf, &pReq->pRing0Buf);
    34643435}
    34653436
  • trunk/src/VBox/Devices/Network/testcase/tstIntNet-1.cpp

    r28025 r28711  
    821821         * Get the ring-3 address of the shared interface buffer.
    822822         */
    823         INTNETIFGETRING3BUFFERREQ GetRing3BufferReq;
    824         GetRing3BufferReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
    825         GetRing3BufferReq.Hdr.cbReq = sizeof(GetRing3BufferReq);
    826         GetRing3BufferReq.pSession = pSession;
    827         GetRing3BufferReq.hIf = OpenReq.hIf;
    828         GetRing3BufferReq.pRing3Buf = NULL;
    829         rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_GET_RING3_BUFFER, 0, &GetRing3BufferReq.Hdr);
     823        INTNETIFGETBUFFERPTRSREQ GetBufferPtrsReq;
     824        GetBufferPtrsReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     825        GetBufferPtrsReq.Hdr.cbReq = sizeof(GetBufferPtrsReq);
     826        GetBufferPtrsReq.pSession = pSession;
     827        GetBufferPtrsReq.hIf = OpenReq.hIf;
     828        GetBufferPtrsReq.pRing3Buf = NULL;
     829        GetBufferPtrsReq.pRing0Buf = NULL;
     830        rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS, 0, &GetBufferPtrsReq.Hdr);
    830831        if (RT_SUCCESS(rc))
    831832        {
    832             PINTNETBUF pBuf = GetRing3BufferReq.pRing3Buf;
     833            PINTNETBUF pBuf = GetBufferPtrsReq.pRing3Buf;
    833834            RTPrintf("tstIntNet-1: pBuf=%p cbBuf=%d cbSend=%d cbRecv=%d\n",
    834835                     pBuf, pBuf->cbBuf, pBuf->cbSend, pBuf->cbRecv);
     
    913914        else
    914915        {
    915             RTPrintf("tstIntNet-1: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_GET_RING3_BUFFER,) failed, rc=%Rrc\n", rc);
     916            RTPrintf("tstIntNet-1: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS,) failed, rc=%Rrc\n", rc);
    916917            g_cErrors++;
    917918        }
  • trunk/src/VBox/Devices/Network/testcase/tstIntNetR0.cpp

    r28706 r28711  
    410410                                         0/*fFlags*/, cbSend, cbRecv, &pThis->hIf0), rcCheck);
    411411    RTTESTI_CHECK_RET(pThis->hIf0 != INTNET_HANDLE_INVALID, VERR_INTERNAL_ERROR);
    412     RTTESTI_CHECK_RC_RET(IntNetR0IfGetRing0Buffer(pThis->hIf0, g_pSession, &pThis->pBuf0), VINF_SUCCESS, rcCheck);
     412    RTTESTI_CHECK_RC_RET(IntNetR0IfGetBufferPtrs(pThis->hIf0, g_pSession, &pThis->pBuf0, NULL), VINF_SUCCESS, rcCheck);
    413413    RTTESTI_CHECK_RET(pThis->pBuf0, VERR_INTERNAL_ERROR);
    414414
     
    418418                                         0/*fFlags*/, cbSend, cbRecv, &pThis->hIf1), rcCheck);
    419419    RTTESTI_CHECK_RET(pThis->hIf1 != INTNET_HANDLE_INVALID, VERR_INTERNAL_ERROR);
    420     RTTESTI_CHECK_RC_RET(IntNetR0IfGetRing0Buffer(pThis->hIf1, g_pSession, &pThis->pBuf1), VINF_SUCCESS, rcCheck);
     420    RTTESTI_CHECK_RC_RET(IntNetR0IfGetBufferPtrs(pThis->hIf1, g_pSession, &pThis->pBuf1, NULL), VINF_SUCCESS, rcCheck);
    421421    RTTESTI_CHECK_RET(pThis->pBuf1, VERR_INTERNAL_ERROR);
    422422
  • trunk/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp

    r28371 r28711  
    912912         * Get the ring-3 address of the shared interface buffer.
    913913         */
    914         INTNETIFGETRING3BUFFERREQ GetRing3BufferReq;
    915         GetRing3BufferReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
    916         GetRing3BufferReq.Hdr.cbReq = sizeof(GetRing3BufferReq);
    917         GetRing3BufferReq.pSession = m_pSession;
    918         GetRing3BufferReq.hIf = m_hIf;
    919         GetRing3BufferReq.pRing3Buf = NULL;
    920         rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_GET_RING3_BUFFER, 0, &GetRing3BufferReq.Hdr);
     914        INTNETIFGETBUFFERPTRSREQ GetBufferPtrsReq;
     915        GetBufferPtrsReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     916        GetBufferPtrsReq.Hdr.cbReq = sizeof(GetBufferPtrsReq);
     917        GetBufferPtrsReq.pSession = m_pSession;
     918        GetBufferPtrsReq.hIf = m_hIf;
     919        GetBufferPtrsReq.pRing3Buf = NULL;
     920        GetBufferPtrsReq.pRing0Buf = NULL;
     921        rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS, 0, &GetBufferPtrsReq.Hdr);
    921922        if (RT_SUCCESS(rc))
    922923        {
    923             PINTNETBUF pBuf = GetRing3BufferReq.pRing3Buf;
     924            PINTNETBUF pBuf = GetBufferPtrsReq.pRing3Buf;
    924925            debugPrint(1, false, "pBuf=%p cbBuf=%d cbSend=%d cbRecv=%d",
    925926                       pBuf, pBuf->cbBuf, pBuf->cbSend, pBuf->cbRecv);
     
    943944        }
    944945        else
    945             RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_GET_RING3_BUFFER,) failed, rc=%Rrc\n", rc);
     946            RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS,) failed, rc=%Rrc\n", rc);
    946947    }
    947948    else
  • trunk/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.cpp

    r28371 r28711  
    264264     * Get the ring-3 address of the shared interface buffer.
    265265     */
    266     INTNETIFGETRING3BUFFERREQ GetRing3BufferReq;
    267     GetRing3BufferReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
    268     GetRing3BufferReq.Hdr.cbReq = sizeof(GetRing3BufferReq);
    269     GetRing3BufferReq.pSession = m_pSession;
    270     GetRing3BufferReq.hIf = m_hIf;
    271     GetRing3BufferReq.pRing3Buf = NULL;
    272     rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_GET_RING3_BUFFER, 0, &GetRing3BufferReq.Hdr);
    273     if (RT_FAILURE(rc))
    274     {
    275         Log2(("VBoxNetBaseService: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_GET_RING3_BUFFER,) failed, rc=%Rrc\n", rc));
     266    GetRing3BufferReq GetBufferPtrsReq;
     267    GetBufferPtrsReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     268    GetBufferPtrsReq.Hdr.cbReq = sizeof(GetBufferPtrsReq);
     269    GetBufferPtrsReq.pSession = m_pSession;
     270    GetBufferPtrsReq.hIf = m_hIf;
     271    GetBufferPtrsReq.pRing3Buf = NULL;
     272    GetBufferPtrsReq.pRing0Buf = NULL;
     273    rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS, 0, &GetBufferPtrsReq.Hdr);
     274    if (RT_FAILURE(rc))
     275    {
     276        Log2(("VBoxNetBaseService: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS,) failed, rc=%Rrc\n", rc));
    276277        goto bad;
    277278    }
    278     pBuf = GetRing3BufferReq.pRing3Buf;
     279    pBuf = GetBufferPtrsReq.pRing3Buf;
    279280    Log2(("pBuf=%p cbBuf=%d cbSend=%d cbRecv=%d\n",
    280281               pBuf, pBuf->cbBuf, pBuf->cbSend, pBuf->cbRecv));
  • trunk/src/VBox/VMM/VMMR0/VMMR0.cpp

    r28706 r28711  
    999999            return IntNetR0IfCloseReq(pSession, (PINTNETIFCLOSEREQ)pReqHdr);
    10001000
    1001         case VMMR0_DO_INTNET_IF_GET_RING3_BUFFER:
    1002             if (u64Arg || !pReqHdr || !vmmR0IsValidSession(pVM, ((PINTNETIFGETRING3BUFFERREQ)pReqHdr)->pSession, pSession) || idCpu != NIL_VMCPUID)
    1003                 return VERR_INVALID_PARAMETER;
    1004             return IntNetR0IfGetRing3BufferReq(pSession, (PINTNETIFGETRING3BUFFERREQ)pReqHdr);
     1001        case VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS:
     1002            if (u64Arg || !pReqHdr || !vmmR0IsValidSession(pVM, ((PINTNETIFGETBUFFERPTRSREQ)pReqHdr)->pSession, pSession) || idCpu != NIL_VMCPUID)
     1003                return VERR_INVALID_PARAMETER;
     1004            return IntNetR0IfGetBufferPtrsReq(pSession, (PINTNETIFGETBUFFERPTRSREQ)pReqHdr);
    10051005
    10061006        case VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE:
  • trunk/src/VBox/VMM/VMMR0/VMMR0.def

    r28439 r28711  
    6767    VMSetErrorV
    6868
     69    ; Internal Networking
     70    IntNetR0Open
     71    IntNetR0IfClose
     72    IntNetR0IfGetRing0Buffer
     73    IntNetR0IfGetRing3Buffer
     74    IntNetR0IfSetPromiscuousMode
     75    IntNetR0IfSetMacAddress
     76    IntNetR0IfSetActive
     77    IntNetR0IfSend
     78    IntNetR0IfWait
     79
    6980    ; runtime
    7081    RTAssertMsg1Weak
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