Hi Sai, Please see the comments inline.
Thanks, Paul > -----Original Message----- > From: Sairam Venugopal [mailto:vsai...@vmware.com] > Sent: Saturday, April 30, 2016 11:38 AM > To: Paul Boca; dev@openvswitch.org > Subject: Re: [ovs-dev] [PATCH V3] datapath-windows: Improved offloading on > STT tunnel > > Hey Paul, > > Thanks for clarifying what OvsExtractLayers was doing. You shouldn¹t have > to extract the layers info for the inner packet since they can be derived > from the STT Header Flags - especially when it¹s CSUM_Partial. That¹s even > mentioned in the STT IETF draft under the STT Flags section - > https://tools.ietf.org/html/draft-davie-stt-08. This definitely impacts > the efficiency of STT. PB: That's true, in case of CSUM_Partial I extract the info from STT header with few exceptions explained below. For CSUM_Verified I'll move extract layers after because it isn't needed. > > Are you running into issues when the inner checksum isn¹t computed and the > STT flags mention otherwise? If yes, then that¹s a bug in the Encap side > of things. I would test a similar setup on KVM and verify if it works. The > function - OvsDecapSetOffloads mimics what KVM does - > https://github.com/openvswitch/ovs/blob/d271907f817db25be8da8d425ac256 > d7ed8 > c96a9/datapath/linux/compat/stt.c#L1222 and handles the case when the > inner checksum is partially computed. When inner checksum is already > computed, why is it necessary to update the IP version of the csumInfo? > Since we don¹t request any further offloads. PB: I've tested Win-to-Win and Lin-to-Win connections and encountered some issues regarding checksums and how flags are set. In __push_stt_header function https://github.com/openvswitch/ovs/blob/ d271907f817db25be8da8d425ac256d7ed8c96a9/datapath/linux/compat/stt.c#L566 only CHECKSUM_PARTIAL and CHECKSUM_UNNECESSARY is verified, ignoring CHECKSUM_COMPLETE and CHECKSUM_NONE in skb->ip_summed. This leads to packets with STT header flags set to 0 even if the checksum is not computed/verified. In case of LSO I added code to recompute pseudo-checksum because I get invalid pseudo-check from Linux on CSUM_Partial case. If I understood the explanation correctly from http://lxr.free-electrons.com/source/include/linux/skbuff.h#L204 skb->ip_summed field is always set to CHECKSUM_PARTIAL in case of LSO. I will rename back OvsDecapApplyOffloads to OvsDecapSetOffloads. > > Moreover, using OvsGetExternalMTU for the inner VM¹s MSS is also > incorrect. Ideally we should be able to retrieve the MTU of the inner VM > and use that or require that a certain default MTU should be set for the > inner VMs. Were you able to test this by changing the MTU of external > adapter without changing that of the inner VM? PB: When I tested, I changed MTU only in VM and now I tried to change MTU for external adapter but it doesn't seem to have any effect on sent packets, OvsGetExternalMtu returns 1500 always. > > I don¹t think the STT header flags can be 0. We should probably get it > confirmed from some other person on the OVS team. If you are encountering > any issues with the current STT setup, please file a bug. There is a > higher likelihood of having a bug in OvsSttEncap(). Although, I see an > advantage in differentiating OvsExtractLayers from OvsExtractFlows, I am > still unsure if this patch improves STT offloading. Do correct me if my > understanding is off. PB: I couldn't find in STT specs if this can be 0 but it happens in some cases to be 0 In Linux-to-Windows connections. > > Thanks, > Sairam > > > On 4/27/16, 12:25 AM, "Paul Boca" <pb...@cloudbasesolutions.com> wrote: > > >Added OvsExtractLayers - populates only the layers field without > >unnecessary > >memory operations for flow part > >If in STT header the flags are 0 then force packets checksums calculation > >Ensure correct pseudo checksum is set for LSO both on send and receive > > > >Signed-off-by: Paul-Daniel Boca <pb...@cloudbasesolutions.com> > >--- > >v2: Fixed a NULL pointer dereference. > > Removed some unused local variables and multiple initializations. > >v3: Use LSO V2 in OvsDoEncapStt > > Fixed alignment and code style > > Use IpHdr TTL for fragment expiration on receive instead 30s > >--- > > datapath-windows/ovsext/Flow.c | 243 > >++++++++++++++++++++++++++++----- > > datapath-windows/ovsext/Flow.h | 2 + > > datapath-windows/ovsext/PacketParser.c | 97 +++++++------ > > datapath-windows/ovsext/PacketParser.h | 8 +- > > datapath-windows/ovsext/Stt.c | 157 +++++++++++++++++---- > > datapath-windows/ovsext/Stt.h | 1 - > > datapath-windows/ovsext/User.c | 20 +-- > > 7 files changed, 413 insertions(+), 115 deletions(-) > > > >diff --git a/datapath-windows/ovsext/Flow.c > >b/datapath-windows/ovsext/Flow.c > >index 1f23625..a49a60c 100644 > >--- a/datapath-windows/ovsext/Flow.c > >+++ b/datapath-windows/ovsext/Flow.c > >@@ -1566,7 +1566,8 @@ _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs, > > > > ndKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ND]); > > RtlCopyMemory(&icmp6FlowPutKey->ndTarget, > >- ndKey->nd_target, sizeof > >(icmp6FlowPutKey->ndTarget)); > >+ ndKey->nd_target, > >+ sizeof (icmp6FlowPutKey->ndTarget)); > > RtlCopyMemory(icmp6FlowPutKey->arpSha, > > ndKey->nd_sll, ETH_ADDR_LEN); > > RtlCopyMemory(icmp6FlowPutKey->arpTha, > >@@ -1596,8 +1597,10 @@ _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs, > > arpFlowPutKey->nwSrc = arpKey->arp_sip; > > arpFlowPutKey->nwDst = arpKey->arp_tip; > > > >- RtlCopyMemory(arpFlowPutKey->arpSha, arpKey->arp_sha, > >ETH_ADDR_LEN); > >- RtlCopyMemory(arpFlowPutKey->arpTha, arpKey->arp_tha, > >ETH_ADDR_LEN); > >+ RtlCopyMemory(arpFlowPutKey->arpSha, arpKey->arp_sha, > >+ ETH_ADDR_LEN); > >+ RtlCopyMemory(arpFlowPutKey->arpTha, arpKey->arp_tha, > >+ ETH_ADDR_LEN); > > /* Kernel datapath assumes 'arpFlowPutKey->nwProto' to be in > >host > > * order. */ > > arpFlowPutKey->nwProto = (UINT8)ntohs((arpKey->arp_op)); > >@@ -1846,29 +1849,195 @@ OvsGetFlowMetadata(OvsFlowKey *key, > > return status; > > } > > > >+ > > /* > >- > >*------------------------------------------------------------------------- > >--- > >- * Initializes 'flow' members from 'packet', 'skb_priority', 'tun_id', > >and > >- * 'ofp_in_port'. > >- * > >- * Initializes 'packet' header pointers as follows: > >- * > >- * - packet->l2 to the start of the Ethernet header. > >- * > >- * - packet->l3 to just past the Ethernet header, or just past the > >- * vlan_header if one is present, to the first byte of the payload > >of the > >- * Ethernet frame. > >- * > >- * - packet->l4 to just past the IPv4 header, if one is present and > >has a > >- * correct length, and otherwise NULL. > >- * > >- * - packet->l7 to just past the TCP, UDP, SCTP or ICMP header, if > >one is > >- * present and has a correct length, and otherwise NULL. > >- * > >- * Returns NDIS_STATUS_SUCCESS normally. Fails only if packet data > >cannot be accessed > >- * (e.g. if Pkt_CopyBytesOut() returns an error). > >- > >*------------------------------------------------------------------------- > >--- > >- */ > >+*------------------------------------------------------------------------ > >---- > >+* Initializes 'layers' members from 'packet' > >+* > >+* Initializes 'layers' header pointers as follows: > >+* > >+* - layers->l2 to the start of the Ethernet header. > >+* > >+* - layers->l3 to just past the Ethernet header, or just past the > >+* vlan_header if one is present, to the first byte of the payload > >of the > >+* Ethernet frame. > >+* > >+* - layers->l4 to just past the IPv4 header, if one is present and > >has a > >+* correct length, and otherwise NULL. > >+* > >+* - layers->l7 to just past the TCP, UDP, SCTP or ICMP header, if one > >is > >+* present and has a correct length, and otherwise NULL. > >+* > >+* - layers->isIPv4/isIPv6/isTcp/isUdp/isSctp based on the packet type > >+* > >+* Returns NDIS_STATUS_SUCCESS normally. > >+* Fails only if packet data cannot be accessed. > >+* (e.g. if OvsParseIPv6() returns an error). > >+*------------------------------------------------------------------------ > >---- > >+*/ > >+NDIS_STATUS > >+OvsExtractLayers(const NET_BUFFER_LIST *packet, > >+ POVS_PACKET_HDR_INFO layers) > >+{ > >+ struct Eth_Header *eth; > >+ UINT8 offset = 0; > >+ PVOID vlanTagValue; > >+ ovs_be16 dlType; > >+ > >+ layers->value = 0; > >+ > >+ /* Link layer. */ > >+ eth = (Eth_Header *)GetStartAddrNBL((NET_BUFFER_LIST *)packet); > >+ > >+ /* > >+ * vlan_tci. > >+ */ > >+ vlanTagValue = NET_BUFFER_LIST_INFO(packet, > >Ieee8021QNetBufferListInfo); > >+ if (!vlanTagValue) { > >+ if (eth->dix.typeNBO == ETH_TYPE_802_1PQ_NBO) { > >+ offset = sizeof(Eth_802_1pq_Tag); > >+ } > >+ > >+ /* > >+ * XXX Please note after this point, src mac and dst mac should > >+ * not be accessed through eth > >+ */ > >+ eth = (Eth_Header *)((UINT8 *)eth + offset); > >+ } > >+ > >+ /* > >+ * dl_type. > >+ * > >+ * XXX assume that at least the first > >+ * 12 bytes of received packets are mapped. This code has the > >stronger > >+ * assumption that at least the first 22 bytes of 'packet' is mapped > >(if my > >+ * arithmetic is right). > >+ */ > >+ if (ETH_TYPENOT8023(eth->dix.typeNBO)) { > >+ dlType = eth->dix.typeNBO; > >+ layers->l3Offset = ETH_HEADER_LEN_DIX + offset; > >+ } else if (OvsPacketLenNBL(packet) >= ETH_HEADER_LEN_802_3 && > >+ eth->e802_3.llc.dsap == 0xaa && > >+ eth->e802_3.llc.ssap == 0xaa && > >+ eth->e802_3.llc.control == ETH_LLC_CONTROL_UFRAME && > >+ eth->e802_3.snap.snapOrg[0] == 0x00 && > >+ eth->e802_3.snap.snapOrg[1] == 0x00 && > >+ eth->e802_3.snap.snapOrg[2] == 0x00) { > >+ dlType = eth->e802_3.snap.snapType.typeNBO; > >+ layers->l3Offset = ETH_HEADER_LEN_802_3 + offset; > >+ } else { > >+ dlType = htons(OVSWIN_DL_TYPE_NONE); > >+ layers->l3Offset = ETH_HEADER_LEN_DIX + offset; > >+ } > >+ > >+ /* Network layer. */ > >+ if (dlType == htons(ETH_TYPE_IPV4)) { > >+ struct IPHdr ip_storage; > >+ const struct IPHdr *nh; > >+ > >+ layers->isIPv4 = 1; > >+ nh = OvsGetIp(packet, layers->l3Offset, &ip_storage); > >+ if (nh) { > >+ layers->l4Offset = layers->l3Offset + nh->ihl * 4; > >+ > >+ if (!(nh->frag_off & htons(IP_OFFSET))) { > >+ if (nh->protocol == SOCKET_IPPROTO_TCP) { > >+ OvsParseTcp(packet, NULL, layers); > >+ } else if (nh->protocol == SOCKET_IPPROTO_UDP) { > >+ OvsParseUdp(packet, NULL, layers); > >+ } else if (nh->protocol == SOCKET_IPPROTO_SCTP) { > >+ OvsParseSctp(packet, NULL, layers); > >+ } else if (nh->protocol == SOCKET_IPPROTO_ICMP) { > >+ ICMPHdr icmpStorage; > >+ const ICMPHdr *icmp; > >+ > >+ icmp = OvsGetIcmp(packet, layers->l4Offset, > >&icmpStorage); > >+ if (icmp) { > >+ layers->l7Offset = layers->l4Offset + sizeof > >*icmp; > >+ } > >+ } > >+ } > >+ } > >+ } else if (dlType == htons(ETH_TYPE_IPV6)) { > >+ NDIS_STATUS status; > >+ Ipv6Key ipv6Key; > >+ > >+ status = OvsParseIPv6(packet, &ipv6Key, layers); > >+ if (status != NDIS_STATUS_SUCCESS) { > >+ return status; > >+ } > >+ layers->isIPv6 = 1; > >+ > >+ if (ipv6Key.nwProto == SOCKET_IPPROTO_TCP) { > >+ OvsParseTcp(packet, &(ipv6Key.l4), layers); > >+ } else if (ipv6Key.nwProto == SOCKET_IPPROTO_UDP) { > >+ OvsParseUdp(packet, &(ipv6Key.l4), layers); > >+ } else if (ipv6Key.nwProto == SOCKET_IPPROTO_SCTP) { > >+ OvsParseSctp(packet, &ipv6Key.l4, layers); > >+ } else if (ipv6Key.nwProto == SOCKET_IPPROTO_ICMPV6) { > >+ Icmp6Key icmp6Key; > >+ OvsParseIcmpV6(packet, NULL, &icmp6Key, layers); > >+ } > >+ } else if (OvsEthertypeIsMpls(dlType)) { > >+ MPLSHdr mplsStorage; > >+ const MPLSHdr *mpls; > >+ > >+ /* > >+ * In the presence of an MPLS label stack the end of the L2 > >+ * header and the beginning of the L3 header differ. > >+ * > >+ * A network packet may contain multiple MPLS labels, but we > >+ * are only interested in the topmost label stack entry. > >+ * > >+ * Advance network header to the beginning of the L3 header. > >+ * layers->l3Offset corresponds to the end of the L2 header. > >+ */ > >+ for (UINT32 i = 0; i < FLOW_MAX_MPLS_LABELS; i++) { > >+ mpls = OvsGetMpls(packet, layers->l3Offset, &mplsStorage); > >+ if (!mpls) { > >+ break; > >+ } > >+ > >+ layers->l3Offset += MPLS_HLEN; > >+ layers->l4Offset += MPLS_HLEN; > >+ > >+ if (mpls->lse & htonl(MPLS_BOS_MASK)) { > >+ /* > >+ * Bottom of Stack bit is set, which means there are no > >+ * remaining MPLS labels in the packet. > >+ */ > >+ break; > >+ } > >+ } > >+ } > >+ > >+ return NDIS_STATUS_SUCCESS; > >+} > >+ > >+/* > >+*------------------------------------------------------------------------ > >---- > >+* Initializes 'flow' members from 'packet', 'skb_priority', 'tun_id', and > >+* 'ofp_in_port'. > >+* > >+* Initializes 'packet' header pointers as follows: > >+* > >+* - packet->l2 to the start of the Ethernet header. > >+* > >+* - packet->l3 to just past the Ethernet header, or just past the > >+* vlan_header if one is present, to the first byte of the payload > >of the > >+* Ethernet frame. > >+* > >+* - packet->l4 to just past the IPv4 header, if one is present and > >has a > >+* correct length, and otherwise NULL. > >+* > >+* - packet->l7 to just past the TCP, UDP, SCTP or ICMP header, if one > >is > >+* present and has a correct length, and otherwise NULL. > >+* > >+* Returns NDIS_STATUS_SUCCESS normally. > >+* Fails only if packet data cannot be accessed. > >+* (e.g. if Pkt_CopyBytesOut() returns an error). > >+*------------------------------------------------------------------------ > >---- > >+*/ > > NDIS_STATUS > > OvsExtractFlow(const NET_BUFFER_LIST *packet, > > UINT32 inPort, > >@@ -1900,8 +2069,8 @@ OvsExtractFlow(const NET_BUFFER_LIST *packet, > > > > /* Link layer. */ > > eth = (Eth_Header *)GetStartAddrNBL((NET_BUFFER_LIST *)packet); > >- memcpy(flow->l2.dlSrc, eth->src, ETH_ADDR_LENGTH); > >- memcpy(flow->l2.dlDst, eth->dst, ETH_ADDR_LENGTH); > >+ RtlCopyMemory(flow->l2.dlSrc, eth->src, ETH_ADDR_LENGTH); > >+ RtlCopyMemory(flow->l2.dlDst, eth->dst, ETH_ADDR_LENGTH); > > > > /* > > * vlan_tci. > >@@ -1923,8 +2092,7 @@ OvsExtractFlow(const NET_BUFFER_LIST *packet, > > flow->l2.vlanTci = 0; > > } > > /* > >- * XXX > >- * Please note after this point, src mac and dst mac should > >+ * XXX Please note after this point, src mac and dst mac should > > * not be accessed through eth > > */ > > eth = (Eth_Header *)((UINT8 *)eth + offset); > >@@ -1955,7 +2123,8 @@ OvsExtractFlow(const NET_BUFFER_LIST *packet, > > layers->l3Offset = ETH_HEADER_LEN_DIX + offset; > > } > > > >- flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE - > >flow->l2.offset; > >+ flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE > >+ - flow->l2.offset; > > /* Network layer. */ > > if (flow->l2.dlType == htons(ETH_TYPE_IPV4)) { > > struct IPHdr ip_storage; > >@@ -2012,9 +2181,9 @@ OvsExtractFlow(const NET_BUFFER_LIST *packet, > > } else if (flow->l2.dlType == htons(ETH_TYPE_IPV6)) { > > NDIS_STATUS status; > > flow->l2.keyLen += OVS_IPV6_KEY_SIZE; > >- status = OvsParseIPv6(packet, flow, layers); > >+ status = OvsParseIPv6(packet, &flow->ipv6Key, layers); > > if (status != NDIS_STATUS_SUCCESS) { > >- memset(&flow->ipv6Key, 0, sizeof (Ipv6Key)); > >+ RtlZeroMemory(&flow->ipv6Key, sizeof (Ipv6Key)); > > return status; > > } > > layers->isIPv6 = 1; > >@@ -2029,7 +2198,7 @@ OvsExtractFlow(const NET_BUFFER_LIST *packet, > > } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_SCTP) { > > OvsParseSctp(packet, &flow->ipv6Key.l4, layers); > > } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_ICMPV6) { > >- OvsParseIcmpV6(packet, flow, layers); > >+ OvsParseIcmpV6(packet, &flow->ipv6Key, &flow->icmp6Key, > >layers); > > flow->l2.keyLen += (OVS_ICMPV6_KEY_SIZE - OVS_IPV6_KEY_SIZE); > > } > > } else if (flow->l2.dlType == htons(ETH_TYPE_ARP)) { > >@@ -2051,10 +2220,10 @@ OvsExtractFlow(const NET_BUFFER_LIST *packet, > > } > > if (arpKey->nwProto == ARPOP_REQUEST > > || arpKey->nwProto == ARPOP_REPLY) { > >- memcpy(&arpKey->nwSrc, arp->arp_spa, 4); > >- memcpy(&arpKey->nwDst, arp->arp_tpa, 4); > >- memcpy(arpKey->arpSha, arp->arp_sha, ETH_ADDR_LENGTH); > >- memcpy(arpKey->arpTha, arp->arp_tha, ETH_ADDR_LENGTH); > >+ RtlCopyMemory(&arpKey->nwSrc, arp->arp_spa, 4); > >+ RtlCopyMemory(&arpKey->nwDst, arp->arp_tpa, 4); > >+ RtlCopyMemory(arpKey->arpSha, arp->arp_sha, > >ETH_ADDR_LENGTH); > >+ RtlCopyMemory(arpKey->arpTha, arp->arp_tha, > >ETH_ADDR_LENGTH); > > } > > } > > } else if (OvsEthertypeIsMpls(flow->l2.dlType)) { > >diff --git a/datapath-windows/ovsext/Flow.h > >b/datapath-windows/ovsext/Flow.h > >index 310c472..88240b5 100644 > >--- a/datapath-windows/ovsext/Flow.h > >+++ b/datapath-windows/ovsext/Flow.h > >@@ -53,6 +53,8 @@ NDIS_STATUS OvsAllocateFlowTable(OVS_DATAPATH > *datapath, > > > > NDIS_STATUS OvsGetFlowMetadata(OvsFlowKey *key, > > PNL_ATTR *keyAttrs); > >+NDIS_STATUS OvsExtractLayers(const NET_BUFFER_LIST *packet, > >+ POVS_PACKET_HDR_INFO layers); > > NDIS_STATUS OvsExtractFlow(const NET_BUFFER_LIST *pkt, UINT32 inPort, > > OvsFlowKey *flow, POVS_PACKET_HDR_INFO layers, > > OvsIPv4TunnelKey *tunKey); > >diff --git a/datapath-windows/ovsext/PacketParser.c > >b/datapath-windows/ovsext/PacketParser.c > >index 93df342..c4a04d0 100644 > >--- a/datapath-windows/ovsext/PacketParser.c > >+++ b/datapath-windows/ovsext/PacketParser.c > >@@ -84,14 +84,13 @@ OvsGetPacketBytes(const NET_BUFFER_LIST *nbl, > > > > NDIS_STATUS > > OvsParseIPv6(const NET_BUFFER_LIST *packet, > >- OvsFlowKey *key, > >+ Ipv6Key *ipv6Key, > > POVS_PACKET_HDR_INFO layers) > > { > > UINT16 ofs = layers->l3Offset; > > IPv6Hdr ipv6HdrStorage; > > const IPv6Hdr *nh; > > UINT32 nextHdr; > >- Ipv6Key *flow= &key->ipv6Key; > > > > nh = OvsGetPacketBytes(packet, sizeof *nh, ofs, &ipv6HdrStorage); > > if (!nh) { > >@@ -99,15 +98,15 @@ OvsParseIPv6(const NET_BUFFER_LIST *packet, > > } > > > > nextHdr = nh->nexthdr; > >- memcpy(&flow->ipv6Src, nh->saddr.s6_addr, 16); > >- memcpy(&flow->ipv6Dst, nh->daddr.s6_addr, 16); > >+ RtlCopyMemory(&ipv6Key->ipv6Src, nh->saddr.s6_addr, 16); > >+ RtlCopyMemory(&ipv6Key->ipv6Dst, nh->daddr.s6_addr, 16); > > > >- flow->nwTos = ((nh->flow_lbl[0] & 0xF0) >> 4) | (nh->priority << 4); > >- flow->ipv6Label = > >+ ipv6Key->nwTos = ((nh->flow_lbl[0] & 0xF0) >> 4) | (nh->priority << > >4); > >+ ipv6Key->ipv6Label = > > ((nh->flow_lbl[0] & 0x0F) << 16) | (nh->flow_lbl[1] << 8) | > >nh->flow_lbl[2]; > >- flow->nwTtl = nh->hop_limit; > >- flow->nwProto = SOCKET_IPPROTO_NONE; > >- flow->nwFrag = OVS_FRAG_TYPE_NONE; > >+ ipv6Key->nwTtl = nh->hop_limit; > >+ ipv6Key->nwProto = SOCKET_IPPROTO_NONE; > >+ ipv6Key->nwFrag = OVS_FRAG_TYPE_NONE; > > > > // Parse extended headers and compute L4 offset > > ofs += sizeof(IPv6Hdr); > >@@ -160,9 +159,9 @@ OvsParseIPv6(const NET_BUFFER_LIST *packet, > > /* We only process the first fragment. */ > > if (fragHdr->offlg != htons(0)) { > > if ((fragHdr->offlg & IP6F_OFF_HOST_ORDER_MASK) == > >htons(0)) { > >- flow->nwFrag = OVS_FRAG_TYPE_FIRST; > >+ ipv6Key->nwFrag = OVS_FRAG_TYPE_FIRST; > > } else { > >- flow->nwFrag = OVS_FRAG_TYPE_LATER; > >+ ipv6Key->nwFrag = OVS_FRAG_TYPE_LATER; > > nextHdr = SOCKET_IPPROTO_FRAGMENT; > > break; > > } > >@@ -170,7 +169,7 @@ OvsParseIPv6(const NET_BUFFER_LIST *packet, > > } > > } > > > >- flow->nwProto = (UINT8)nextHdr; > >+ ipv6Key->nwProto = (UINT8)nextHdr; > > layers->l4Offset = ofs; > > return NDIS_STATUS_SUCCESS; > > } > >@@ -183,10 +182,14 @@ OvsParseTcp(const NET_BUFFER_LIST *packet, > > TCPHdr tcpStorage; > > const TCPHdr *tcp = OvsGetTcp(packet, layers->l4Offset, &tcpStorage); > > if (tcp) { > >- flow->tpSrc = tcp->source; > >- flow->tpDst = tcp->dest; > >- layers->isTcp = 1; > >- layers->l7Offset = layers->l4Offset + 4 * tcp->doff; > >+ if (flow) { > >+ flow->tpSrc = tcp->source; > >+ flow->tpDst = tcp->dest; > >+ } > >+ if (layers) { > >+ layers->isTcp = 1; > >+ layers->l7Offset = layers->l4Offset + 4 * tcp->doff; > >+ } > > } > > } > > > >@@ -198,10 +201,14 @@ OvsParseSctp(const NET_BUFFER_LIST *packet, > > SCTPHdr sctpStorage; > > const SCTPHdr *sctp = OvsGetSctp(packet, layers->l4Offset, > >&sctpStorage); > > if (sctp) { > >- flow->tpSrc = sctp->source; > >- flow->tpDst = sctp->dest; > >- layers->isSctp = 1; > >- layers->l7Offset = layers->l4Offset + sizeof *sctp; > >+ if (flow) { > >+ flow->tpSrc = sctp->source; > >+ flow->tpDst = sctp->dest; > >+ } > >+ if (layers) { > >+ layers->isSctp = 1; > >+ layers->l7Offset = layers->l4Offset + sizeof *sctp; > >+ } > > } > > } > > > >@@ -213,29 +220,33 @@ OvsParseUdp(const NET_BUFFER_LIST *packet, > > UDPHdr udpStorage; > > const UDPHdr *udp = OvsGetUdp(packet, layers->l4Offset, &udpStorage); > > if (udp) { > >- flow->tpSrc = udp->source; > >- flow->tpDst = udp->dest; > >- layers->isUdp = 1; > >- if (udp->check == 0) { > >- layers->udpCsumZero = 1; > >+ if (flow) { > >+ flow->tpSrc = udp->source; > >+ flow->tpDst = udp->dest; > >+ } > >+ if (layers) { > >+ layers->isUdp = 1; > >+ if (udp->check == 0) { > >+ layers->udpCsumZero = 1; > >+ } > >+ layers->l7Offset = layers->l4Offset + sizeof *udp; > > } > >- layers->l7Offset = layers->l4Offset + sizeof *udp; > > } > > } > > > > NDIS_STATUS > > OvsParseIcmpV6(const NET_BUFFER_LIST *packet, > >- OvsFlowKey *key, > >- POVS_PACKET_HDR_INFO layers) > >+ Ipv6Key *ipv6Key, > >+ Icmp6Key *icmp6Key, > >+ POVS_PACKET_HDR_INFO layers) > > { > > UINT16 ofs = layers->l4Offset; > > ICMPHdr icmpStorage; > > const ICMPHdr *icmp; > >- Icmp6Key *flow = &key->icmp6Key; > > > >- memset(&flow->ndTarget, 0, sizeof(flow->ndTarget)); > >- memset(flow->arpSha, 0, sizeof(flow->arpSha)); > >- memset(flow->arpTha, 0, sizeof(flow->arpTha)); > >+ memset(&icmp6Key->ndTarget, 0, sizeof(icmp6Key->ndTarget)); > >+ memset(icmp6Key->arpSha, 0, sizeof(icmp6Key->arpSha)); > >+ memset(icmp6Key->arpTha, 0, sizeof(icmp6Key->arpTha)); > > > > icmp = OvsGetIcmp(packet, ofs, &icmpStorage); > > if (!icmp) { > >@@ -247,8 +258,10 @@ OvsParseIcmpV6(const NET_BUFFER_LIST *packet, > > * The ICMPv6 type and code fields use the 16-bit transport port > > * fields, so we need to store them in 16-bit network byte order. > > */ > >- key->ipv6Key.l4.tpSrc = htons(icmp->type); > >- key->ipv6Key.l4.tpDst = htons(icmp->code); > >+ if (ipv6Key) { > >+ ipv6Key->l4.tpSrc = htons(icmp->type); > >+ ipv6Key->l4.tpDst = htons(icmp->code); > >+ } > > > > if (icmp->code == 0 && > > (icmp->type == ND_NEIGHBOR_SOLICIT || > >@@ -261,7 +274,7 @@ OvsParseIcmpV6(const NET_BUFFER_LIST *packet, > > if (!ndTarget) { > > return NDIS_STATUS_FAILURE; > > } > >- flow->ndTarget = *ndTarget; > >+ icmp6Key->ndTarget = *ndTarget; > > > > while ((UINT32)(ofs + 8) <= OvsPacketLenNBL(packet)) { > > /* > >@@ -288,14 +301,14 @@ OvsParseIcmpV6(const NET_BUFFER_LIST *packet, > > * layer option is specified twice. > > */ > > if (ndOpt->type == ND_OPT_SOURCE_LINKADDR && optLen == 8) { > >- if (Eth_IsNullAddr(flow->arpSha)) { > >- memcpy(flow->arpSha, ndOpt + 1, ETH_ADDR_LENGTH); > >+ if (Eth_IsNullAddr(icmp6Key->arpSha)) { > >+ memcpy(icmp6Key->arpSha, ndOpt + 1, ETH_ADDR_LENGTH); > > } else { > > goto invalid; > > } > > } else if (ndOpt->type == ND_OPT_TARGET_LINKADDR && optLen > >== 8) { > >- if (Eth_IsNullAddr(flow->arpTha)) { > >- memcpy(flow->arpTha, ndOpt + 1, ETH_ADDR_LENGTH); > >+ if (Eth_IsNullAddr(icmp6Key->arpTha)) { > >+ memcpy(icmp6Key->arpTha, ndOpt + 1, ETH_ADDR_LENGTH); > > } else { > > goto invalid; > > } > >@@ -309,9 +322,9 @@ OvsParseIcmpV6(const NET_BUFFER_LIST *packet, > > return NDIS_STATUS_SUCCESS; > > > > invalid: > >- memset(&flow->ndTarget, 0, sizeof(flow->ndTarget)); > >- memset(flow->arpSha, 0, sizeof(flow->arpSha)); > >- memset(flow->arpTha, 0, sizeof(flow->arpTha)); > >+ RtlZeroMemory(&icmp6Key->ndTarget, sizeof(icmp6Key->ndTarget)); > >+ RtlZeroMemory(icmp6Key->arpSha, sizeof(icmp6Key->arpSha)); > >+ RtlZeroMemory(icmp6Key->arpTha, sizeof(icmp6Key->arpTha)); > > > > return NDIS_STATUS_FAILURE; > > } > >diff --git a/datapath-windows/ovsext/PacketParser.h > >b/datapath-windows/ovsext/PacketParser.h > >index 47d227f..f1d7f28 100644 > >--- a/datapath-windows/ovsext/PacketParser.h > >+++ b/datapath-windows/ovsext/PacketParser.h > >@@ -22,7 +22,7 @@ > > > > const VOID* OvsGetPacketBytes(const NET_BUFFER_LIST *_pNB, UINT32 len, > > UINT32 SrcOffset, VOID *storage); > >-NDIS_STATUS OvsParseIPv6(const NET_BUFFER_LIST *packet, OvsFlowKey > *key, > >+NDIS_STATUS OvsParseIPv6(const NET_BUFFER_LIST *packet, Ipv6Key *key, > > POVS_PACKET_HDR_INFO layers); > > VOID OvsParseTcp(const NET_BUFFER_LIST *packet, L4Key *flow, > > POVS_PACKET_HDR_INFO layers); > >@@ -30,8 +30,10 @@ VOID OvsParseUdp(const NET_BUFFER_LIST *packet, > L4Key > >*flow, > > POVS_PACKET_HDR_INFO layers); > > VOID OvsParseSctp(const NET_BUFFER_LIST *packet, L4Key *flow, > > POVS_PACKET_HDR_INFO layers); > >-NDIS_STATUS OvsParseIcmpV6(const NET_BUFFER_LIST *packet, OvsFlowKey > >*key, > >- POVS_PACKET_HDR_INFO layers); > >+NDIS_STATUS OvsParseIcmpV6(const NET_BUFFER_LIST *packet, > >+ Ipv6Key *ipv6Key, > >+ Icmp6Key *flow, > >+ POVS_PACKET_HDR_INFO layers); > > > > static __inline ULONG > > OvsPacketLenNBL(const NET_BUFFER_LIST *_pNB) > >diff --git a/datapath-windows/ovsext/Stt.c b/datapath-windows/ovsext/Stt.c > >index dd7bf92..c547837 100644 > >--- a/datapath-windows/ovsext/Stt.c > >+++ b/datapath-windows/ovsext/Stt.c > >@@ -217,6 +217,8 @@ OvsDoEncapStt(POVS_VPORT_ENTRY vport, > > } else { > > innerPartialChecksum = TRUE; > > } > >+ } else if (!layers->isIPv4) { > >+ innerChecksumVerified = TRUE; > > } > > > > status = NdisRetreatNetBufferDataStart(curNb, headRoom, 0, NULL); > >@@ -231,8 +233,8 @@ OvsDoEncapStt(POVS_VPORT_ENTRY vport, > > * memory. > > */ > > curMdl = NET_BUFFER_CURRENT_MDL(curNb); > >- ASSERT((int) (MmGetMdlByteCount(curMdl) - > >NET_BUFFER_CURRENT_MDL_OFFSET(curNb)) > >- >= (int) headRoom); > >+ ASSERT((int) (MmGetMdlByteCount(curMdl) - > >+ NET_BUFFER_CURRENT_MDL_OFFSET(curNb)) >= (int) headRoom); > > > > buf = (PUINT8) MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority); > > if (!buf) { > >@@ -288,8 +290,10 @@ OvsDoEncapStt(POVS_VPORT_ENTRY vport, > > /* Calculate pseudo header chksum */ > > tcpChksumLen = sizeof(TCPHdr) + STT_HDR_LEN + innerFrameLen; > > ASSERT(tcpChksumLen < 65535); > >- outerTcpHdr->check = IPPseudoChecksum(&fwdInfo->srcIpAddr,(uint32 *) > >&tunKey->dst, > >- IPPROTO_TCP, (uint16) > >tcpChksumLen); > >+ outerTcpHdr->check = IPPseudoChecksum(&fwdInfo->srcIpAddr, > >+ (uint32 *) &tunKey->dst, > >+ IPPROTO_TCP, > >+ (uint16) tcpChksumLen); > > sttHdr->version = 0; > > > > /* Set STT Header */ > >@@ -327,8 +331,16 @@ OvsDoEncapStt(POVS_VPORT_ENTRY vport, > > NET_BUFFER_LIST_INFO(curNbl, > > TcpIpChecksumNetBufferListInfo) = > >csumInfo.Value; > > > >- UINT32 encapMss = OvsGetExternalMtu(switchContext) - sizeof(IPHdr) - > >sizeof(TCPHdr); > >+ UINT32 encapMss = OvsGetExternalMtu(switchContext) > >+ - sizeof(IPHdr) > >+ - sizeof(TCPHdr); > > if (ipTotalLen > encapMss) { > >+ outerIpHdr->check = IPChecksum((UINT8 *)outerIpHdr, > >+ sizeof *outerIpHdr, 0); > >+ outerTcpHdr->check = IPPseudoChecksum(&fwdInfo->srcIpAddr, > >+ (uint32 *) &tunKey->dst, > >+ IPPROTO_TCP, (uint16) 0); > >+ > > lsoInfo.Value = 0; > > lsoInfo.LsoV2Transmit.TcpHeaderOffset = tcpHeaderOffset; > > lsoInfo.LsoV2Transmit.MSS = encapMss; > >@@ -616,7 +628,8 @@ OvsSttReassemble(POVS_SWITCH_CONTEXT > switchContext, > > > > UINT64 currentTime; > > NdisGetCurrentSystemTime((LARGE_INTEGER *) ¤tTime); > >- entry->timeout = currentTime + STT_ENTRY_TIMEOUT; > >+ // use IpHdr TTL for fragment expiration > >+ entry->timeout = currentTime + ((UINT64)ipHdr->ttl*1000*1000*10); > > > > if (segOffset == 0) { > > entry->sttHdr = *sttHdr; > >@@ -655,7 +668,8 @@ handle_error: > > if (lastPacket) { > > /* Retrieve the original STT header */ > > NdisMoveMemory(newSttHdr, &pktFragEntry->sttHdr, sizeof > >(SttHdr)); > >- targetPNbl = OvsAllocateNBLFromBuffer(switchContext, > >pktFragEntry->packetBuf, > >+ targetPNbl = OvsAllocateNBLFromBuffer(switchContext, > >+ pktFragEntry->packetBuf, > > innerPacketLen); > > > > /* Delete this entry and free up the memory/ */ > >@@ -668,16 +682,68 @@ handle_error: > > return lastPacket ? targetPNbl : NULL; > > } > > > >-VOID > >-OvsDecapSetOffloads(PNET_BUFFER_LIST curNbl, SttHdr *sttHdr) > >+ > >+/* > >+*------------------------------------------------------------------------ > >---- > >+* OvsDecapApplyOffloads > >+* Processes received STT header and sets > >TcpIpChecksumNetBufferListInfo > >+* accordingly. > >+* For TCP packets with total length bigger than destination MSS it > >+* populates TcpLargeSendNetBufferListInfo. > >+* > >+* Returns NDIS_STATUS_SUCCESS normally. > >+* Fails only if packet data is invalid. > >+* (e.g. if OvsExtractLayers() returns an error). > >+*------------------------------------------------------------------------ > >---- > >+*/ > >+NDIS_STATUS > >+OvsDecapApplyOffloads(POVS_SWITCH_CONTEXT switchContext, > >+ PNET_BUFFER_LIST *curNbl, SttHdr *sttHdr) > > { > >- if ((sttHdr->flags & STT_CSUM_VERIFIED) > >- || !(sttHdr->flags & STT_CSUM_PARTIAL)) { > >- return; > >+ NDIS_STATUS status; > >+ OVS_PACKET_HDR_INFO layers; > >+ NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; > >+ > >+ // if STT_CSUM_PARTIAL is not set we have two options: > >+ // - STT_CSUM_VERIFIED is set - we only set IsIPv4/IsIPv6 > >+ // - no flag set - we must compute the checksums > >+ if (!(sttHdr->flags & STT_CSUM_PARTIAL)) { > >+ status = OvsExtractLayers(*curNbl, &layers); > >+ if (status != NDIS_STATUS_SUCCESS) { > >+ return status; > >+ } > >+ > >+ csumInfo.Value = 0; > >+ csumInfo.Transmit.IsIPv4 = layers.isIPv4; > >+ csumInfo.Transmit.IsIPv6 = layers.isIPv6; > >+ > >+ if (sttHdr->flags & STT_CSUM_VERIFIED) { > >+ NET_BUFFER_LIST_INFO(*curNbl, > >+ TcpIpChecksumNetBufferListInfo) = csumInfo.Value; > >+ return NDIS_STATUS_SUCCESS; > >+ } > >+ > >+ /* Set Transmit fields in order to calculate the checksums */ > >+ csumInfo.Transmit.IpHeaderChecksum = layers.isIPv4; > >+ csumInfo.Transmit.TcpChecksum = layers.isTcp; > >+ csumInfo.Transmit.UdpChecksum = layers.isUdp; > >+ > >+ status = OvsApplySWChecksumOnNB(&layers, *curNbl, &csumInfo); > >+ if (status != NDIS_STATUS_SUCCESS) { > >+ return status; > >+ } > >+ > >+ csumInfo.Value = 0; > >+ csumInfo.Transmit.IpHeaderChecksum = 0; > >+ csumInfo.Transmit.TcpChecksum = 0; > >+ csumInfo.Transmit.UdpChecksum = 0; > >+ NET_BUFFER_LIST_INFO(*curNbl, > >+ TcpIpChecksumNetBufferListInfo) = csumInfo.Value; > >+ > >+ return NDIS_STATUS_SUCCESS; > > } > > > > UINT8 protoType; > >- NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; > > csumInfo.Value = 0; > > csumInfo.Transmit.IpHeaderChecksum = 0; > > csumInfo.Transmit.TcpHeaderOffset = sttHdr->l4Offset; > >@@ -703,14 +769,58 @@ OvsDecapSetOffloads(PNET_BUFFER_LIST curNbl, > SttHdr > >*sttHdr) > > csumInfo.Transmit.IsIPv6 = 1; > > csumInfo.Transmit.UdpChecksum = 1; > > } > >- NET_BUFFER_LIST_INFO(curNbl, > >+ NET_BUFFER_LIST_INFO(*curNbl, > > TcpIpChecksumNetBufferListInfo) = > >csumInfo.Value; > > > > if (sttHdr->mss) { > > NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO lsoInfo; > >+ > >+ if (sttHdr->flags & STT_PROTO_TCP) > >+ { > >+ PMDL curMdl = NULL; > >+ PNET_BUFFER curNb; > >+ PUINT8 buf = NULL; > >+ > >+ status = OvsExtractLayers(*curNbl, &layers); > >+ if (status != NDIS_STATUS_SUCCESS) { > >+ return status; > >+ } > >+ > >+ curNb = NET_BUFFER_LIST_FIRST_NB(*curNbl); > >+ curMdl = NET_BUFFER_CURRENT_MDL(curNb); > >+ > >+ buf = (PUINT8)MmGetSystemAddressForMdlSafe(curMdl, > >+ LowPagePriority); > >+ buf += NET_BUFFER_CURRENT_MDL_OFFSET(curNb); > >+ > >+ // apply pseudo checksum on extracted packet > >+ if (sttHdr->flags & STT_PROTO_IPV4) { > >+ IPHdr *ipHdr; > >+ TCPHdr *tcpHdr; > >+ > >+ ipHdr = (IPHdr *)(buf + layers.l3Offset); > >+ tcpHdr = (TCPHdr *)(buf + layers.l4Offset); > >+ > > Sai: Why are you recomputing checksum here? Doesn¹t this mean your > previous changes have been reset? > > >+ tcpHdr->check = IPPseudoChecksum(&ipHdr->saddr, > >+ (uint32 *)&ipHdr->daddr, > >+ IPPROTO_TCP, 0); > >+ } else { > >+ IPv6Hdr *ipHdr; > >+ TCPHdr *tcpHdr; > >+ > >+ ipHdr = (IPv6Hdr *)(buf + layers.l3Offset); > >+ tcpHdr = (TCPHdr *)(buf + layers.l4Offset); > >+ > >+ tcpHdr->check = > >IPv6PseudoChecksum((UINT32*)&ipHdr->saddr, > >+ (UINT32*)&ipHdr->daddr, > >+ IPPROTO_TCP, 0); > >+ } > >+ } > >+ > >+ // setup LSO > > lsoInfo.Value = 0; > > lsoInfo.LsoV2Transmit.TcpHeaderOffset = sttHdr->l4Offset; > >- lsoInfo.LsoV2Transmit.MSS = ETH_DEFAULT_MTU > > Sai: We can¹t use the ExternalMTU as MSS for inner VM. > > >+ lsoInfo.LsoV2Transmit.MSS = OvsGetExternalMtu(switchContext) > > - sizeof(IPHdr) > > - sizeof(TCPHdr); > > lsoInfo.LsoV2Transmit.Type = > NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE; > >@@ -719,9 +829,11 @@ OvsDecapSetOffloads(PNET_BUFFER_LIST curNbl, > SttHdr > >*sttHdr) > > } else { > > lsoInfo.LsoV2Transmit.IPVersion = > >NDIS_TCP_LARGE_SEND_OFFLOAD_IPv6; > > } > >- NET_BUFFER_LIST_INFO(curNbl, > >+ NET_BUFFER_LIST_INFO(*curNbl, > > TcpLargeSendNetBufferListInfo) = > >lsoInfo.Value; > > } > >+ > >+ return NDIS_STATUS_SUCCESS; > > } > > > > /* > >@@ -736,15 +848,14 @@ OvsDecapStt(POVS_SWITCH_CONTEXT > switchContext, > > OvsIPv4TunnelKey *tunKey, > > PNET_BUFFER_LIST *newNbl) > > { > >- NDIS_STATUS status = NDIS_STATUS_FAILURE; > >- PNET_BUFFER curNb, newNb; > >+ NDIS_STATUS status; > >+ PNET_BUFFER curNb; > > IPHdr *ipHdr; > > char *ipBuf[sizeof(IPHdr)]; > > SttHdr stt; > > SttHdr *sttHdr; > > char *sttBuf[STT_HDR_LEN]; > > UINT32 advanceCnt, hdrLen; > >- BOOLEAN isLsoPacket = FALSE; > > > > curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); > > ASSERT(NET_BUFFER_NEXT_NB(curNb) == NULL); > >@@ -767,7 +878,7 @@ OvsDecapStt(POVS_SWITCH_CONTEXT switchContext, > > TCPHdr *tcp = (TCPHdr *)((PCHAR)ipHdr + ipHdr->ihl * 4); > > > > /* Skip IP & TCP headers */ > >- hdrLen = sizeof(IPHdr) + sizeof(TCPHdr), > >+ hdrLen = (ipHdr->ihl * 4) + (tcp->doff * 4); > > NdisAdvanceNetBufferDataStart(curNb, hdrLen, FALSE, NULL); > > advanceCnt += hdrLen; > > > >@@ -775,7 +886,7 @@ OvsDecapStt(POVS_SWITCH_CONTEXT switchContext, > > UINT32 totalLen = (seq >> STT_SEQ_LEN_SHIFT); > > UINT16 payloadLen = (UINT16)ntohs(ipHdr->tot_len) > > - (ipHdr->ihl * 4) > >- - (sizeof * tcp); > >+ - (tcp->doff * 4); > > > > /* Check if incoming packet requires reassembly */ > > if (totalLen != payloadLen) { > >@@ -788,7 +899,6 @@ OvsDecapStt(POVS_SWITCH_CONTEXT switchContext, > > } > > > > *newNbl = pNbl; > >- isLsoPacket = TRUE; > > } else { > > /* STT Header */ > > sttHdr = NdisGetDataBuffer(curNb, sizeof *sttHdr, > >@@ -812,7 +922,6 @@ OvsDecapStt(POVS_SWITCH_CONTEXT switchContext, > > OvsCompleteNBL(switchContext, *newNbl, TRUE); > > return NDIS_STATUS_FAILURE; > > } > >- newNb = NET_BUFFER_LIST_FIRST_NB(*newNbl); > > > > ASSERT(sttHdr); > > > >@@ -826,7 +935,7 @@ OvsDecapStt(POVS_SWITCH_CONTEXT switchContext, > > tunKey->pad = 0; > > > > /* Set Checksum and LSO offload flags */ > >- OvsDecapSetOffloads(*newNbl, sttHdr); > >+ OvsDecapApplyOffloads(switchContext, newNbl, sttHdr); > > > > return NDIS_STATUS_SUCCESS; > > } > >diff --git a/datapath-windows/ovsext/Stt.h b/datapath-windows/ovsext/Stt.h > >index a3e3915..20066e6 100644 > >--- a/datapath-windows/ovsext/Stt.h > >+++ b/datapath-windows/ovsext/Stt.h > >@@ -36,7 +36,6 @@ > > > > #define STT_HASH_TABLE_SIZE ((UINT32)1 << 10) > > #define STT_HASH_TABLE_MASK (STT_HASH_TABLE_SIZE - 1) > >-#define STT_ENTRY_TIMEOUT 300000000 // 30s > > #define STT_CLEANUP_INTERVAL 300000000 // 30s > > > > #define STT_ETH_PAD 2 > >diff --git a/datapath-windows/ovsext/User.c > >b/datapath-windows/ovsext/User.c > >index 34f38f4..33cbd89 100644 > >--- a/datapath-windows/ovsext/User.c > >+++ b/datapath-windows/ovsext/User.c > >@@ -459,7 +459,8 @@ NTSTATUS > > OvsPurgeDpIoctl(PFILE_OBJECT fileObject) > > { > > POVS_OPEN_INSTANCE instance = > >(POVS_OPEN_INSTANCE)fileObject->FsContext; > >- POVS_USER_PACKET_QUEUE queue = > >(POVS_USER_PACKET_QUEUE)instance->packetQueue; > >+ POVS_USER_PACKET_QUEUE queue = > >+ (POVS_USER_PACKET_QUEUE)instance->packetQueue; > > > > if (queue == NULL) { > > return STATUS_INVALID_PARAMETER; > >@@ -736,7 +737,8 @@ OvsCreateAndAddPackets(PVOID userData, > > NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO tsoInfo; > > UINT32 packetLength; > > > >- tsoInfo.Value = NET_BUFFER_LIST_INFO(nbl, > >TcpLargeSendNetBufferListInfo); > >+ tsoInfo.Value = NET_BUFFER_LIST_INFO(nbl, > >+ TcpLargeSendNetBufferListInfo); > > nb = NET_BUFFER_LIST_FIRST_NB(nbl); > > packetLength = NET_BUFFER_DATA_LENGTH(nb); > > > >@@ -838,7 +840,8 @@ OvsCompletePacketHeader(UINT8 *packet, > > (UINT32 > >*)&ipHdr->DestinationAddress, > > IPPROTO_TCP, > >hdrInfoOut->l4PayLoad); > > } else { > >- PIPV6_HEADER ipv6Hdr = (PIPV6_HEADER)(packet + > >hdrInfoIn->l3Offset); > >+ PIPV6_HEADER ipv6Hdr = (PIPV6_HEADER)(packet + > >+ hdrInfoIn->l3Offset); > > hdrInfoOut->l4PayLoad = > > (UINT16)(ntohs(ipv6Hdr->PayloadLength) + > > hdrInfoIn->l3Offset + sizeof(IPV6_HEADER)- > >@@ -852,9 +855,9 @@ OvsCompletePacketHeader(UINT8 *packet, > > hdrInfoOut->tcpCsumNeeded = 1; > > ovsUserStats.recalTcpCsum++; > > } else if (!isRecv) { > >- if (csumInfo.Transmit.TcpChecksum) { > >+ if (hdrInfoIn->isTcp && csumInfo.Transmit.TcpChecksum) { > > hdrInfoOut->tcpCsumNeeded = 1; > >- } else if (csumInfo.Transmit.UdpChecksum) { > >+ } else if (hdrInfoIn->isUdp && csumInfo.Transmit.UdpChecksum) { > > hdrInfoOut->udpCsumNeeded = 1; > > } > > if (hdrInfoOut->tcpCsumNeeded || hdrInfoOut->udpCsumNeeded) { > >@@ -864,7 +867,8 @@ OvsCompletePacketHeader(UINT8 *packet, > > hdrInfoOut->tcpCsumNeeded ? IPPROTO_TCP : IPPROTO_UDP; > > #endif > > if (hdrInfoIn->isIPv4) { > >- PIPV4_HEADER ipHdr = (PIPV4_HEADER)(packet + > >hdrInfoIn->l3Offset); > >+ PIPV4_HEADER ipHdr = (PIPV4_HEADER)(packet + > >+ hdrInfoIn->l3Offset); > > hdrInfoOut->l4PayLoad = > >(UINT16)(ntohs(ipHdr->TotalLength) - > > (ipHdr->HeaderLength << 2)); > > #ifdef DBG > >@@ -972,8 +976,8 @@ OvsCreateQueueNlPacket(PVOID userData, > > csumInfo.Value = NET_BUFFER_LIST_INFO(nbl, > >TcpIpChecksumNetBufferListInfo); > > > > if (isRecv && (csumInfo.Receive.TcpChecksumFailed || > >- (csumInfo.Receive.UdpChecksumFailed && > >!hdrInfo->udpCsumZero) || > >- csumInfo.Receive.IpChecksumFailed)) { > >+ (csumInfo.Receive.UdpChecksumFailed && > >!hdrInfo->udpCsumZero) || > >+ csumInfo.Receive.IpChecksumFailed)) { > > OVS_LOG_INFO("Packet dropped due to checksum failure."); > > ovsUserStats.dropDuetoChecksum++; > > return NULL; > >-- > >2.7.2.windows.1 > > > >_______________________________________________ > >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=Dc > >ruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=RdwsCDAI2yfo1TYwm > cBC9a_itZZsD- > >eTS48y7bP8hUk&s=Avc2We4lg6NREQbdMXwz-VDKZWtz17bHf4xvrocCeaY&e= > _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev