@@ -1116,7 +1116,8 @@ GetSegmentHeaderInfo(PNET_BUFFER_LIST nbl,
* --------------------------------------------------------------------------
*/
static NDIS_STATUS
-FixSegmentHeader(PNET_BUFFER nb, UINT16 segmentSize, UINT32 seqNumber)
+FixSegmentHeader(PNET_BUFFER nb, UINT16 segmentSize, UINT32 seqNumber,
+ BOOLEAN lastPacket, UINT16 packetCounter)
{
EthHdr *dstEth;
IPHdr *dstIP;
@@ -1141,18 +1142,29 @@ FixSegmentHeader(PNET_BUFFER nb, UINT16 segmentSize, UINT32 seqNumber)
/* Fix IP length and checksum */
ASSERT(dstIP->protocol == IPPROTO_TCP);
dstIP->tot_len = htons(segmentSize + dstIP->ihl * 4 + TCP_HDR_LEN(dstTCP));
+ dstIP->id += packetCounter;
dstIP->check = 0;
dstIP->check = IPChecksum((UINT8 *)dstIP, dstIP->ihl * 4, 0);
/* Fix TCP checksum */
dstTCP->seq = htonl(seqNumber);
- dstTCP->check =
- IPPseudoChecksum((UINT32 *)&dstIP->saddr,
- (UINT32 *)&dstIP->daddr,
- IPPROTO_TCP, segmentSize + TCP_HDR_LEN(dstTCP));
+
+ if (dstTCP->fin) {
+ dstTCP->fin = lastPacket;
+ }
+ if (dstTCP->psh) {
+ dstTCP->psh = lastPacket;
+ }
+
+ UINT16 csumLength = segmentSize + TCP_HDR_LEN(dstTCP);;
SV: Double semicolons at the end of the line.
+ dstTCP->check = IPPseudoChecksum(&dstIP->saddr,
+ &dstIP->daddr,
+ IPPROTO_TCP,
+ csumLength);
SV: Improper alignment above.
dstTCP->check = CalculateChecksumNB(nb,
- (UINT16)(NET_BUFFER_DATA_LENGTH(nb) - sizeof *dstEth - dstIP->ihl * 4),
- sizeof *dstEth + dstIP->ihl * 4);
+ csumLength,
+ sizeof *dstEth + dstIP->ihl * 4);
SV: Improper alignment above.
+
return STATUS_SUCCESS;
}
@@ -1190,6 +1202,7 @@ OvsTcpSegmentNBL(PVOID ovsContext,
NDIS_STATUS status;
UINT16 segmentSize;
ULONG copiedSize;
+ UINT16 packetCounter = 0;
srcCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl);
if (srcCtx == NULL || srcCtx->magic != OVS_CTX_MAGIC) { @@ -1232,7 +1245,9 @@ OvsTcpSegmentNBL(PVOID ovsContext,
goto nblcopy_error;
}
- status = FixSegmentHeader(newNb, segmentSize, seqNumber);
+ status = FixSegmentHeader(newNb, segmentSize, seqNumber,
+ NET_BUFFER_NEXT_NB(newNb) == NULL,
+ packetCounter);
if (status != NDIS_STATUS_SUCCESS) {
goto nblcopy_error;
}
@@ -1241,6 +1256,7 @@ OvsTcpSegmentNBL(PVOID ovsContext,
/* Move on to the next segment */
size -= segmentSize;
seqNumber += segmentSize;
+ packetCounter++;
}
status = OvsAllocateNBLContext(context, newNbl); diff --git a/datapath-windows/ovsext/Checksum.c b/datapath-windows/ovsext/Checksum.c
@@ -68,34 +68,48 @@ CalculateOnesComplement(UINT8 *start, {
UINT64 sum = 0, val;
UINT64 *src = (UINT64 *)start;
- union {
- UINT32 val;
- UINT8 b8[4];
- } tmp;
-
while (totalLength > 7) {
val = *src;
- sum += (val >> 32) + (val & 0xffffffff);
+ sum += val;
+ if (sum < val) sum++;
src++;
totalLength -= 8;
}
+
+ start = (UINT8 *)src;
+
if (totalLength > 3) {
- sum += *(UINT32 *)src;
- src = (UINT64 *)((UINT8 *)src + 4);
+ UINT32 val = *(UINT32 *)start;
+ sum += val;
+ if (sum < val) sum++;
+ start += 4;
totalLength -= 4;
}
- start = (UINT8 *)src;
- tmp.val = 0;
- switch (totalLength) {
- case 3:
- tmp.b8[2] = start[2];
- case 2:
- tmp.b8[1] = start[1];
- case 1:
- tmp.b8[0] = start[0];
- sum += tmp.val;
+
+ if (totalLength > 1) {
+ UINT16 val = *(UINT16 *)start;
+ sum += val;
+ if (sum < val) sum++;
+ start += 2;
+ totalLength -= 2;
}
- sum = (isEvenStart ? sum : swap64(sum)) + initial;
+
+ if (totalLength > 0) {
+ UINT8 val = *start;
+ sum += val;
+ if (sum < val) sum++;
+ start += 1;
+ totalLength -= 1;
+ }
+ ASSERT(totalLength == 0);
+
+ if (!isEvenStart) {
+ sum = _byteswap_uint64(sum);
+ }
+
+ sum += initial;
+ if (sum < initial) sum++;
+
return sum;
}
@@ -428,6 +442,7 @@ CalculateChecksumNB(const PNET_BUFFER nb,
ULONG firstMdlLen;
/* Running count of bytes in remainder of the MDLs including current. */
ULONG packetLen;
+ BOOLEAN swapEnd = 1 & csumDataLen;
if ((nb == NULL) || (csumDataLen == 0)
|| (offset >= NET_BUFFER_DATA_LENGTH(nb)) @@ -482,10 +497,8 @@ CalculateChecksumNB(const PNET_BUFFER nb,
while (csumDataLen && (currentMdl != NULL)) {
ASSERT(mdlLen < 65536);
csLen = MIN((UINT16) mdlLen, csumDataLen);
- //XXX Not handling odd bytes yet.
- ASSERT(((csLen & 0x1) == 0) || csumDataLen <= mdlLen);
- csum = CalculateOnesComplement(src, csLen, csum, TRUE);
+ csum = CalculateOnesComplement(src, csLen, csum, !(1 &
+ csumDataLen));
fold64(csum);
csumDataLen -= csLen;
@@ -504,9 +517,14 @@ CalculateChecksumNB(const PNET_BUFFER nb,
}
}
+ fold64(csum);
ASSERT(csumDataLen == 0);
ASSERT((csum & ~0xffff) == 0);
- return (UINT16) ~csum;
+ csum = (UINT16)~csum;
+ if (swapEnd) {
+ return _byteswap_ushort((UINT16)csum);
+ }
+ return (UINT16)csum;
}
/*
@@ -152,9 +152,9 @@ OvsCleanupVxlanTunnel(PIRP irp,
if (vxlanPort->filterID != 0) {
status = OvsTunnelFilterDelete(irp,
- vxlanPort->filterID,
- callback,
- tunnelContext);
+ vxlanPort->filterID,
+ callback,
+ tunnelContext);
} else {
OvsFreeMemoryWithTag(vport->priv, OVS_VXLAN_POOL_TAG);
vport->priv = NULL;
@@ -190,6 +190,9 @@ OvsDoEncapVxlan(POVS_VPORT_ENTRY vport,
POVS_VXLAN_VPORT vportVxlan;
UINT32 headRoom = OvsGetVxlanTunHdrSize();
UINT32 packetLength;
+ NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo;
+ csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl,
+
+ TcpIpChecksumNetBufferListInfo);
/*
* XXX: the assumption currently is that the NBL is owned by OVS, and @@ -198,20 +201,24 @@ OvsDoEncapVxlan(POVS_VPORT_ENTRY vport,