From: Oliver Kurth Date: Fri, 15 Sep 2017 18:23:10 +0000 (-0700) Subject: Additional AsyncSocket API clean-up. X-Git-Tag: stable-10.2.0~475 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=97369f9f83795eecf186ce3e360e06faa53d0da9;p=thirdparty%2Fopen-vm-tools.git Additional AsyncSocket API clean-up. - Convert void-returning asyncsocket entrypoints to have an integer return type, returning ASOCKERR_*/ - Do not exit recv loop early when SSL_Pending is zero; the socket itself may have more data immediately available. - Allow a small number of recursives uses of the send callback. Common header file change; not applicable to open-vm-tools. --- diff --git a/open-vm-tools/lib/asyncsocket/asyncSocketInterface.c b/open-vm-tools/lib/asyncsocket/asyncSocketInterface.c index acec81d44..0d50b51cb 100644 --- a/open-vm-tools/lib/asyncsocket/asyncSocketInterface.c +++ b/open-vm-tools/lib/asyncsocket/asyncSocketInterface.c @@ -77,7 +77,7 @@ * (default is NULL: no callback) * * Results: - * None. + * ASOCKERR_SUCCESS or ASOCKERR_*. * * Side effects: * None. @@ -85,16 +85,20 @@ *---------------------------------------------------------------------------- */ -void +int AsyncSocket_SetCloseOptions(AsyncSocket *asock, // IN int flushEnabledMaxWaitMsec, // IN AsyncSocketCloseFn closeCb) // IN { + int ret; if (VALID(asock, setCloseOptions)) { AsyncSocketLock(asock); - VT(asock)->setCloseOptions(asock, flushEnabledMaxWaitMsec, closeCb); + ret = VT(asock)->setCloseOptions(asock, flushEnabledMaxWaitMsec, closeCb); AsyncSocketUnlock(asock); + } else { + ret = ASOCKERR_INVAL; } + return ret; } @@ -432,7 +436,7 @@ AsyncSocket_SetBufferSizes(AsyncSocket *asock, // IN * unless requested by the client. * * Result - * None + * ASOCKERR_SUCCESS or ASOCKERR_* * * Side-effects * See description above. @@ -440,15 +444,19 @@ AsyncSocket_SetBufferSizes(AsyncSocket *asock, // IN *----------------------------------------------------------------------------- */ -void +int AsyncSocket_SetSendLowLatencyMode(AsyncSocket *asock, // IN Bool enable) // IN { + int ret; if (VALID(asock, setSendLowLatencyMode)) { AsyncSocketLock(asock); - VT(asock)->setSendLowLatencyMode(asock, enable); + ret = VT(asock)->setSendLowLatencyMode(asock, enable); AsyncSocketUnlock(asock); + } else { + ret = ASOCKERR_INVAL; } + return ret; } @@ -464,9 +472,12 @@ AsyncSocket_SetSendLowLatencyMode(AsyncSocket *asock, // IN * after the sslConnectFn callback is called. * * Results: - * None. - * Error is always reported using the callback supplied. Detailed SSL - * verification error can be retrieved from verifyParam structure. + * ASOCKERR_SUCCESS indicates we have started async connect. + * ASOCKERR_* indicates a failure to start the connect. + * + * Errors during asynchronous processing is reported using the + * callback supplied. Detailed SSL verification error can be + * retrieved from verifyParam structure. * * Side effects: * None. @@ -474,19 +485,23 @@ AsyncSocket_SetSendLowLatencyMode(AsyncSocket *asock, // IN *----------------------------------------------------------------------------- */ -void +int AsyncSocket_StartSslConnect(AsyncSocket *asock, // IN SSLVerifyParam *verifyParam, // IN/OPT void *sslCtx, // IN AsyncSocketSslConnectFn sslConnectFn, // IN void *clientData) // IN { + int ret; if (VALID(asock, startSslConnect)) { AsyncSocketLock(asock); - VT(asock)->startSslConnect(asock, verifyParam, sslCtx, sslConnectFn, - clientData); + ret = VT(asock)->startSslConnect(asock, verifyParam, sslCtx, sslConnectFn, + clientData); AsyncSocketUnlock(asock); + } else { + ret = ASOCKERR_INVAL; } + return ret; } @@ -566,8 +581,11 @@ AsyncSocket_AcceptSSL(AsyncSocket *asock, // IN * or an error occurs. * * Results: - * None. - * Error is always reported using the callback supplied. + * ASOCKERR_SUCCESS indicates we have started async accept. + * ASOCKERR_* indicates a failure to start the accept. + * + * Errors during asynchronous processing are reported using the + * callback supplied. * * Side effects: * None. @@ -575,17 +593,21 @@ AsyncSocket_AcceptSSL(AsyncSocket *asock, // IN *----------------------------------------------------------------------------- */ -void +int AsyncSocket_StartSslAccept(AsyncSocket *asock, // IN void *sslCtx, // IN AsyncSocketSslAcceptFn sslAcceptFn, // IN void *clientData) // IN { + int ret; if (VALID(asock, startSslAccept)) { AsyncSocketLock(asock); - VT(asock)->startSslAccept(asock, sslCtx, sslAcceptFn, clientData); + ret = VT(asock)->startSslAccept(asock, sslCtx, sslAcceptFn, clientData); AsyncSocketUnlock(asock); + } else { + ret = ASOCKERR_INVAL; } + return ret; } @@ -967,7 +989,7 @@ AsyncSocket_CancelRecvEx(AsyncSocket *asock, // IN * function. * * Results: - * None. + * ASOCKERR_*. * * Side effects: * None. @@ -975,14 +997,18 @@ AsyncSocket_CancelRecvEx(AsyncSocket *asock, // IN *---------------------------------------------------------------------------- */ -void +int AsyncSocket_CancelCbForClose(AsyncSocket *asock) // IN: { + int ret; if (VALID(asock, cancelCbForClose)) { AsyncSocketLock(asock); - VT(asock)->cancelCbForClose(asock); + ret = VT(asock)->cancelCbForClose(asock); AsyncSocketUnlock(asock); + } else { + ret = ASOCKERR_INVAL; } + return ret; } diff --git a/open-vm-tools/lib/asyncsocket/asyncSocketVTable.h b/open-vm-tools/lib/asyncsocket/asyncSocketVTable.h index 240af72b7..b33c6dae3 100644 --- a/open-vm-tools/lib/asyncsocket/asyncSocketVTable.h +++ b/open-vm-tools/lib/asyncsocket/asyncSocketVTable.h @@ -60,17 +60,17 @@ typedef struct AsyncSocketVTable { int (*setTCPTimeouts)(AsyncSocket *asock, int keepIdle, int keepIntvl, int keepCnt); Bool (*setBufferSizes)(AsyncSocket *asock, int sendSz, int recvSz); - void (*setSendLowLatencyMode)(AsyncSocket *asock, Bool enable); - void (*setCloseOptions)(AsyncSocket *asock, int flushEnabledMaxWaitMsec, + int (*setSendLowLatencyMode)(AsyncSocket *asock, Bool enable); + int (*setCloseOptions)(AsyncSocket *asock, int flushEnabledMaxWaitMsec, AsyncSocketCloseFn closeCb); Bool (*connectSSL)(AsyncSocket *asock, struct _SSLVerifyParam *verifyParam, void *sslContext); - void (*startSslConnect)(AsyncSocket *asock, + int (*startSslConnect)(AsyncSocket *asock, struct _SSLVerifyParam *verifyParam, void *sslCtx, AsyncSocketSslConnectFn sslConnectFn, void *clientData); Bool (*acceptSSL)(AsyncSocket *asock, void *sslCtx); - void (*startSslAccept)(AsyncSocket *asock, void *sslCtx, + int (*startSslAccept)(AsyncSocket *asock, void *sslCtx, AsyncSocketSslAcceptFn sslAcceptFn, void *clientData); int (*flush)(AsyncSocket *asock, int timeoutMS); @@ -87,7 +87,7 @@ typedef struct AsyncSocketVTable { int (*close)(AsyncSocket *asock); int (*cancelRecv)(AsyncSocket *asock, int *partialRecvd, void **recvBuf, void **recvFn, Bool cancelOnSend); - void (*cancelCbForClose)(AsyncSocket *asock); + int (*cancelCbForClose)(AsyncSocket *asock); int (*getLocalVMCIAddress)(AsyncSocket *asock, uint32 *cid, uint32 *port); int (*getRemoteVMCIAddress)(AsyncSocket *asock, uint32 *cid, uint32 *port); int (*getWebSocketError)(AsyncSocket *asock); diff --git a/open-vm-tools/lib/asyncsocket/asyncsocket.c b/open-vm-tools/lib/asyncsocket/asyncsocket.c index adce1a65f..845b362e8 100644 --- a/open-vm-tools/lib/asyncsocket/asyncsocket.c +++ b/open-vm-tools/lib/asyncsocket/asyncsocket.c @@ -211,7 +211,7 @@ typedef struct AsyncTCPSocket { Bool sendCbRT; Bool sendBufFull; Bool sendLowLatency; - Bool inLowLatencySendCb; + int inLowLatencySendCb; Bool sslConnected; @@ -312,20 +312,20 @@ static int AsyncTCPSocketSetTCPTimeouts(AsyncSocket *asock, int keepIdle, int keepIntvl, int keepCnt); static Bool AsyncTCPSocketSetBufferSizes(AsyncSocket *asock, int sendSz, int recvSz); -static void AsyncTCPSocketSetSendLowLatencyMode(AsyncSocket *asock, +static int AsyncTCPSocketSetSendLowLatencyMode(AsyncSocket *asock, Bool enable); static Bool AsyncTCPSocketConnectSSL(AsyncSocket *asock, struct _SSLVerifyParam *verifyParam, void *sslContext); -static void AsyncTCPSocketStartSslConnect(AsyncSocket *asock, - SSLVerifyParam *verifyParam, - void *sslCtx, - AsyncSocketSslConnectFn sslConnectFn, - void *clientData); -static Bool AsyncTCPSocketAcceptSSL(AsyncSocket *asock, void *sslCtx); -static void AsyncTCPSocketStartSslAccept(AsyncSocket *asock, void *sslCtx, - AsyncSocketSslAcceptFn sslAcceptFn, +static int AsyncTCPSocketStartSslConnect(AsyncSocket *asock, + SSLVerifyParam *verifyParam, + void *sslCtx, + AsyncSocketSslConnectFn sslConnectFn, void *clientData); +static Bool AsyncTCPSocketAcceptSSL(AsyncSocket *asock, void *sslCtx); +static int AsyncTCPSocketStartSslAccept(AsyncSocket *asock, void *sslCtx, + AsyncSocketSslAcceptFn sslAcceptFn, + void *clientData); static int AsyncTCPSocketFlush(AsyncSocket *asock, int timeoutMS); static void AsyncTCPSocketCancelRecvCb(AsyncTCPSocket *asock); @@ -341,12 +341,12 @@ static int AsyncTCPSocketClose(AsyncSocket *asock); static int AsyncTCPSocketCancelRecv(AsyncSocket *asock, int *partialRecvd, void **recvBuf, void **recvFn, Bool cancelOnSend); -static void AsyncTCPSocketCancelCbForClose(AsyncSocket *asock); +static int AsyncTCPSocketCancelCbForClose(AsyncSocket *asock); static int AsyncTCPSocketGetLocalVMCIAddress(AsyncSocket *asock, uint32 *cid, uint32 *port); static int AsyncTCPSocketGetRemoteVMCIAddress(AsyncSocket *asock, uint32 *cid, uint32 *port); -static void AsyncTCPSocketSetCloseOptions(AsyncSocket *asock, +static int AsyncTCPSocketSetCloseOptions(AsyncSocket *asock, int flushEnabledMaxWaitMsec, AsyncSocketCloseFn closeCb); static void AsyncTCPSocketDestroy(AsyncSocket *s); @@ -2979,7 +2979,17 @@ AsyncTCPSocketSend(AsyncSocket *base, // IN LOG(2, ("%s: sending %d bytes\n", __FUNCTION__, len)); ASSERT(AsyncTCPSocketIsLocked(asock)); - ASSERT(!asock->inLowLatencySendCb); + + /* + * In low-latency mode, we want to guard against recursive calls to + * Send from within the send callback, as these have the capacity + * to blow up the stack. However some operations generate implicit + * sends (such as Close on a websocket) seem like they should be + * legal from the send callback. So, allow a small degree of + * recursive use of the send callback to accomodate these internal + * paths. + */ + ASSERT(asock->inLowLatencySendCb < 2); if (AsyncTCPSocketGetState(asock) != AsyncSocketConnected) { TCPSOCKWARN(asock, ("send called but state is not connected!\n")); @@ -3014,9 +3024,9 @@ AsyncTCPSocketSend(AsyncSocket *base, // IN * callback to be invoked prior to the call to * AsyncTCPSocket_Send() returning. */ - asock->inLowLatencySendCb = TRUE; + asock->inLowLatencySendCb++; asock->internalSendFn((void *)asock); - asock->inLowLatencySendCb = FALSE; + asock->inLowLatencySendCb--; } else { #ifdef _WIN32 /* @@ -3214,10 +3224,8 @@ static int AsyncTCPSocketFillRecvBuffer(AsyncTCPSocket *s) // IN { int recvd; - int needed; int sysErr = 0; int result; - int pending = 0; ASSERT(AsyncTCPSocketIsLocked(s)); ASSERT(AsyncTCPSocketGetState(s) == AsyncSocketConnected); @@ -3230,14 +3238,11 @@ AsyncTCPSocketFillRecvBuffer(AsyncTCPSocket *s) // IN * (e.g. aioMgr wait function), then FillRecvBuffer can be potentially be * called twice for the same receive event. */ - - needed = s->base.recvLen - s->base.recvPos; - if (!s->base.recvBuf && needed == 0) { + if (!s->base.recvBuf) { + ASSERT(s->base.recvLen == s->base.recvPos); return ASOCKERR_SUCCESS; } - ASSERT(needed > 0); - AsyncTCPSocketAddRef(s); /* @@ -3246,12 +3251,14 @@ AsyncTCPSocketFillRecvBuffer(AsyncTCPSocket *s) // IN s->inRecvLoop = TRUE; - do { + while (TRUE) { + int needed = s->base.recvLen - s->base.recvPos; + + ASSERT(needed > 0); /* * Try to read the remaining bytes to complete the current recv request. */ - if (s->passFd.expected) { int fd; @@ -3276,7 +3283,7 @@ AsyncTCPSocketFillRecvBuffer(AsyncTCPSocket *s) // IN s->sslConnected = TRUE; s->base.recvPos += recvd; if (AsyncSocketCheckAndDispatchRecv(&s->base, &result)) { - goto exit; + break; } } else if (recvd == 0) { TCPSOCKLG0(s, ("recv detected client closed connection\n")); @@ -3285,52 +3292,22 @@ AsyncTCPSocketFillRecvBuffer(AsyncTCPSocket *s) // IN * of connection by peer (via the error handler callback). */ result = ASOCKERR_REMOTE_DISCONNECT; - goto exit; + break; } else if ((sysErr = ASOCK_LASTERROR()) == ASOCK_EWOULDBLOCK) { TCPSOCKLOG(4, s, ("recv would block\n")); + result = ASOCKERR_SUCCESS; break; } else { TCPSOCKLG0(s, ("recv error %d: %s\n", sysErr, - Err_Errno2String(sysErr))); + Err_Errno2String(sysErr))); s->genericErrno = sysErr; result = ASOCKERR_GENERIC; - goto exit; + break; } + } - /* - * At this point, s->recvFoo have been updated to point to the - * next chained Recv buffer. By default we're done at this - * point, but we may want to continue if the SSL socket has data - * buffered in userspace already (SSL_Pending). - */ - - needed = s->base.recvLen - s->base.recvPos; - ASSERT(needed > 0); - - pending = SSL_Pending(s->sslSock); - needed = MIN(needed, pending); - - } while (needed); - - /* - * Reach this point only when previous SSL_Pending returns 0 or - * error is ASOCK_EWOULDBLOCK - */ - - ASSERT(pending == 0 || sysErr == ASOCK_EWOULDBLOCK); - - /* - * Both a spurious wakeup and receiving any data even if it wasn't enough - * to fire the callback are both success. We were ready and now - * presumably we aren't ready anymore. - */ - - result = ASOCKERR_SUCCESS; - -exit: s->inRecvLoop = FALSE; AsyncTCPSocketRelease(s); - return result; } @@ -4126,7 +4103,7 @@ AsyncTCPSocketCancelRecvCb(AsyncTCPSocket *asock) // IN: * socket is closed. * * Results: - * None. + * ASOCKERR_*. * * Side effects: * Unregisters send/recv Poll callbacks, and fires the send @@ -4136,7 +4113,7 @@ AsyncTCPSocketCancelRecvCb(AsyncTCPSocket *asock) // IN: *---------------------------------------------------------------------------- */ -static void +static int AsyncTCPSocketCancelCbForClose(AsyncSocket *base) // IN: { AsyncTCPSocket *asock = TCPSocket(base); @@ -4235,6 +4212,7 @@ AsyncTCPSocketCancelCbForClose(AsyncSocket *base) // IN: free(cur); } AsyncTCPSocketRelease(asock); + return ASOCKERR_SUCCESS; } @@ -4281,7 +4259,7 @@ AsyncTCPSocketCancelCbForConnectingClose(AsyncTCPSocket *asock) // IN * (default is NULL: no callback) * * Results: - * None. + * ASOCKERR_*. * * Side effects: * None. @@ -4289,7 +4267,7 @@ AsyncTCPSocketCancelCbForConnectingClose(AsyncTCPSocket *asock) // IN *---------------------------------------------------------------------------- */ -static void +static int AsyncTCPSocketSetCloseOptions(AsyncSocket *base, // IN int flushEnabledMaxWaitMsec, // IN AsyncSocketCloseFn closeCb) // IN @@ -4298,6 +4276,7 @@ AsyncTCPSocketSetCloseOptions(AsyncSocket *base, // IN asock->flushEnabledMaxWaitMsec = flushEnabledMaxWaitMsec; asock->closeCb = closeCb; VERIFY(closeCb == NULL); + return ASOCKERR_SUCCESS; } @@ -5337,8 +5316,8 @@ AsyncTCPSocketSslConnectCallback(void *clientData) // IN * set to zero. * * Results: - * None. - * Error is always reported using the callback supplied. + * ASOCKERR_SUCCESS or ASOCKERR_*. + * Errors during async processing are reported using the callback supplied. * * Side effects: * None. @@ -5346,7 +5325,7 @@ AsyncTCPSocketSslConnectCallback(void *clientData) // IN *----------------------------------------------------------------------------- */ -static void +static int AsyncTCPSocketStartSslConnect(AsyncSocket *base, // IN SSLVerifyParam *verifyParam, // IN/OPT void *sslCtx, // IN @@ -5364,7 +5343,7 @@ AsyncTCPSocketStartSslConnect(AsyncSocket *base, // IN if (asock->sslConnectFn || asock->sslAcceptFn) { TCPSOCKWARN(asock, ("An SSL operation was already initiated.\n")); - return; + return ASOCKERR_GENERIC; } ok = SSL_SetupConnectAndVerifyWithContext(asock->sslSock, verifyParam, @@ -5372,15 +5351,16 @@ AsyncTCPSocketStartSslConnect(AsyncSocket *base, // IN if (!ok) { /* Something went wrong already */ (*sslConnectFn)(FALSE, BaseSocket(asock), clientData); - return; + return ASOCKERR_GENERIC; } asock->sslConnectFn = sslConnectFn; asock->clientData = clientData; AsyncTCPSocketSslConnectCallback(asock); + return ASOCKERR_SUCCESS; #else - NOT_IMPLEMENTED(); + return ASOCKERR_INVAL; #endif } @@ -5461,8 +5441,8 @@ AsyncTCPSocketSslAcceptCallback(void *clientData) // IN * not have to include the openssl header. This is in sync with * SSL_AcceptWithContext(), where the sslCtx param is typed as void * * Results: - * None. - * Error is always reported using the callback supplied. + * ASOCKERR_SUCCESS or ASOCKERR_*. + * Errors during async processing reported using the callback supplied. * * Side effects: * None. @@ -5470,7 +5450,7 @@ AsyncTCPSocketSslAcceptCallback(void *clientData) // IN *----------------------------------------------------------------------------- */ -static void +static int AsyncTCPSocketStartSslAccept(AsyncSocket *base, // IN void *sslCtx, // IN AsyncSocketSslAcceptFn sslAcceptFn, // IN @@ -5486,20 +5466,21 @@ AsyncTCPSocketStartSslAccept(AsyncSocket *base, // IN if (asock->sslAcceptFn || asock->sslConnectFn) { TCPSOCKWARN(asock, ("An SSL operation was already initiated.\n")); - return; + return ASOCKERR_GENERIC; } ok = SSL_SetupAcceptWithContext(asock->sslSock, sslCtx); if (!ok) { /* Something went wrong already */ (*sslAcceptFn)(FALSE, BaseSocket(asock), clientData); - return; + return ASOCKERR_GENERIC; } asock->sslAcceptFn = sslAcceptFn; asock->clientData = clientData; AsyncTCPSocketSslAcceptCallback(asock); + return ASOCKERR_SUCCESS; } @@ -5594,7 +5575,7 @@ AsyncTCPSocketSetBufferSizes(AsyncSocket *base, // IN * unless requested by the client. * * Result - * None + * ASOCKERR_* * * Side-effects * See description above. @@ -5602,12 +5583,13 @@ AsyncTCPSocketSetBufferSizes(AsyncSocket *base, // IN *----------------------------------------------------------------------------- */ -static void +static int AsyncTCPSocketSetSendLowLatencyMode(AsyncSocket *base, // IN Bool enable) // IN { AsyncTCPSocket *asock = TCPSocket(base); asock->sendLowLatency = enable; + return ASOCKERR_SUCCESS; } diff --git a/open-vm-tools/lib/include/asyncsocket.h b/open-vm-tools/lib/include/asyncsocket.h index a3c78d1e1..c5931ab18 100644 --- a/open-vm-tools/lib/include/asyncsocket.h +++ b/open-vm-tools/lib/include/asyncsocket.h @@ -381,18 +381,18 @@ AsyncSocket_ConnectWebSocket(const char *url, Bool AsyncSocket_ConnectSSL(AsyncSocket *asock, struct _SSLVerifyParam *verifyParam, void *sslContext); -void AsyncSocket_StartSslConnect(AsyncSocket *asock, - struct _SSLVerifyParam *verifyParam, - void *sslCtx, - AsyncSocketSslConnectFn sslConnectFn, - void *clientData); - -Bool AsyncSocket_AcceptSSL(AsyncSocket *asock, void *sslCtx); -void AsyncSocket_StartSslAccept(AsyncSocket *asock, +int AsyncSocket_StartSslConnect(AsyncSocket *asock, + struct _SSLVerifyParam *verifyParam, void *sslCtx, - AsyncSocketSslAcceptFn sslAcceptFn, + AsyncSocketSslConnectFn sslConnectFn, void *clientData); +Bool AsyncSocket_AcceptSSL(AsyncSocket *asock, void *sslCtx); +int AsyncSocket_StartSslAccept(AsyncSocket *asock, + void *sslCtx, + AsyncSocketSslAcceptFn sslAcceptFn, + void *clientData); + /* * Create a new AsyncSocket from an existing socket */ @@ -483,7 +483,7 @@ int AsyncSocket_CancelRecvEx(AsyncSocket *asock, int *partialRecvd, void **recvB /* * Unregister asynchronous send and recv from poll */ -void AsyncSocket_CancelCbForClose(AsyncSocket *asock); +int AsyncSocket_CancelCbForClose(AsyncSocket *asock); /* * Set the error handler to invoke on I/O errors (default is to close the @@ -502,9 +502,9 @@ Bool AsyncSocket_SetBufferSizes(AsyncSocket *asock, // IN /* * Set optional AsyncSocket_Close() behaviors. */ -void AsyncSocket_SetCloseOptions(AsyncSocket *asock, - int flushEnabledMaxWaitMsec, - AsyncSocketCloseFn closeCb); +int AsyncSocket_SetCloseOptions(AsyncSocket *asock, + int flushEnabledMaxWaitMsec, + AsyncSocketCloseFn closeCb); /* * Close the connection and destroy the asock. @@ -537,7 +537,7 @@ uint16 AsyncSocket_GetWebSocketCloseStatus(AsyncSocket *asock); /* * Set low-latency mode for sends: */ -void AsyncSocket_SetSendLowLatencyMode(AsyncSocket *asock, Bool enable); +int AsyncSocket_SetSendLowLatencyMode(AsyncSocket *asock, Bool enable); /* * Get negotiated websocket protocol diff --git a/open-vm-tools/modules/shared/vmxnet/eth_public.h b/open-vm-tools/modules/shared/vmxnet/eth_public.h index 256098909..f8e81ebc2 100644 --- a/open-vm-tools/modules/shared/vmxnet/eth_public.h +++ b/open-vm-tools/modules/shared/vmxnet/eth_public.h @@ -120,6 +120,7 @@ typedef enum { ETH_TYPE_AKIMBI_NBO = 0xDE88, ETH_TYPE_VMWARE_NBO = 0x2289, ETH_TYPE_802_1PQ_NBO = 0x0081, // not really a DIX type, but used as such + ETH_TYPE_802_3_PAUSE_NBO = 0x0888, // pause frame based ethernet flow control } Eth_DixTypeNBO; // low two bits of the LLC control byte @@ -757,6 +758,27 @@ Eth_IsFrameTagged(const Eth_Header *eh) return (eh->dix.typeNBO == ETH_TYPE_802_1PQ_NBO); } +/* + *---------------------------------------------------------------------- + * + * Eth_IsPauseFrame -- + * + * Is the frame 802.3 pause frame ? + * + * Results: + * TRUE or FALSE. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static INLINE Bool +Eth_IsPauseFrame(const Eth_Header *eh) +{ + return (eh->dix.typeNBO == ETH_TYPE_802_3_PAUSE_NBO); +} /* *----------------------------------------------------------------------