diff options
-rw-r--r-- | datapath-windows/ovsext/Geneve.c | 14 | ||||
-rw-r--r-- | datapath-windows/ovsext/Geneve.h | 6 | ||||
-rw-r--r-- | datapath-windows/ovsext/Gre.c | 29 | ||||
-rw-r--r-- | datapath-windows/ovsext/Gre.h | 16 | ||||
-rw-r--r-- | datapath-windows/ovsext/Offload.c | 10 | ||||
-rw-r--r-- | datapath-windows/ovsext/Offload.h | 3 | ||||
-rw-r--r-- | datapath-windows/ovsext/Stt.c | 44 | ||||
-rw-r--r-- | datapath-windows/ovsext/Stt.h | 6 | ||||
-rw-r--r-- | datapath-windows/ovsext/Vxlan.c | 14 | ||||
-rw-r--r-- | datapath-windows/ovsext/Vxlan.h | 6 |
10 files changed, 111 insertions, 37 deletions
diff --git a/datapath-windows/ovsext/Geneve.c b/datapath-windows/ovsext/Geneve.c index 6dca69bc7..210716d5a 100644 --- a/datapath-windows/ovsext/Geneve.c +++ b/datapath-windows/ovsext/Geneve.c @@ -262,10 +262,16 @@ NDIS_STATUS OvsDecapGeneve(POVS_SWITCH_CONTEXT switchContext, PUINT8 bufferStart; PVOID optStart; NDIS_STATUS status; + OVS_PACKET_HDR_INFO layers = { 0 }; + + status = OvsExtractLayers(curNbl, &layers); + if (status != NDIS_STATUS_SUCCESS) { + return status; + } /* Check the length of the UDP payload */ curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); - tunnelSize = OvsGetGeneveTunHdrMinSize(); + tunnelSize = OvsGetGeneveTunHdrSizeFromLayers(&layers); packetLength = NET_BUFFER_DATA_LENGTH(curNb); if (packetLength <= tunnelSize) { return NDIS_STATUS_INVALID_LENGTH; @@ -295,13 +301,13 @@ NDIS_STATUS OvsDecapGeneve(POVS_SWITCH_CONTEXT switchContext, ethHdr = (EthHdr *)bufferStart; /* XXX: Handle IP options. */ - ipHdr = (IPHdr *)((PCHAR)ethHdr + sizeof *ethHdr); + ipHdr = (IPHdr *)(bufferStart + layers.l3Offset); tunKey->src = ipHdr->saddr; tunKey->dst = ipHdr->daddr; tunKey->tos = ipHdr->tos; tunKey->ttl = ipHdr->ttl; tunKey->pad = 0; - udpHdr = (UDPHdr *)((PCHAR)ipHdr + sizeof *ipHdr); + udpHdr = (UDPHdr *)(bufferStart + layers.l4Offset); /* Validate if NIC has indicated checksum failure. */ status = OvsValidateUDPChecksum(curNbl, udpHdr->check == 0); @@ -312,7 +318,7 @@ NDIS_STATUS OvsDecapGeneve(POVS_SWITCH_CONTEXT switchContext, /* Calculate and verify UDP checksum if NIC didn't do it. */ if (udpHdr->check != 0) { status = OvsCalculateUDPChecksum(curNbl, curNb, ipHdr, udpHdr, - packetLength); + packetLength, &layers); tunKey->flags |= OVS_TNL_F_CSUM; if (status != NDIS_STATUS_SUCCESS) { goto dropNbl; diff --git a/datapath-windows/ovsext/Geneve.h b/datapath-windows/ovsext/Geneve.h index 019c0dd9f..db758dd07 100644 --- a/datapath-windows/ovsext/Geneve.h +++ b/datapath-windows/ovsext/Geneve.h @@ -113,6 +113,12 @@ OvsGetGeneveTunHdrMaxSize(VOID) return OvsGetGeneveTunHdrMinSize() + TUN_OPT_MAX_LEN; } +static __inline UINT32 +OvsGetGeneveTunHdrSizeFromLayers(POVS_PACKET_HDR_INFO layers) +{ + return layers->l7Offset + sizeof(GeneveHdr); +} + #define GENEVE_UDP_PORT 6081 #define GENEVE_UDP_PORT_NBO 0xC117 #define GENEVE_VER 0 diff --git a/datapath-windows/ovsext/Gre.c b/datapath-windows/ovsext/Gre.c index f095742a4..1f38ee794 100644 --- a/datapath-windows/ovsext/Gre.c +++ b/datapath-windows/ovsext/Gre.c @@ -317,35 +317,42 @@ OvsDecapGre(POVS_SWITCH_CONTEXT switchContext, GREHdr *greHdr; UINT32 tunnelSize, packetLength; UINT32 headRoom = 0; + UINT32 maxGreLen; PUINT8 bufferStart; NDIS_STATUS status = NDIS_STATUS_SUCCESS; PCHAR tempBuf = NULL; + OVS_PACKET_HDR_INFO layers; ASSERT(*newNbl == NULL); *newNbl = NULL; + status = OvsExtractLayers(curNbl, &layers); + if (status != NDIS_STATUS_SUCCESS) { + return status; + } curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); packetLength = NET_BUFFER_DATA_LENGTH(curNb); curMdl = NET_BUFFER_CURRENT_MDL(curNb); - tunnelSize = GreTunHdrSize(0); + tunnelSize = GreTunHdrSizeFromLayers(0, &layers); if (packetLength <= tunnelSize) { return NDIS_STATUS_INVALID_LENGTH; } + maxGreLen = GreMaxLengthFromLayers(&layers); /* Get a contiguous buffer for the maximum length of a GRE header */ - bufferStart = NdisGetDataBuffer(curNb, OVS_MAX_GRE_LGTH, NULL, 1, 0); + bufferStart = NdisGetDataBuffer(curNb, maxGreLen, NULL, 1, 0); if (!bufferStart) { /* Documentation is unclear on where the packet can be fragmented. * For the moment allocate the buffer needed to get the maximum length * of a GRE header contiguous */ - tempBuf = OvsAllocateMemoryWithTag(OVS_MAX_GRE_LGTH, OVS_GRE_POOL_TAG); + tempBuf = OvsAllocateMemoryWithTag(maxGreLen, OVS_GRE_POOL_TAG); if (!tempBuf) { status = NDIS_STATUS_RESOURCES; goto end; } - RtlZeroMemory(tempBuf, OVS_MAX_GRE_LGTH); - bufferStart = NdisGetDataBuffer(curNb, OVS_MAX_GRE_LGTH, tempBuf, + RtlZeroMemory(tempBuf, maxGreLen); + bufferStart = NdisGetDataBuffer(curNb, maxGreLen, tempBuf, 1, 0); if (!bufferStart) { status = NDIS_STATUS_RESOURCES; @@ -354,9 +361,9 @@ OvsDecapGre(POVS_SWITCH_CONTEXT switchContext, } ethHdr = (EthHdr *)bufferStart; - headRoom += sizeof *ethHdr; + headRoom += layers.l3Offset; - ipHdr = (IPHdr *)((PCHAR)ethHdr + sizeof *ethHdr); + ipHdr = (IPHdr *)(bufferStart + layers.l3Offset); tunKey->src = ipHdr->saddr; tunKey->dst = ipHdr->daddr; tunKey->tos = ipHdr->tos; @@ -364,10 +371,10 @@ OvsDecapGre(POVS_SWITCH_CONTEXT switchContext, tunKey->pad = 0; headRoom += sizeof *ipHdr; - greHdr = (GREHdr *)((PCHAR)ipHdr + sizeof *ipHdr); + greHdr = (GREHdr *)(bufferStart + layers.l4Offset); headRoom += sizeof *greHdr; - tunnelSize = GreTunHdrSize(greHdr->flags); + tunnelSize = GreTunHdrSizeFromLayers(greHdr->flags, &layers); /* Verify the packet length after looking at the GRE flags*/ if (packetLength <= tunnelSize) { @@ -390,8 +397,8 @@ OvsDecapGre(POVS_SWITCH_CONTEXT switchContext, UINT16 chksum = CalculateChecksumNB(curNb, (UINT16)(NET_BUFFER_DATA_LENGTH(curNb) - - (ipHdr->ihl * 4 + sizeof *ethHdr)), - ipHdr->ihl * 4 + sizeof *ethHdr); + layers.l4Offset), + layers.l4Offset); if (prevChksum != chksum) { status = STATUS_NDIS_INVALID_PACKET; goto end; diff --git a/datapath-windows/ovsext/Gre.h b/datapath-windows/ovsext/Gre.h index c45df8fed..45f3f59f3 100644 --- a/datapath-windows/ovsext/Gre.h +++ b/datapath-windows/ovsext/Gre.h @@ -103,4 +103,20 @@ GreTunHdrSize(UINT16 flags) return sum; } +static __inline UINT32 +GreTunHdrSizeFromLayers(UINT16 flags, POVS_PACKET_HDR_INFO layers) +{ + UINT32 sum = layers->l4Offset + sizeof(GREHdr); + sum += (flags & GRE_CSUM) ? 4 : 0; + sum += (flags & GRE_KEY) ? 4 : 0; + + return sum; +} + +static __inline UINT32 +GreMaxLengthFromLayers(POVS_PACKET_HDR_INFO layers) +{ + return (layers->l4Offset + sizeof(GREHdr) + 12); +} + #endif /*__GRE_H_ */ diff --git a/datapath-windows/ovsext/Offload.c b/datapath-windows/ovsext/Offload.c index 0905c8057..7b75e0afc 100644 --- a/datapath-windows/ovsext/Offload.c +++ b/datapath-windows/ovsext/Offload.c @@ -612,7 +612,8 @@ OvsCalculateUDPChecksum(PNET_BUFFER_LIST curNbl, PNET_BUFFER curNb, IPHdr *ipHdr, UDPHdr *udpHdr, - UINT32 packetLength) + UINT32 packetLength, + POVS_PACKET_HDR_INFO layers) { NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; UINT16 checkSum; @@ -625,16 +626,17 @@ OvsCalculateUDPChecksum(PNET_BUFFER_LIST curNbl, checkSum = udpHdr->check; - l4Payload = packetLength - sizeof(EthHdr) - ipHdr->ihl * 4; + l4Payload = packetLength - layers->l4Offset; udpHdr->check = 0; udpHdr->check = IPPseudoChecksum((UINT32 *)&ipHdr->saddr, (UINT32 *)&ipHdr->daddr, IPPROTO_UDP, (UINT16)l4Payload); udpHdr->check = CalculateChecksumNB(curNb, (UINT16)l4Payload, - sizeof(EthHdr) + ipHdr->ihl * 4); + layers->l4Offset); if (checkSum != udpHdr->check) { - OVS_LOG_TRACE("UDP checksum incorrect."); + OVS_LOG_ERROR("UDP checksum incorrect, expected %u, got %u", + udpHdr->check, checkSum); return NDIS_STATUS_INVALID_PACKET; } } diff --git a/datapath-windows/ovsext/Offload.h b/datapath-windows/ovsext/Offload.h index d3731b171..b2a0b6faa 100644 --- a/datapath-windows/ovsext/Offload.h +++ b/datapath-windows/ovsext/Offload.h @@ -39,7 +39,8 @@ NDIS_STATUS OvsCalculateUDPChecksum(PNET_BUFFER_LIST curNbl, PNET_BUFFER curNb, IPHdr *ipHdr, UDPHdr *udpHdr, - UINT32 packetLength); + UINT32 packetLength, + POVS_PACKET_HDR_INFO layers); ULONG OVSGetTcpMSS(PNET_BUFFER_LIST nbl); diff --git a/datapath-windows/ovsext/Stt.c b/datapath-windows/ovsext/Stt.c index f98070f33..8eb71676a 100644 --- a/datapath-windows/ovsext/Stt.c +++ b/datapath-windows/ovsext/Stt.c @@ -415,9 +415,23 @@ ret_error: *---------------------------------------------------------------------------- */ static __inline NDIS_STATUS -OvsValidateTCPChecksum(PNET_BUFFER_LIST curNbl, PNET_BUFFER curNb) +OvsValidateTCPChecksum(PNET_BUFFER_LIST curNbl, + PNET_BUFFER curNb, + POVS_PACKET_HDR_INFO layers) { + PUINT8 buf; + PMDL curMdl; NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; + NDIS_STATUS status; + + curMdl = NET_BUFFER_CURRENT_MDL(curNb); + buf = (PUINT8)MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority) + + NET_BUFFER_CURRENT_MDL_OFFSET(curNb); + if (!buf) { + status = NDIS_STATUS_INVALID_PACKET; + return status; + } + csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo); @@ -433,23 +447,22 @@ OvsValidateTCPChecksum(PNET_BUFFER_LIST curNbl, PNET_BUFFER curNb) return NDIS_STATUS_SUCCESS; } - EthHdr *eth = (EthHdr *)NdisGetDataBuffer(curNb, sizeof(EthHdr), - NULL, 1, 0); - if (eth == NULL) { + EthHdr *ethHdr = (EthHdr *)buf; + if (ethHdr == NULL) { return NDIS_STATUS_RESOURCES; } - if (eth->Type == ntohs(NDIS_ETH_TYPE_IPV4)) { - IPHdr *ip = (IPHdr *)((PCHAR)eth + sizeof *eth); - UINT32 l4Payload = ntohs(ip->tot_len) - ip->ihl * 4; - TCPHdr *tcp = (TCPHdr *)((PCHAR)ip + ip->ihl * 4); + if (ethHdr->Type == ntohs(NDIS_ETH_TYPE_IPV4)) { + IPHdr *ipHdr = (IPHdr *)(buf + layers->l3Offset); + UINT32 l4Payload = ntohs(ipHdr->tot_len) - ipHdr->ihl * 4; + TCPHdr *tcp = (TCPHdr *)(buf + layers->l4Offset); checkSum = tcp->check; tcp->check = 0; - tcp->check = IPPseudoChecksum(&ip->saddr, &ip->daddr, + tcp->check = IPPseudoChecksum(&ipHdr->saddr, &ipHdr->daddr, IPPROTO_TCP, (UINT16)l4Payload); tcp->check = CalculateChecksumNB(curNb, (UINT16)(l4Payload), - sizeof(EthHdr) + ip->ihl * 4); + layers->l4Offset); if (checkSum != tcp->check) { return NDIS_STATUS_INVALID_PACKET; } @@ -912,18 +925,24 @@ OvsDecapStt(POVS_SWITCH_CONTEXT switchContext, SttHdr *sttHdr; char *sttBuf[STT_HDR_LEN]; UINT32 advanceCnt, hdrLen; + OVS_PACKET_HDR_INFO layers = { 0 }; + + status = OvsExtractLayers(curNbl, &layers); + if (status != NDIS_STATUS_SUCCESS) { + return status; + } curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); ASSERT(NET_BUFFER_NEXT_NB(curNb) == NULL); /* Validate the TCP Checksum */ - status = OvsValidateTCPChecksum(curNbl, curNb); + status = OvsValidateTCPChecksum(curNbl, curNb, &layers); if (status != NDIS_STATUS_SUCCESS) { return status; } /* Skip Eth header */ - hdrLen = sizeof(EthHdr); + hdrLen = layers.l3Offset; NdisAdvanceNetBufferDataStart(curNb, hdrLen, FALSE, NULL); advanceCnt = hdrLen; @@ -996,7 +1015,6 @@ OvsDecapStt(POVS_SWITCH_CONTEXT switchContext, tunKey->pad = 0; /* Handle ECN */ - OVS_PACKET_HDR_INFO layers = {0}; if (0 != ipHdr->tos) { status = OvsExtractLayers(*newNbl, &layers); if (status != NDIS_STATUS_SUCCESS) { diff --git a/datapath-windows/ovsext/Stt.h b/datapath-windows/ovsext/Stt.h index 988a1c1eb..2999dcf99 100644 --- a/datapath-windows/ovsext/Stt.h +++ b/datapath-windows/ovsext/Stt.h @@ -115,4 +115,10 @@ OvsGetSttTunHdrSize(VOID) STT_HDR_LEN; } +static __inline UINT32 +OvsGetSttTunHdrSizeFromLayers(POVS_PACKET_HDR_INFO layers) +{ + return layers->l7Offset + STT_HDR_LEN; +} + #endif /*__OVS_STT_H_ */ diff --git a/datapath-windows/ovsext/Vxlan.c b/datapath-windows/ovsext/Vxlan.c index f66a7e57f..47c734e1e 100644 --- a/datapath-windows/ovsext/Vxlan.c +++ b/datapath-windows/ovsext/Vxlan.c @@ -391,11 +391,17 @@ OvsDecapVxlan(POVS_SWITCH_CONTEXT switchContext, UINT32 tunnelSize, packetLength; PUINT8 bufferStart; NDIS_STATUS status; + OVS_PACKET_HDR_INFO layers = { 0 }; + + status = OvsExtractLayers(curNbl, &layers); + if (status != NDIS_STATUS_SUCCESS) { + return status; + } /* Check the length of the UDP payload */ curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); packetLength = NET_BUFFER_DATA_LENGTH(curNb); - tunnelSize = OvsGetVxlanTunHdrSize(); + tunnelSize = OvsGetVxlanTunHdrSizeFromLayers(&layers); if (packetLength < tunnelSize) { return NDIS_STATUS_INVALID_LENGTH; } @@ -424,13 +430,13 @@ OvsDecapVxlan(POVS_SWITCH_CONTEXT switchContext, ethHdr = (EthHdr *)bufferStart; /* XXX: Handle IP options. */ - ipHdr = (IPHdr *)((PCHAR)ethHdr + sizeof *ethHdr); + ipHdr = (IPHdr *)(bufferStart + layers.l3Offset); tunKey->src = ipHdr->saddr; tunKey->dst = ipHdr->daddr; tunKey->tos = ipHdr->tos; tunKey->ttl = ipHdr->ttl; tunKey->pad = 0; - udpHdr = (UDPHdr *)((PCHAR)ipHdr + sizeof *ipHdr); + udpHdr = (UDPHdr *)(bufferStart + layers.l4Offset); /* Validate if NIC has indicated checksum failure. */ status = OvsValidateUDPChecksum(curNbl, udpHdr->check == 0); @@ -442,7 +448,7 @@ OvsDecapVxlan(POVS_SWITCH_CONTEXT switchContext, if (udpHdr->check != 0) { tunKey->flags |= OVS_TNL_F_CSUM; status = OvsCalculateUDPChecksum(curNbl, curNb, ipHdr, udpHdr, - packetLength); + packetLength, &layers); if (status != NDIS_STATUS_SUCCESS) { goto dropNbl; } diff --git a/datapath-windows/ovsext/Vxlan.h b/datapath-windows/ovsext/Vxlan.h index f4a8bceba..e2fb2dc08 100644 --- a/datapath-windows/ovsext/Vxlan.h +++ b/datapath-windows/ovsext/Vxlan.h @@ -85,6 +85,12 @@ OvsGetVxlanTunHdrSize(VOID) sizeof (VXLANHdr); } +static __inline UINT32 +OvsGetVxlanTunHdrSizeFromLayers(POVS_PACKET_HDR_INFO layers) +{ + return layers->l7Offset + sizeof(VXLANHdr); +} + #define VXLAN_UDP_PORT 4789 #define VXLAN_UDP_PORT_NBO 0xB512 |