diff options
author | Yin Lin <linyi@vmware.com> | 2017-06-09 15:16:06 -0700 |
---|---|---|
committer | Gurucharan Shetty <guru@ovn.org> | 2017-06-12 12:08:07 -0700 |
commit | b7a6b3a76be7227a4cdaa5610553aa84f34d88fb (patch) | |
tree | 595dbe0b37b524d675eb2b18e86b097090fbb390 /datapath-windows/ovsext/Actions.c | |
parent | 560cc32cf50a31682a72ca7b42fde64c92114f09 (diff) | |
download | openvswitch-b7a6b3a76be7227a4cdaa5610553aa84f34d88fb.tar.gz |
datapath-windows: NAT integration with conntrack
This patch integrates NAT module with existing conntrack module. NAT
action is now supported.
Signed-off-by: Yin Lin <linyi@vmware.com>
Acked-by: Alin Gabriel Serdean <aserdean@cloudbasesolutions.com>
Signed-off-by: Gurucharan Shetty <guru@ovn.org>
Diffstat (limited to 'datapath-windows/ovsext/Actions.c')
-rw-r--r-- | datapath-windows/ovsext/Actions.c | 119 |
1 files changed, 116 insertions, 3 deletions
diff --git a/datapath-windows/ovsext/Actions.c b/datapath-windows/ovsext/Actions.c index c3f036290..668825bbf 100644 --- a/datapath-windows/ovsext/Actions.c +++ b/datapath-windows/ovsext/Actions.c @@ -1380,7 +1380,7 @@ PUINT8 OvsGetHeaderBySize(OvsForwardingContext *ovsFwdCtx, * based on the specified key. *---------------------------------------------------------------------------- */ -static __inline NDIS_STATUS +NDIS_STATUS OvsUpdateUdpPorts(OvsForwardingContext *ovsFwdCtx, const struct ovs_key_udp *udpAttr) { @@ -1427,7 +1427,7 @@ OvsUpdateUdpPorts(OvsForwardingContext *ovsFwdCtx, * based on the specified key. *---------------------------------------------------------------------------- */ -static __inline NDIS_STATUS +NDIS_STATUS OvsUpdateTcpPorts(OvsForwardingContext *ovsFwdCtx, const struct ovs_key_tcp *tcpAttr) { @@ -1465,12 +1465,125 @@ OvsUpdateTcpPorts(OvsForwardingContext *ovsFwdCtx, /* *---------------------------------------------------------------------------- + * OvsUpdateAddressAndPort -- + * Updates the source/destination IP and port fields in + * ovsFwdCtx.curNbl inline based on the specified key. + *---------------------------------------------------------------------------- + */ +NDIS_STATUS +OvsUpdateAddressAndPort(OvsForwardingContext *ovsFwdCtx, + UINT32 newAddr, UINT16 newPort, + BOOLEAN isSource, BOOLEAN isTx) +{ + PUINT8 bufferStart; + UINT32 hdrSize; + OVS_PACKET_HDR_INFO *layers = &ovsFwdCtx->layers; + IPHdr *ipHdr; + TCPHdr *tcpHdr = NULL; + UDPHdr *udpHdr = NULL; + UINT32 *addrField = NULL; + UINT16 *portField = NULL; + UINT16 *checkField = NULL; + BOOLEAN l4Offload = FALSE; + NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; + + ASSERT(layers->value != 0); + + if (layers->isTcp || layers->isUdp) { + hdrSize = layers->l4Offset + + layers->isTcp ? sizeof (*tcpHdr) : sizeof (*udpHdr); + } else { + hdrSize = layers->l3Offset + sizeof (*ipHdr); + } + + bufferStart = OvsGetHeaderBySize(ovsFwdCtx, hdrSize); + if (!bufferStart) { + return NDIS_STATUS_RESOURCES; + } + + ipHdr = (IPHdr *)(bufferStart + layers->l3Offset); + + if (layers->isTcp) { + tcpHdr = (TCPHdr *)(bufferStart + layers->l4Offset); + } else if (layers->isUdp) { + udpHdr = (UDPHdr *)(bufferStart + layers->l4Offset); + } + + csumInfo.Value = NET_BUFFER_LIST_INFO(ovsFwdCtx->curNbl, + TcpIpChecksumNetBufferListInfo); + /* + * Adjust the IP header inline as dictated by the action, and also update + * the IP and the TCP checksum for the data modified. + * + * In the future, this could be optimized to make one call to + * ChecksumUpdate32(). Ignoring this for now, since for the most common + * case, we only update the TTL. + */ + + if (isSource) { + addrField = &ipHdr->saddr; + if (tcpHdr) { + portField = &tcpHdr->source; + checkField = &tcpHdr->check; + l4Offload = isTx ? (BOOLEAN)csumInfo.Transmit.TcpChecksum : + ((BOOLEAN)csumInfo.Receive.TcpChecksumSucceeded || + (BOOLEAN)csumInfo.Receive.TcpChecksumFailed); + } else if (udpHdr) { + portField = &udpHdr->source; + checkField = &udpHdr->check; + l4Offload = isTx ? (BOOLEAN)csumInfo.Transmit.UdpChecksum : + ((BOOLEAN)csumInfo.Receive.UdpChecksumSucceeded || + (BOOLEAN)csumInfo.Receive.UdpChecksumFailed); + } + } else { + addrField = &ipHdr->daddr; + if (tcpHdr) { + portField = &tcpHdr->dest; + checkField = &tcpHdr->check; + } else if (udpHdr) { + portField = &udpHdr->dest; + checkField = &udpHdr->check; + } + } + if (*addrField != newAddr) { + UINT32 oldAddr = *addrField; + if (checkField && *checkField != 0) { + if (l4Offload) { + /* Recompute IP pseudo checksum */ + *checkField = ~(*checkField); + *checkField = ChecksumUpdate32(*checkField, oldAddr, + newAddr); + *checkField = ~(*checkField); + } else { + *checkField = ChecksumUpdate32(*checkField, oldAddr, + newAddr); + } + } + if (ipHdr->check != 0) { + ipHdr->check = ChecksumUpdate32(ipHdr->check, oldAddr, + newAddr); + } + *addrField = newAddr; + } + + if (portField && *portField != newPort) { + if (checkField && !l4Offload) { + *checkField = ChecksumUpdate16(*checkField, *portField, + newPort); + } + *portField = newPort; + } + return NDIS_STATUS_SUCCESS; +} + +/* + *---------------------------------------------------------------------------- * OvsUpdateIPv4Header -- * Updates the IPv4 header in ovsFwdCtx.curNbl inline based on the * specified key. *---------------------------------------------------------------------------- */ -static __inline NDIS_STATUS +NDIS_STATUS OvsUpdateIPv4Header(OvsForwardingContext *ovsFwdCtx, const struct ovs_key_ipv4 *ipAttr) { |