Message ID | 1453342590-6020-1-git-send-email-aserdean@cloudbasesolutions.com |
---|---|
State | Not Applicable |
Headers | show |
Hi Alin, Thanks for the change. Only suggestion I had is to add the new functions to Checksum.c. If you are concerned about the name Checksum.c, we could rename it to Offloads.c. BufferMgmt[ch] is for NBL clone/copy/split etc. Thanks, -- Nithin -----Original Message----- From: dev <dev-bounces@openvswitch.org> on behalf of Alin Serdean <aserdean@cloudbasesolutions.com> Date: Wednesday, January 20, 2016 at 6:16 PM To: "dev@openvswitch.org" <dev@openvswitch.org> Subject: [ovs-dev] [PATCH] datapath-windows: Refactor sofware offloads and mss >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 <aserdean@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 >https://urldefense.proofpoint.com/v2/url?u=http-3A__openvswitch.org_mailma >n_listinfo_dev&d=BQIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=pN >HQcdr7B40b4h6Yb7FIedI1dnBsxdDuTLBYD3JqV80&m=lA-zFUIHGjKzRsuCQlabvoqaPOSkhy >LBBfCtVAO1yWg&s=CYx1ZKx7e6g6lYzTZcgMiwz3T29NwhO3E5lNyTzgF08&e=
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;
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 <aserdean@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(-)