The purpose of this patch is to refactor the software offloads found in the VXLAN and GRE code and also to refactor how the maximmum segment size for a given NBL is obtained.
This patch introduces two functions OvsApplySWChecksumOnNB and OVSGetTcpMSS. OVSGetTcpMSS - will return the mss found in a given NBL. OvsApplySWChecksumOnNB - will compute and set software offloads for a given NBL. Signed-off-by: Alin Gabriel Serdean <aserd...@cloudbasesolutions.com> --- datapath-windows/ovsext/BufferMgmt.c | 106 +++++++++++++++++++++++++++++++++++ datapath-windows/ovsext/BufferMgmt.h | 21 ++++++- datapath-windows/ovsext/Gre.c | 79 ++------------------------ datapath-windows/ovsext/Stt.c | 15 +---- datapath-windows/ovsext/Vxlan.c | 79 ++------------------------ 5 files changed, 135 insertions(+), 165 deletions(-) diff --git a/datapath-windows/ovsext/BufferMgmt.c b/datapath-windows/ovsext/BufferMgmt.c index 7ec073b..e9d339c 100644 --- a/datapath-windows/ovsext/BufferMgmt.c +++ b/datapath-windows/ovsext/BufferMgmt.c @@ -1311,6 +1311,112 @@ nblcopy_error: } /* + * OvsApplySWChecksumOnNB -- + * + * This function calculates and sets the required sofware offloads given by + * csumInfo for a given NBL(nbl) with a single NB. + * + */ +NDIS_STATUS +OvsApplySWChecksumOnNB(POVS_PACKET_HDR_INFO layers, + PNET_BUFFER_LIST nbl, + PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo) +{ + PNET_BUFFER curNb; + PMDL curMdl; + PUINT8 bufferStart; + UINT32 packetLength = 0; + ASSERT(nbl != NULL); + + curNb = NET_BUFFER_LIST_FIRST_NB(nbl); + ASSERT(curNb->Next == NULL); + packetLength = NET_BUFFER_DATA_LENGTH(curNb); + curMdl = NET_BUFFER_CURRENT_MDL(curNb); + bufferStart = (PUINT8)MmGetSystemAddressForMdlSafe(curMdl, + LowPagePriority); + if (!bufferStart) { + return NDIS_STATUS_RESOURCES; + } + + bufferStart += NET_BUFFER_CURRENT_MDL_OFFSET(curNb); + + if (layers->isIPv4) { + IPHdr *ip = (IPHdr *)(bufferStart + layers->l3Offset); + + if (csumInfo->Transmit.IpHeaderChecksum) { + ip->check = 0; + ip->check = IPChecksum((UINT8 *)ip, 4 * ip->ihl, 0); + } + + if (layers->isTcp && csumInfo->Transmit.TcpChecksum) { + UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset); + TCPHdr *tcp = (TCPHdr *)(bufferStart + layers->l4Offset); + tcp->check = IPPseudoChecksum(&ip->saddr, &ip->daddr, + IPPROTO_TCP, csumLength); + tcp->check = CalculateChecksumNB(curNb, csumLength, + (UINT32)(layers->l4Offset)); + } else if (layers->isUdp && csumInfo->Transmit.UdpChecksum) { + UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset); + UDPHdr *udp = (UDPHdr *)((PCHAR)ip + sizeof *ip); + udp->check = IPPseudoChecksum(&ip->saddr, &ip->daddr, + IPPROTO_UDP, csumLength); + udp->check = CalculateChecksumNB(curNb, csumLength, + (UINT32)(layers->l4Offset)); + } + } else if (layers->isIPv6) { + IPv6Hdr *ip = (IPv6Hdr *)(bufferStart + layers->l3Offset); + + if (layers->isTcp && csumInfo->Transmit.TcpChecksum) { + UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset); + TCPHdr *tcp = (TCPHdr *)(bufferStart + layers->l4Offset); + tcp->check = IPv6PseudoChecksum((UINT32 *) &ip->saddr, + (UINT32 *) &ip->daddr, + IPPROTO_TCP, csumLength); + tcp->check = CalculateChecksumNB(curNb, csumLength, + (UINT32)(layers->l4Offset)); + } else if (layers->isUdp && csumInfo->Transmit.UdpChecksum) { + UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset); + UDPHdr *udp = (UDPHdr *)((PCHAR)ip + sizeof *ip); + udp->check = IPv6PseudoChecksum((UINT32 *) &ip->saddr, + (UINT32 *) &ip->daddr, + IPPROTO_UDP, csumLength); + udp->check = CalculateChecksumNB(curNb, csumLength, + (UINT32)(layers->l4Offset)); + } + } + + return NDIS_STATUS_SUCCESS; +} + +/* + * OVSGetTcpMSS -- + * + * This function returns the maximum segment size of the given NBL. It takes + * into consideration both LSO v1 and v2. + */ +ULONG +OVSGetTcpMSS(PNET_BUFFER_LIST nbl) +{ + NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO lsoInfo; + ASSERT(nbl != NULL); + + lsoInfo.Value = NET_BUFFER_LIST_INFO(nbl, + TcpLargeSendNetBufferListInfo); + switch (lsoInfo.Transmit.Type) { + case NDIS_TCP_LARGE_SEND_OFFLOAD_V1_TYPE: + return lsoInfo.LsoV1Transmit.MSS; + break; + case NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE: + return lsoInfo.LsoV2Transmit.MSS; + break; + default: + OVS_LOG_ERROR("Unknown LSO transmit type:%d", + lsoInfo.Transmit.Type); + return 0; + } +} + +/* * -------------------------------------------------------------------------- * OvsAllocateNBLFromBuffer -- * diff --git a/datapath-windows/ovsext/BufferMgmt.h b/datapath-windows/ovsext/BufferMgmt.h index 79abc3d..3f44b9b 100644 --- a/datapath-windows/ovsext/BufferMgmt.h +++ b/datapath-windows/ovsext/BufferMgmt.h @@ -63,7 +63,6 @@ typedef union _OVS_BUFFER_CONTEXT { UINT64 value[MEM_ALIGN_SIZE(16) >> 3]; } OVS_BUFFER_CONTEXT, *POVS_BUFFER_CONTEXT; - typedef struct _OVS_NBL_POOL { NDIS_SWITCH_CONTEXT ndisContext; NDIS_HANDLE ndisHandle; @@ -83,11 +82,13 @@ typedef struct _OVS_NBL_POOL { NDIS_STATUS OvsInitBufferPool(PVOID context); + VOID OvsCleanupBufferPool(PVOID context); PNET_BUFFER_LIST OvsAllocateFixSizeNBL(PVOID context, UINT32 size, UINT32 headRoom); + PNET_BUFFER_LIST OvsAllocateVariableSizeNBL(PVOID context, UINT32 size, UINT32 headRoom); @@ -106,22 +107,36 @@ PNET_BUFFER_LIST OvsPartialCopyToMultipleNBLs(PVOID context, UINT32 copySize, UINT32 headRoom, BOOLEAN copyNblInfo); + PNET_BUFFER_LIST OvsFullCopyNBL(PVOID context, PNET_BUFFER_LIST nbl, UINT32 headRoom, BOOLEAN copyNblInfo); + PNET_BUFFER_LIST OvsTcpSegmentNBL(PVOID context, PNET_BUFFER_LIST nbl, POVS_PACKET_HDR_INFO hdrInfo, UINT32 MSS, UINT32 headRoom); + PNET_BUFFER_LIST OvsAllocateNBLFromBuffer(PVOID context, PVOID buffer, ULONG length); -PNET_BUFFER_LIST OvsFullCopyToMultipleNBLs(PVOID context, - PNET_BUFFER_LIST nbl, UINT32 headRoom, BOOLEAN copyNblInfo); + +PNET_BUFFER_LIST OvsFullCopyToMultipleNBLs(PVOID context, PNET_BUFFER_LIST nbl, + UINT32 headRoom, + BOOLEAN copyNblInfo); + PNET_BUFFER_LIST OvsCompleteNBL(PVOID context, PNET_BUFFER_LIST nbl, BOOLEAN updateRef); + NDIS_STATUS OvsSetCtxSourcePortNo(PNET_BUFFER_LIST nbl, UINT32 portNo); NDIS_STATUS OvsGetCtxSourcePortNo(PNET_BUFFER_LIST nbl, UINT32 *portNo); +ULONG OVSGetTcpMSS(PNET_BUFFER_LIST nbl); + +NDIS_STATUS OvsApplySWChecksumOnNB(POVS_PACKET_HDR_INFO layers, + PNET_BUFFER_LIST nbl, + PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO + csumInfo); + #endif /* __BUFFER_MGMT_H_ */ diff --git a/datapath-windows/ovsext/Gre.c b/datapath-windows/ovsext/Gre.c index 5abd4a4..fbba930 100644 --- a/datapath-windows/ovsext/Gre.c +++ b/datapath-windows/ovsext/Gre.c @@ -147,21 +147,8 @@ OvsDoEncapGre(POVS_VPORT_ENTRY vport, packetLength = NET_BUFFER_DATA_LENGTH(curNb); if (layers->isTcp) { - NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO tsoInfo; - - tsoInfo.Value = NET_BUFFER_LIST_INFO(curNbl, - TcpLargeSendNetBufferListInfo); - switch (tsoInfo.Transmit.Type) { - case NDIS_TCP_LARGE_SEND_OFFLOAD_V1_TYPE: - mss = tsoInfo.LsoV1Transmit.MSS; - break; - case NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE: - mss = tsoInfo.LsoV2Transmit.MSS; - break; - default: - OVS_LOG_ERROR("Unknown LSO transmit type:%d", - tsoInfo.Transmit.Type); - } + mss = OVSGetTcpMSS(curNbl); + OVS_LOG_TRACE("MSS %u packet len %u", mss, packetLength); if (mss) { @@ -188,71 +175,15 @@ OvsDoEncapGre(POVS_VPORT_ENTRY vport, OVS_LOG_ERROR("Unable to copy NBL"); return NDIS_STATUS_FAILURE; } - /* - * To this point we do not have GRE hardware offloading. - * Apply defined checksums - */ - curNb = NET_BUFFER_LIST_FIRST_NB(*newNbl); - curMdl = NET_BUFFER_CURRENT_MDL(curNb); - bufferStart = (PUINT8)MmGetSystemAddressForMdlSafe(curMdl, - LowPagePriority); - if (!bufferStart) { - status = NDIS_STATUS_RESOURCES; - goto ret_error; - } NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo); - bufferStart += NET_BUFFER_CURRENT_MDL_OFFSET(curNb); - - if (layers->isIPv4) { - IPHdr *ip = (IPHdr *)(bufferStart + layers->l3Offset); - - if (csumInfo.Transmit.IpHeaderChecksum) { - ip->check = 0; - ip->check = IPChecksum((UINT8 *)ip, 4 * ip->ihl, 0); - } - - if (layers->isTcp && csumInfo.Transmit.TcpChecksum) { - UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset); - TCPHdr *tcp = (TCPHdr *)(bufferStart + layers->l4Offset); - tcp->check = IPPseudoChecksum(&ip->saddr, &ip->daddr, - IPPROTO_TCP, csumLength); - tcp->check = CalculateChecksumNB(curNb, csumLength, - (UINT32)(layers->l4Offset)); - } else if (layers->isUdp && csumInfo.Transmit.UdpChecksum) { - UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset); - UDPHdr *udp = (UDPHdr *)((PCHAR)ip + sizeof *ip); - udp->check = IPPseudoChecksum(&ip->saddr, &ip->daddr, - IPPROTO_UDP, csumLength); - udp->check = CalculateChecksumNB(curNb, csumLength, - (UINT32)(layers->l4Offset)); - } - } else if (layers->isIPv6) { - IPv6Hdr *ip = (IPv6Hdr *)(bufferStart + layers->l3Offset); - - if (layers->isTcp && csumInfo.Transmit.TcpChecksum) { - UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset); - TCPHdr *tcp = (TCPHdr *)(bufferStart + layers->l4Offset); - tcp->check = IPv6PseudoChecksum((UINT32 *) &ip->saddr, - (UINT32 *) &ip->daddr, - IPPROTO_TCP, csumLength); - tcp->check = CalculateChecksumNB(curNb, csumLength, - (UINT32)(layers->l4Offset)); - } else if (layers->isUdp && csumInfo.Transmit.UdpChecksum) { - UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset); - UDPHdr *udp = (UDPHdr *)((PCHAR)ip + sizeof *ip); - udp->check = IPv6PseudoChecksum((UINT32 *) &ip->saddr, - (UINT32 *) &ip->daddr, - IPPROTO_UDP, csumLength); - udp->check = CalculateChecksumNB(curNb, csumLength, - (UINT32)(layers->l4Offset)); - } + status = OvsApplySWChecksumOnNB(layers, *newNbl, &csumInfo); + if (status != NDIS_STATUS_SUCCESS) { + goto ret_error; } - /* Clear out TcpIpChecksumNetBufferListInfo flag */ - NET_BUFFER_LIST_INFO(*newNbl, TcpIpChecksumNetBufferListInfo) = 0; } curNbl = *newNbl; diff --git a/datapath-windows/ovsext/Stt.c b/datapath-windows/ovsext/Stt.c index 0ae2633..6da0ac9 100644 --- a/datapath-windows/ovsext/Stt.c +++ b/datapath-windows/ovsext/Stt.c @@ -163,20 +163,7 @@ OvsDoEncapStt(POVS_VPORT_ENTRY vport, BOOLEAN innerPartialChecksum = FALSE; if (layers->isTcp) { - lsoInfo.Value = NET_BUFFER_LIST_INFO(curNbl, - TcpLargeSendNetBufferListInfo); - - switch (lsoInfo.Transmit.Type) { - case NDIS_TCP_LARGE_SEND_OFFLOAD_V1_TYPE: - mss = lsoInfo.LsoV1Transmit.MSS; - break; - case NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE: - mss = lsoInfo.LsoV2Transmit.MSS; - break; - default: - OVS_LOG_ERROR("Unknown LSO transmit type:%d", - lsoInfo.Transmit.Type); - } + mss = OVSGetTcpMSS(curNbl); } vportStt = (POVS_STT_VPORT) GetOvsVportPriv(vport); diff --git a/datapath-windows/ovsext/Vxlan.c b/datapath-windows/ovsext/Vxlan.c index 2516ece..813fe42 100644 --- a/datapath-windows/ovsext/Vxlan.c +++ b/datapath-windows/ovsext/Vxlan.c @@ -201,21 +201,8 @@ OvsDoEncapVxlan(POVS_VPORT_ENTRY vport, packetLength = NET_BUFFER_DATA_LENGTH(curNb); if (layers->isTcp) { - NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO tsoInfo; - - tsoInfo.Value = NET_BUFFER_LIST_INFO(curNbl, - TcpLargeSendNetBufferListInfo); - switch (tsoInfo.Transmit.Type) { - case NDIS_TCP_LARGE_SEND_OFFLOAD_V1_TYPE: - mss = tsoInfo.LsoV1Transmit.MSS; - break; - case NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE: - mss = tsoInfo.LsoV2Transmit.MSS; - break; - default: - OVS_LOG_ERROR("Unknown LSO transmit type:%d", - tsoInfo.Transmit.Type); - } + mss = OVSGetTcpMSS(curNbl); + OVS_LOG_TRACE("MSS %u packet len %u", mss, packetLength); if (mss) { @@ -242,70 +229,14 @@ OvsDoEncapVxlan(POVS_VPORT_ENTRY vport, OVS_LOG_ERROR("Unable to copy NBL"); return NDIS_STATUS_FAILURE; } - /* - * To this point we do not have VXLAN offloading. - * Apply defined checksums - */ - curNb = NET_BUFFER_LIST_FIRST_NB(*newNbl); - curMdl = NET_BUFFER_CURRENT_MDL(curNb); - bufferStart = (PUINT8)MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority); - if (!bufferStart) { - status = NDIS_STATUS_RESOURCES; - goto ret_error; - } - NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo); + status = OvsApplySWChecksumOnNB(layers, *newNbl, &csumInfo); - bufferStart += NET_BUFFER_CURRENT_MDL_OFFSET(curNb); - - if (layers->isIPv4) { - IPHdr *ip = (IPHdr *)(bufferStart + layers->l3Offset); - - if (csumInfo.Transmit.IpHeaderChecksum) { - ip->check = 0; - ip->check = IPChecksum((UINT8 *)ip, 4 * ip->ihl, 0); - } - - if (layers->isTcp && csumInfo.Transmit.TcpChecksum) { - UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset); - TCPHdr *tcp = (TCPHdr *)(bufferStart + layers->l4Offset); - tcp->check = IPPseudoChecksum(&ip->saddr, &ip->daddr, - IPPROTO_TCP, csumLength); - tcp->check = CalculateChecksumNB(curNb, csumLength, - (UINT32)(layers->l4Offset)); - } else if (layers->isUdp && csumInfo.Transmit.UdpChecksum) { - UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset); - UDPHdr *udp = (UDPHdr *)((PCHAR)ip + sizeof *ip); - udp->check = IPPseudoChecksum(&ip->saddr, &ip->daddr, - IPPROTO_UDP, csumLength); - udp->check = CalculateChecksumNB(curNb, csumLength, - (UINT32)(layers->l4Offset)); - } - } else if (layers->isIPv6) { - IPv6Hdr *ip = (IPv6Hdr *)(bufferStart + layers->l3Offset); - - if (layers->isTcp && csumInfo.Transmit.TcpChecksum) { - UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset); - TCPHdr *tcp = (TCPHdr *)(bufferStart + layers->l4Offset); - tcp->check = IPv6PseudoChecksum((UINT32 *) &ip->saddr, - (UINT32 *) &ip->daddr, - IPPROTO_TCP, csumLength); - tcp->check = CalculateChecksumNB(curNb, csumLength, - (UINT32)(layers->l4Offset)); - } else if (layers->isUdp && csumInfo.Transmit.UdpChecksum) { - UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset); - UDPHdr *udp = (UDPHdr *)((PCHAR)ip + sizeof *ip); - udp->check = IPv6PseudoChecksum((UINT32 *) &ip->saddr, - (UINT32 *) &ip->daddr, - IPPROTO_UDP, csumLength); - udp->check = CalculateChecksumNB(curNb, csumLength, - (UINT32)(layers->l4Offset)); - } + if (status != NDIS_STATUS_SUCCESS) { + goto ret_error; } - /* Clear out TcpIpChecksumNetBufferListInfo flag */ - NET_BUFFER_LIST_INFO(*newNbl, TcpIpChecksumNetBufferListInfo) = 0; } curNbl = *newNbl; -- 1.9.5.msysgit.0 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev