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;
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);
/* 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;
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
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;
}
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;
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) {
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;
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_ */
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;
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;
}
}
PNET_BUFFER curNb,
IPHdr *ipHdr,
UDPHdr *udpHdr,
- UINT32 packetLength);
+ UINT32 packetLength,
+ POVS_PACKET_HDR_INFO layers);
ULONG OVSGetTcpMSS(PNET_BUFFER_LIST nbl);
*----------------------------------------------------------------------------
*/
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);
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;
}
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;
tunKey->pad = 0;
/* Handle ECN */
- OVS_PACKET_HDR_INFO layers = {0};
if (0 != ipHdr->tos) {
status = OvsExtractLayers(*newNbl, &layers);
if (status != NDIS_STATUS_SUCCESS) {
STT_HDR_LEN;
}
+static __inline UINT32
+OvsGetSttTunHdrSizeFromLayers(POVS_PACKET_HDR_INFO layers)
+{
+ return layers->l7Offset + STT_HDR_LEN;
+}
+
#endif /*__OVS_STT_H_ */
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;
}
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);
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;
}
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