/*
- * Copyright (c) 2014 VMware, Inc.
+ * Copyright (c) 2014, 2016 VMware, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
#include "precomp.h"
+#include "Debug.h"
+#include "Flow.h"
+#include "Offload.h"
+#include "NetProto.h"
+#include "PacketParser.h"
#include "Switch.h"
+#include "Vport.h"
#ifdef OVS_DBG_MOD
#undef OVS_DBG_MOD
#endif
#define OVS_DBG_MOD OVS_DBG_BUFMGMT
-#include "Debug.h"
-#include "NetProto.h"
-#include "Flow.h"
-#include "Checksum.h"
-#include "PacketParser.h"
+
/*
* --------------------------------------------------------------------------
OvsInitNBLContext(ctx, OVS_BUFFER_FROM_FIX_SIZE_POOL |
OVS_BUFFER_PRIVATE_FORWARD_CONTEXT, size,
- OVS_DEFAULT_PORT_NO);
+ OVS_DPPORT_NUMBER_INVALID);
line = __LINE__;
allocate_done:
OVS_LOG_LOUD("Allocate Fix NBL: %p, line: %d", nbl, line);
OvsInitNBLContext(ctx, OVS_BUFFER_PRIVATE_MDL | OVS_BUFFER_PRIVATE_DATA |
OVS_BUFFER_PRIVATE_FORWARD_CONTEXT |
OVS_BUFFER_FROM_ZERO_SIZE_POOL,
- size, OVS_DEFAULT_PORT_NO);
+ size, OVS_DPPORT_NUMBER_INVALID);
OVS_LOG_LOUD("Allocate variable size NBL: %p", nbl);
return nbl;
* we use first nb to decide whether we need advance or retreat during
* complete.
*/
- OvsInitNBLContext(ctx, flags, NET_BUFFER_DATA_LENGTH(nb), OVS_DEFAULT_PORT_NO);
+ OvsInitNBLContext(ctx, flags, NET_BUFFER_DATA_LENGTH(nb),
+ OVS_DPPORT_NUMBER_INVALID);
return ctx;
}
srcNb = NET_BUFFER_LIST_FIRST_NB(nbl);
OvsInitNBLContext(dstCtx, flags, NET_BUFFER_DATA_LENGTH(srcNb) - copySize,
- OVS_DEFAULT_PORT_NO);
+ OVS_DPPORT_NUMBER_INVALID);
InterlockedIncrement((LONG volatile *)&srcCtx->refCount);
OVS_BUFFER_PRIVATE_FORWARD_CONTEXT;
OvsInitNBLContext(dstCtx, flags, NET_BUFFER_DATA_LENGTH(firstNb),
- OVS_DEFAULT_PORT_NO);
+ OVS_DPPORT_NUMBER_INVALID);
#ifdef DBG
OvsDumpNetBufferList(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;
/* 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));
+
+ /*
+ * Set the TCP FIN and PSH bit only for the last packet
+ * More information can be found under:
+ * https://msdn.microsoft.com/en-us/library/windows/hardware/ff568840%28v=vs.85%29.aspx
+ */
+ if (dstTCP->fin) {
+ dstTCP->fin = lastPacket;
+ }
+ if (dstTCP->psh) {
+ dstTCP->psh = lastPacket;
+ }
+
+ UINT16 csumLength = segmentSize + TCP_HDR_LEN(dstTCP);
+ dstTCP->check = IPPseudoChecksum(&dstIP->saddr,
+ &dstIP->daddr,
+ IPPROTO_TCP,
+ csumLength);
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);
+
return STATUS_SUCCESS;
}
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) {
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;
}
/* Move on to the next segment */
size -= segmentSize;
seqNumber += segmentSize;
+ packetCounter++;
}
status = OvsAllocateNBLContext(context, newNbl);
return NULL;
}
+/*
+ * --------------------------------------------------------------------------
+ * OvsAllocateNBLFromBuffer --
+ *
+ * This function allocates all the stuff necessary for creating an NBL from the
+ * input buffer of specified length, namely, a nonpaged data buffer of size
+ * length, an MDL from it, and a NB and NBL from it. It does not allocate an NBL
+ * context yet. It also copies data from the specified buffer to the NBL.
+ * --------------------------------------------------------------------------
+ */
+PNET_BUFFER_LIST
+OvsAllocateNBLFromBuffer(PVOID context,
+ PVOID buffer,
+ ULONG length)
+{
+ POVS_SWITCH_CONTEXT switchContext = (POVS_SWITCH_CONTEXT)context;
+ UINT8 *data = NULL;
+ PNET_BUFFER_LIST nbl = NULL;
+ PNET_BUFFER nb;
+ PMDL mdl;
+
+ if (length > OVS_DEFAULT_DATA_SIZE) {
+ nbl = OvsAllocateVariableSizeNBL(switchContext, length,
+ OVS_DEFAULT_HEADROOM_SIZE);
+
+ } else {
+ nbl = OvsAllocateFixSizeNBL(switchContext, length,
+ OVS_DEFAULT_HEADROOM_SIZE);
+ }
+ if (nbl == NULL) {
+ return NULL;
+ }
+
+ nb = NET_BUFFER_LIST_FIRST_NB(nbl);
+ mdl = NET_BUFFER_CURRENT_MDL(nb);
+ data = (PUINT8)MmGetSystemAddressForMdlSafe(mdl, LowPagePriority) +
+ NET_BUFFER_CURRENT_MDL_OFFSET(nb);
+ if (!data) {
+ OvsCompleteNBL(switchContext, nbl, TRUE);
+ return NULL;
+ }
+
+ NdisMoveMemory(data, buffer, length);
+
+ return nbl;
+}
/*
* --------------------------------------------------------------------------