summaryrefslogtreecommitdiff
path: root/datapath-windows/ovsext/BufferMgmt.c
diff options
context:
space:
mode:
Diffstat (limited to 'datapath-windows/ovsext/BufferMgmt.c')
-rw-r--r--datapath-windows/ovsext/BufferMgmt.c119
1 files changed, 80 insertions, 39 deletions
diff --git a/datapath-windows/ovsext/BufferMgmt.c b/datapath-windows/ovsext/BufferMgmt.c
index 3189e9b61..00db31f04 100644
--- a/datapath-windows/ovsext/BufferMgmt.c
+++ b/datapath-windows/ovsext/BufferMgmt.c
@@ -1122,11 +1122,10 @@ static NDIS_STATUS
FixSegmentHeader(PNET_BUFFER nb, UINT16 segmentSize, UINT32 seqNumber,
BOOLEAN lastPacket, UINT16 packetCounter)
{
- EthHdr *dstEth;
- IPHdr *dstIP;
- TCPHdr *dstTCP;
- PMDL mdl;
- PUINT8 bufferStart;
+ EthHdr *dstEth = NULL;
+ TCPHdr *dstTCP = NULL;
+ PMDL mdl = NULL;
+ PUINT8 bufferStart = NULL;
mdl = NET_BUFFER_FIRST_MDL(nb);
@@ -1135,44 +1134,86 @@ FixSegmentHeader(PNET_BUFFER nb, UINT16 segmentSize, UINT32 seqNumber,
return NDIS_STATUS_RESOURCES;
}
dstEth = (EthHdr *)(bufferStart + NET_BUFFER_CURRENT_MDL_OFFSET(nb));
- ASSERT((INT)MmGetMdlByteCount(mdl) - NET_BUFFER_CURRENT_MDL_OFFSET(nb)
- >= sizeof(EthHdr) + sizeof(IPHdr) + sizeof(TCPHdr));
- dstIP = (IPHdr *)((PCHAR)dstEth + sizeof *dstEth);
- dstTCP = (TCPHdr *)((PCHAR)dstIP + dstIP->ihl * 4);
- ASSERT((INT)MmGetMdlByteCount(mdl) - NET_BUFFER_CURRENT_MDL_OFFSET(nb)
- >= sizeof(EthHdr) + dstIP->ihl * 4 + TCP_HDR_LEN(dstTCP));
-
- /* 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);
- /*
- * 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;
+ switch (dstEth->Type) {
+ case ETH_TYPE_IPV4_NBO:
+ {
+ IPHdr *dstIP = NULL;
+
+ ASSERT((INT)MmGetMdlByteCount(mdl) - NET_BUFFER_CURRENT_MDL_OFFSET(nb)
+ >= sizeof(EthHdr) + sizeof(IPHdr) + sizeof(TCPHdr));
+ dstIP = (IPHdr *)((PCHAR)dstEth + sizeof(*dstEth));
+ dstTCP = (TCPHdr *)((PCHAR)dstIP + dstIP->ihl * 4);
+ ASSERT((INT)MmGetMdlByteCount(mdl) - NET_BUFFER_CURRENT_MDL_OFFSET(nb)
+ >= sizeof(EthHdr) + dstIP->ihl * 4 + TCP_HDR_LEN(dstTCP));
+
+ /* 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);
+ dstTCP->seq = htonl(seqNumber);
+
+ /*
+ * 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,
+ csumLength,
+ sizeof(*dstEth) + dstIP->ihl * 4);
+ break;
+ }
+ case ETH_TYPE_IPV6_NBO:
+ {
+ IPv6Hdr *dstIP = NULL;
+
+ ASSERT((INT)MmGetMdlByteCount(mdl) - NET_BUFFER_CURRENT_MDL_OFFSET(nb)
+ >= sizeof(EthHdr) + sizeof(IPv6Hdr) + sizeof(TCPHdr));
+ dstIP = (IPv6Hdr *)((PCHAR)dstEth + sizeof(*dstEth));
+ dstTCP = (TCPHdr *)((PCHAR)dstIP + sizeof(IPv6Hdr));
+ ASSERT((INT)MmGetMdlByteCount(mdl) - NET_BUFFER_CURRENT_MDL_OFFSET(nb)
+ >= sizeof(EthHdr) + sizeof(IPv6Hdr) + TCP_HDR_LEN(dstTCP));
+
+ /* Fix IP length */
+ ASSERT(dstIP->nexthdr == IPPROTO_TCP);
+ dstIP->payload_len = htons(segmentSize + sizeof(IPv6Hdr) + TCP_HDR_LEN(dstTCP));
+
+ dstTCP->seq = htonl(seqNumber);
+ if (dstTCP->fin) {
+ dstTCP->fin = lastPacket;
+ }
+ if (dstTCP->psh) {
+ dstTCP->psh = lastPacket;
+ }
+
+ UINT16 csumLength = segmentSize + TCP_HDR_LEN(dstTCP);
+ dstTCP->check = IPv6PseudoChecksum((UINT32*)&dstIP->saddr,
+ (UINT32*)&dstIP->daddr,
+ IPPROTO_TCP,
+ csumLength);
+ dstTCP->check = CalculateChecksumNB(nb,
+ csumLength,
+ sizeof(*dstEth) + sizeof(IPv6Hdr));
+ break;
}
- if (dstTCP->psh) {
- dstTCP->psh = lastPacket;
+ default:
+ OVS_LOG_ERROR("Invalid eth type: %d\n", dstEth->Type);
+ ASSERT(! "Invalid eth type");
}
- UINT16 csumLength = segmentSize + TCP_HDR_LEN(dstTCP);
- dstTCP->check = IPPseudoChecksum(&dstIP->saddr,
- &dstIP->daddr,
- IPPROTO_TCP,
- csumLength);
- dstTCP->check = CalculateChecksumNB(nb,
- csumLength,
- sizeof *dstEth + dstIP->ihl * 4);
-
return STATUS_SUCCESS;
}