From 6941a7650f08de3637cfc41791257e163c87c53d Mon Sep 17 00:00:00 2001 From: Wilson Peng Date: Wed, 17 Jul 2024 19:42:29 +0800 Subject: [PATCH] datapath-windows: Merge split dis-continuous net-buf. NdisGetDataBuffer() is called without providing a buffer to copy packet data in case it is not contiguous. So, it fails in some scenarios where the packet is handled by the general network stack before OVS and headers become split in multiple buffers. In the fix it will supply the stack buffer to copy packet data when call NdisGetDataBuffer(). In the conntrack Action process, it will do OvsPartialCopyNBL firstly with the size of layers l7offsets. If the header is split the header will be merged to one continuous buffer. But IPV6 traffic is not handed in this case. Reported-at: https://github.com/openvswitch/ovs-issues/issues/323 Signed-off-by: Wilson Peng Signed-off-by: 0-day Robot --- datapath-windows/ovsext/Actions.c | 7 +++++++ datapath-windows/ovsext/BufferMgmt.c | 16 +++++++++++++--- datapath-windows/ovsext/Conntrack.c | 4 +++- datapath-windows/ovsext/IpFragment.c | 8 ++++++-- 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/datapath-windows/ovsext/Actions.c b/datapath-windows/ovsext/Actions.c index 97029b0f4e1..4bc2a6b65e8 100644 --- a/datapath-windows/ovsext/Actions.c +++ b/datapath-windows/ovsext/Actions.c @@ -2414,6 +2414,13 @@ OvsDoExecuteActions(POVS_SWITCH_CONTEXT switchContext, } PNET_BUFFER_LIST oldNbl = ovsFwdCtx.curNbl; + PUINT8 bufferStart = NULL; + + bufferStart = OvsGetHeaderBySize(&ovsFwdCtx, layers->l7Offset); + if (!bufferStart) { + dropReason = L"OVS-Netbuf reallocated failed"; + goto dropit; + } status = OvsExecuteConntrackAction(&ovsFwdCtx, key, (const PNL_ATTR)a); if (status != NDIS_STATUS_SUCCESS) { diff --git a/datapath-windows/ovsext/BufferMgmt.c b/datapath-windows/ovsext/BufferMgmt.c index 5c52757a087..40faaefd69d 100644 --- a/datapath-windows/ovsext/BufferMgmt.c +++ b/datapath-windows/ovsext/BufferMgmt.c @@ -1110,12 +1110,22 @@ GetIpHeaderInfo(PNET_BUFFER_LIST curNbl, IPHdr *ipHdr; IPv6Hdr *ipv6Hdr; PNET_BUFFER curNb; + CHAR tempBuf[MAX_IPV4_HLEN]; curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); ASSERT(NET_BUFFER_NEXT_NB(curNb) == NULL); - eth = (EthHdr *)NdisGetDataBuffer(curNb, - hdrInfo->l4Offset, - NULL, 1, 0); + + if (hdrInfo->isIPv6) { + eth = (EthHdr *)NdisGetDataBuffer(curNb, + hdrInfo->l4Offset, + NULL, 1, 0); + } else { + NdisZeroMemory(tempBuf, MAX_IPV4_HLEN); + eth = (EthHdr *)NdisGetDataBuffer(curNb, + hdrInfo->l4Offset, + (PVOID)tempBuf, 1, 0); + } + if (eth == NULL) { return NDIS_STATUS_INVALID_PACKET; } diff --git a/datapath-windows/ovsext/Conntrack.c b/datapath-windows/ovsext/Conntrack.c index 39ba5cc10ec..1a1794fc1c9 100644 --- a/datapath-windows/ovsext/Conntrack.c +++ b/datapath-windows/ovsext/Conntrack.c @@ -683,6 +683,7 @@ OvsGetTcpHeader(PNET_BUFFER_LIST nbl, TCPHdr *tcp; VOID *dest = storage; uint16_t ipv6ExtLength = 0; + CHAR tempBuf[MAX_IPV4_HLEN]; if (layers->isIPv6) { ipv6Hdr = NdisGetDataBuffer(NET_BUFFER_LIST_FIRST_NB(nbl), @@ -701,9 +702,10 @@ OvsGetTcpHeader(PNET_BUFFER_LIST nbl, return storage; } } else { + NdisZeroMemory(tempBuf, MAX_IPV4_HLEN); ipHdr = NdisGetDataBuffer(NET_BUFFER_LIST_FIRST_NB(nbl), layers->l4Offset + sizeof(TCPHdr), - NULL, 1 /*no align*/, 0); + (PVOID)tempBuf, 1 /*no align*/, 0); if (ipHdr == NULL) { return NULL; } diff --git a/datapath-windows/ovsext/IpFragment.c b/datapath-windows/ovsext/IpFragment.c index afb8e50d6bf..4e119d82a34 100644 --- a/datapath-windows/ovsext/IpFragment.c +++ b/datapath-windows/ovsext/IpFragment.c @@ -153,12 +153,14 @@ OvsIpv4Reassemble(POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST newNbl = NULL; UINT16 ipHdrLen, packetHeader; UINT32 packetLen; + CHAR tempBuf[MAX_IPV4_HLEN]; curNb = NET_BUFFER_LIST_FIRST_NB(*curNbl); ASSERT(NET_BUFFER_NEXT_NB(curNb) == NULL); + NdisZeroMemory(tempBuf, MAX_IPV4_HLEN); eth = (EthHdr*)NdisGetDataBuffer(curNb, layers->l4Offset, - NULL, 1, 0); + (PVOID)tempBuf, 1, 0); if (eth == NULL) { return NDIS_STATUS_INVALID_PACKET; } @@ -253,12 +255,14 @@ OvsProcessIpv4Fragment(POVS_SWITCH_CONTEXT switchContext, POVS_IPFRAG_ENTRY entry; POVS_FRAGMENT_LIST fragStorage; LOCK_STATE_EX htLockState; + CHAR tempBuf[MAX_IPV4_HLEN]; curNb = NET_BUFFER_LIST_FIRST_NB(*curNbl); ASSERT(NET_BUFFER_NEXT_NB(curNb) == NULL); + NdisZeroMemory(tempBuf, MAX_IPV4_HLEN); eth = (EthHdr*)NdisGetDataBuffer(curNb, layers->l4Offset, - NULL, 1, 0); + (PVOID)tempBuf, 1, 0); if (eth == NULL) { return NDIS_STATUS_INVALID_PACKET; }