summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/intro/install/windows.rst180
-rw-r--r--datapath-windows/ovsext/Actions.c1
-rw-r--r--datapath-windows/ovsext/Conntrack-ftp.c109
-rw-r--r--datapath-windows/ovsext/Conntrack-related.c30
-rw-r--r--datapath-windows/ovsext/Conntrack-tcp.c53
-rw-r--r--datapath-windows/ovsext/Conntrack.c77
-rw-r--r--datapath-windows/ovsext/Conntrack.h19
-rw-r--r--include/windows/netinet/in.h1
8 files changed, 345 insertions, 125 deletions
diff --git a/Documentation/intro/install/windows.rst b/Documentation/intro/install/windows.rst
index 0a392d781..44fc6ae37 100644
--- a/Documentation/intro/install/windows.rst
+++ b/Documentation/intro/install/windows.rst
@@ -852,78 +852,164 @@ related state.
normal scenario
Vif38(20::1, ofport:2)->Vif40(20:2, ofport:3)
- Vif38Name="podvif38"
- Vif40Name="podvif40"
+ Vif38Name="podvif70"
+ Vif40Name="Ethernet1"
Vif38Port=2
- Vif38Address="20::1"
- Vif38MacAddressCli="00-15-5D-F0-01-0b"
+ Vif38Address="20::88"
Vif40Port=3
- Vif40Address="20::2"
- Vif40MacAddressCli="00-15-5D-F0-01-0C"
+ Vif40Address="20::45"
+ Vif40MacAddressCli="00-50-56-98-9d-97"
+ Vif38MacAddressCli="00-15-5D-F0-01-0B"
Protocol="tcp6"
- > netsh int ipv6 set neighbors $Vif38Name $Vif40Address \
- $Vif40MacAddressCli
- > netsh int ipv6 set neighbors $Vif40Name $Vif38Address \
- $Vif38MacAddressCli
+ > netsh int ipv6 set neighbors $Vif38Name $Vif40Address $Vif40MacAddressCli
+ > netsh int ipv6 set neighbors $Vif42Name $Vif38Ip $Vif38MacAddressCli
> ovs-ofctl del-flows br-int --strict "table=0,priority=0"
- > ovs-ofctl add-flow br-int "table=0,priority=1,$Protocol \
+ > ovs-ofctl add-flow br-int "table=0,priority=1,$Protocol
actions=ct(table=1)"
- > ovs-ofctl add-flow br-int "table=1,priority=1,ct_state=+new+trk-est, \
+ > ovs-ofctl add-flow br-int "table=1,priority=1,tp_dst=21, $Protocol,\
+ actions=ct(commit,table=2,alg=ftp)"
+ > ovs-ofctl add-flow br-int "table=1,priority=1,tp_src=21, $Protocol,\
+ actions=ct(commit,table=2,alg=ftp)"
+ > ovs-ofctl add-flow br-int "table=1,priority=1, ct_state=+new+trk+rel,\
$Protocol,actions=ct(commit,table=2)"
> ovs-ofctl add-flow br-int "table=1,priority=1, \
- ct_state=-new+trk+est-rel, $Protocol,actions=ct(commit,table=2)"
- > ovs-ofctl add-flow br-int "table=1,priority=1, \
- ct_state=-new+trk+est+rel, $Protocol,actions=ct(commit,table=2)"
- > ovs-ofctl add-flow br-int "table=2,priority=1,ip6, \
+ ct_state=-new+trk+est+rel,$Protocol,actions=ct(commit,table=2)"
+ > ovs-ofctl add-flow br-int "table=2,priority=1,ip6,\
ipv6_dst=$Vif38Address,$Protocol,actions=output:$Vif38Port"
- > ovs-ofctl add-flow br-int "table=2,priority=1,ip6, \
+ > ovs-ofctl add-flow br-int "table=2,priority=1,ip6,\
ipv6_dst=$Vif40Address,$Protocol,actions=output:$Vif40Port"
+
::
nat scenario
Vif38(20::1, ofport:2) -> nat address(20::9) -> Vif42(21::3, ofport:4)
Due to not construct flow to return neighbor mac address, we set the
neighbor mac address manually
+ Vif38Name="podvif70"
+ Vif42Name="Ethernet1"
+ Vif38Ip="20::88"
Vif38Port=2
- Vif42Port=4
- Vif38Name="podvif38"
- Vif42Name="podvif42"
+ Vif42Port=3
NatAddress="20::9"
NatMacAddress="aa:bb:cc:dd:ee:ff"
NatMacAddressForCli="aa-bb-cc-dd-ee-ff"
Vif42Ip="21::3"
- Vif38MacAddress="00:15:5D:F0:01:0B"
- Vif42MacAddress="00:15:5D:F0:01:0D"
+ Vif38MacAddress="00:15:5D:F0:01:14"
+ Vif38MacAddressCli="00-15-5D-F0-01-14"
+ Vif42MacAddress="00:50:56:98:9d:97"
Protocol="tcp6"
- > netsh int ipv6 set neighbors $Vif38Name $NatAddress \
- $NatMacAddressForCli
- > netsh int ipv6 set neighbors $Vif42Name $NatAddress \
- $NatMacAddressForCli
+ netsh int ipv6 set neighbors $Vif38Name $NatAddress $NatMacAddressForCli
+ netsh int ipv6 set neighbors $Vif42Name $Vif38Ip $Vif38MacAddressCli
> ovs-ofctl del-flows br-int --strict "table=0,priority=0"
- > ovs-ofctl add-flow br-int "table=0,priority=2,ipv6, \
- dl_dst=$NatMacAddress,ct_state=-trk,$Protocol \
- actions=ct(table=1,zone=456,nat)"
- > ovs-ofctl add-flow br-int "table=0,priority=1,ipv6, \
- ct_state=-trk,ip6,$Protocol actions=ct(nat, zone=456,table=1)"
- > ovs-ofctl add-flow br-int "table=1,ipv6,in_port=$Vif38Port, \
- ipv6_dst=$NatAddress,ct_state=+trk+new,$Protocol \
- actions=ct(commit,nat(dst=$Vif42Ip),zone=456, \
- exec(set_field:1->ct_mark)),mod_dl_src=$NatMacAddress, \
+ > ovs-ofctl add-flow br-int "table=0,priority=2,ipv6,ipv6_dst=$NatAddress,\
+ ct_state=-trk,$Protocol actions=ct(table=1,zone=456)"
+ > ovs-ofctl add-flow br-int "table=0,priority=1,ipv6,ipv6_dst=$Vif38Ip,\
+ ct_state=-trk,ip6,$Protocol actions=ct(zone=456,table=1)"
+ > ovs-ofctl add-flow br-int "table=1,priority=2,ipv6,in_port=$Vif38Port,\
+ ipv6_dst=$NatAddress,ct_state=+trk-rel,tp_dst=21,$Protocol \
+ actions=ct(commit,alg=ftp,nat(dst=$Vif42Ip),zone=456, \
+ exec(set_field:1->ct_mark)),mod_dl_src=$NatMacAddress,\
mod_dl_dst=$Vif42MacAddress,output:$Vif42Port"
- > ovs-ofctl add-flow br-int "table=1,ipv6,ct_state=+dnat,$Protocol, \
- action=resubmit(,2)"
- > ovs-ofctl add-flow br-int "table=1,ipv6,ct_state=+trk+snat, \
- $Protocol,action=resubmit(,2)"
- > ovs-ofctl add-flow br-int "table=1,ipv6,ct_state=+trk+rel,$Protocol, \
- action=resubmit(,2)"
- > ovs-ofctl add-flow br-int "table=2,ipv6,in_port=$Vif38Port, \
- ipv6_dst=$Vif42Ip,$Protocol, actions=mod_dl_src=$NatMacAddress, \
- mod_dl_dst=$Vif42MacAddress,output:$Vif42Port"
- > ovs-ofctl add-flow br-int "table=2,ipv6,in_port=$Vif42Port, \
- ct_state=-new+est,ct_mark=1,ct_zone=456,$Protocol, \
- actions=mod_dl_src=$NatMacAddress,mod_dl_dst=$Vif38MacAddress, \
+ > ovs-ofctl add-flow br-int "table=1,priority=1,ipv6,ct_state=+trk-rel,\
+ ipv6_dst=$Vif38Ip,$Protocol,action=ct(nat,alg=ftp,zone=456,table=2)"
+ > ovs-ofctl add-flow br-int "table=1,ipv6,ct_state=+trk+rel,\
+ ipv6_dst=$NatAddress,$Protocol,\
+ action=ct(table=2,commit,nat(dst=$Vif42Ip),\
+ zone=456, exec(set_field:1->ct_mark))"
+ > ovs-ofctl add-flow br-int "table=1,ipv6,ct_state=+trk+rel,$Protocol,\
+ ipv6_dst=$Vif38Ip, action=ct(nat,zone=456,table=2)"
+ > ovs-ofctl add-flow br-int "table=2,ipv6,ipv6_dst=$Vif42Ip,$Protocol,\
+ actions=mod_dl_src=$NatMacAddress, mod_dl_dst=$Vif42MacAddress,\
+ output:$Vif42Port"
+ > ovs-ofctl add-flow br-int "table=2,ipv6,ipv6_dst=$Vif38Ip,\
+ ct_state=-new+est,ct_mark=1,ct_zone=456,$Protocol,\
+ actions=mod_dl_src=$NatMacAddress,mod_dl_dst=$Vif38MacAddress,\
output:$Vif38Port"
+ > ovs-ofctl add-flow br-int "table=2,ipv6,ipv6_dst=$Vif38Ip,\
+ ct_state=+new,ct_mark=1,ct_zone=456,$Protocol,\
+ actions=mod_dl_src=$NatMacAddress,\
+ mod_dl_dst=$Vif38MacAddress, output:$Vif38Port"
+
+Tftp same with ftp, it also contains a related connection, we could use
+following follow test the tftp connection.
+
+::
+
+ normal scenario
+ Vif38Name="podvif70"
+ Vif40Name="Ethernet1"
+ Vif38Port=2
+ Vif38Address="20::88"
+ Vif40Port=3
+ Vif40Address="20::45"
+ Vif40MacAddressCli="00-50-56-98-9d-97"
+ Vif38MacAddressCli="00-15-5D-F0-01-14"
+ Protocol="udp6"
+ netsh int ipv6 set neighbors $Vif38Name $Vif40Address $Vif40MacAddressCli
+ netsh int ipv6 set neighbors $Vif40Name $Vif38Address $Vif38MacAddressCli
+ > ovs-ofctl del-flows br-int --strict "table=0,priority=0"
+ > ovs-ofctl add-flow br-int "table=0,priority=1,$Protocol,
+ ipv6_src=$Vif38Address actions=ct(table=1)"
+ > ovs-ofctl add-flow br-int "table=0,priority=1,$Protocol,
+ ipv6_src=$Vif40Address actions=ct(table=1)"
+ > ovs-ofctl add-flow br-int "table=1,priority=1,ct_state=+new+trk-est,
+ tp_dst=69,$Protocol,udp6 actions=ct(commit,alg=tftp,table=2)"
+ > ovs-ofctl add-flow br-int "table=1,priority=1,ct_state=-new+trk+est-rel,\
+ udp6 $Protocol,actions=ct(commit,table=2)"
+ > ovs-ofctl add-flow br-int "table=1,priority=1,ct_state=-new+trk+est+rel,\
+ $Protocol,actions=ct(commit,table=2)"
+ > ovs-ofctl add-flow br-int "table=1,priority=1,ct_state=+new+trk+rel,\
+ $Protocol,actions=ct(commit,table=2)"
+ > ovs-ofctl add-flow br-int "table=2,priority=1,ip6,\
+ ipv6_dst=$Vif38Address,$Protocol,actions=output:$Vif38Port"
+ > ovs-ofctl add-flow br-int "table=2,priority=1,ip6,\
+ ipv6_dst=$Vif40Address,$Protocol,actions=output:$Vif40Port"
+
+::
+
+ nat scenario
+ Vif38Name="podvif70"
+ Vif42Name="Ethernet1"
+ Vif38Ip="20::88"
+ Vif38Port=2
+ Vif42Port=3
+ NatAddress="20::9"
+ NatMacAddress="aa:bb:cc:dd:ee:ff"
+ NatMacAddressForCli="aa-bb-cc-dd-ee-ff"
+ Vif42Ip="21::3"
+ Vif38MacAddress="00:15:5D:F0:01:14"
+ Vif38MacAddressCli="00-15-5D-F0-01-14"
+ Vif42MacAddress="00:50:56:98:9d:97"
+ Protocol="ip6"
+ netsh int ipv6 set neighbors $Vif38Name $NatAddress $NatMacAddressForCli
+ netsh int ipv6 set neighbors $Vif42Name $Vif38Ip $Vif38MacAddressCli
+ > ovs-ofctl del-flows br-int --strict "table=0,priority=0"
+ > ovs-ofctl add-flow br-int "table=0,priority=2,ipv6,\
+ dl_dst=$NatMacAddress,ct_state=-trk,$Protocol \
+ actions=ct(table=1,zone=456)"
+ > ovs-ofctl add-flow br-int "table=0,priority=1,ipv6,ct_state=-trk,ip6,\
+ $Protocol actions=ct(table=1,zone=456)"
+ > ovs-ofctl add-flow br-int "table=1,in_port=$Vif38Port,\
+ ipv6_dst=$NatAddress,ct_state=+trk+new-rel,$Protocol,udp6\
+ actions=ct(commit,alg=tftp,nat(dst=$Vif42Ip),zone=456,\
+ exec(set_field:1->ct_mark)),mod_dl_src=$NatMacAddress,\
+ mod_dl_dst=$Vif42MacAddress,output:$Vif42Port"
+ > ovs-ofctl add-flow br-int "table=1,ipv6,in_port=$Vif42Port,\
+ ipv6_dst=$Vif38Ip,ct_state=+trk+rel-rpl,$Protocol\
+ actions=ct(commit,nat(src=$NatAddress),zone=456,\
+ exec(set_field:1->ct_mark)),mod_dl_src=$NatMacAddress,\
+ mod_dl_dst=$Vif38MacAddress,output:$Vif38Port"
+ > ovs-ofctl add-flow br-int "table=1,ipv6,ct_state=+trk+rel+est+rpl,\
+ $Protocol,action=ct(nat,table=2,zone=456)"
+ > ovs-ofctl add-flow br-int "table=2,ipv6,in_port=$Vif38Port,\
+ ct_state=+rel+dnat,ipv6_dst=$Vif42Ip,$Protocol,\
+ actions=mod_dl_src=$NatMacAddress,mod_dl_dst=$Vif42MacAddress,\
+ output:$Vif42Port"
+ > ovs-ofctl add-flow br-int "table=2,ipv6,in_port=$Vif42Port,\
+ ct_state=-new+est,$Protocol,actions=mod_dl_src=$NatMacAddress,\
+ mod_dl_dst=$Vif38MacAddress,output:$Vif38Port"
+
.. note::
diff --git a/datapath-windows/ovsext/Actions.c b/datapath-windows/ovsext/Actions.c
index 20de4db4c..3100532e1 100644
--- a/datapath-windows/ovsext/Actions.c
+++ b/datapath-windows/ovsext/Actions.c
@@ -2378,7 +2378,6 @@ OvsDoExecuteActions(POVS_SWITCH_CONTEXT switchContext,
}
OvsExecuteHash(key, (const PNL_ATTR)a);
-
break;
}
diff --git a/datapath-windows/ovsext/Conntrack-ftp.c b/datapath-windows/ovsext/Conntrack-ftp.c
index 066723685..6775496cf 100644
--- a/datapath-windows/ovsext/Conntrack-ftp.c
+++ b/datapath-windows/ovsext/Conntrack-ftp.c
@@ -122,12 +122,9 @@ OvsCtExtractNumbers(char *buf,
*----------------------------------------------------------------------------
*/
NDIS_STATUS
-OvsCtHandleFtp(PNET_BUFFER_LIST curNbl,
- OvsFlowKey *key,
- OVS_PACKET_HDR_INFO *layers,
- UINT64 currentTime,
- POVS_CT_ENTRY entry,
- BOOLEAN request)
+OvsCtHandleFtp(PNET_BUFFER_LIST curNbl, OvsFlowKey *key,
+ OVS_PACKET_HDR_INFO *layers, UINT64 currentTime,
+ POVS_CT_ENTRY entry)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
FTP_TYPE ftpType = 0;
@@ -157,52 +154,51 @@ OvsCtHandleFtp(PNET_BUFFER_LIST curNbl,
OvsStrlcpy((char *)ftpMsg, (char *)buf, min(len, sizeof(ftpMsg)));
char *req = NULL;
- if (request) {
- if ((len >= 5) && (OvsStrncmp("PORT", ftpMsg, 4) == 0)) {
- ftpType = FTP_TYPE_ACTIVE;
- req = ftpMsg + 4;
- } else if ((len >= 5) && (OvsStrncmp("EPRT", ftpMsg, 4) == 0)) {
- ftpType = FTP_EXTEND_TYPE_ACTIVE;
- req = ftpMsg + 4;
+ if ((len >= 5) && (OvsStrncmp("PORT", ftpMsg, 4) == 0)) {
+ ftpType = FTP_TYPE_ACTIVE;
+ req = ftpMsg + 4;
+ } else if ((len >= 5) && (OvsStrncmp("EPRT", ftpMsg, 4) == 0)) {
+ ftpType = FTP_EXTEND_TYPE_ACTIVE;
+ req = ftpMsg + 4;
+ }
+
+ if ((len >= 4) && (OvsStrncmp(FTP_PASV_RSP_PREFIX, ftpMsg, 3) == 0)) {
+ ftpType = FTP_TYPE_PASV;
+ /* There are various formats for PASV command. We try to support
+ * some of them. This has been addressed by RFC 2428 - EPSV.
+ * Eg:
+ * 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2).
+ * 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2
+ * 227 Entering Passive Mode. h1,h2,h3,h4,p1,p2
+ * 227 =h1,h2,h3,h4,p1,p2
+ */
+ char *paren;
+ paren = strchr(ftpMsg, '(');
+ if (paren) {
+ req = paren + 1;
+ } else {
+ /* PASV command without ( */
+ req = ftpMsg + 3;
+ }
+ } else if ((len >= 4) && (
+ OvsStrncmp(FTP_EXTEND_PASV_RSP_PREFIX, ftpMsg, 3) == 0)) {
+ ftpType = FTP_EXTEND_TYPE_PASV;
+ /* The ftp extended passive mode only contain port info, ip address
+ * is same with the network protocol used by control connection.
+ * 229 Entering Extended Passive Mode (|||port|)
+ * */
+ char *paren;
+ paren = strchr(ftpMsg, '|');
+ if (paren) {
+ req = paren + 3;
+ } else {
+ /* Not a valid EPSV packet. */
+ return NDIS_STATUS_INVALID_PACKET;
}
- } else {
- if ((len >= 4) && (OvsStrncmp(FTP_PASV_RSP_PREFIX, ftpMsg, 3) == 0)) {
- ftpType = FTP_TYPE_PASV;
- /* There are various formats for PASV command. We try to support
- * some of them. This has been addressed by RFC 2428 - EPSV.
- * Eg:
- * 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2).
- * 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2
- * 227 Entering Passive Mode. h1,h2,h3,h4,p1,p2
- * 227 =h1,h2,h3,h4,p1,p2
- */
- char *paren;
- paren = strchr(ftpMsg, '(');
- if (paren) {
- req = paren + 1;
- } else {
- /* PASV command without ( */
- req = ftpMsg + 3;
- }
- } else if ((len >= 4) && (OvsStrncmp(FTP_EXTEND_PASV_RSP_PREFIX, ftpMsg, 3) == 0)) {
- ftpType = FTP_EXTEND_TYPE_PASV;
- /* The ftp extended passive mode only contain port info, ip address
- * is same with the network protocol used by control connection.
- * 229 Entering Extended Passive Mode (|||port|)
- * */
- char *paren;
- paren = strchr(ftpMsg, '|');
- if (paren) {
- req = paren + 3;
- } else {
- /* Not a valid EPSV packet. */
- return NDIS_STATUS_INVALID_PACKET;
- }
- if (!(*req > '0' && * req < '9')) {
- /* Not a valid port number. */
- return NDIS_STATUS_INVALID_PACKET;
- }
+ if (!(*req > '0' && * req < '9')) {
+ /* Not a valid port number. */
+ return NDIS_STATUS_INVALID_PACKET;
}
}
@@ -226,8 +222,15 @@ OvsCtHandleFtp(PNET_BUFFER_LIST curNbl,
(arr[2] << 8) | arr[3]);
port = ntohs(((arr[4] << 8) | arr[5]));
- serverIp.ipv4 = ip;
- clientIp.ipv4 = key->ipKey.nwDst;
+ if (ftpType == FTP_TYPE_ACTIVE) {
+ serverIp.ipv4 = key->ipKey.nwDst;
+ clientIp.ipv4 = ip;
+ }
+
+ if (ftpType == FTP_TYPE_PASV) {
+ serverIp.ipv4 = ip;
+ clientIp.ipv4 = key->ipKey.nwDst;
+ }
} else {
if (ftpType == FTP_EXTEND_TYPE_ACTIVE) {
/** In ftp active mode, we need to parse string like below:
@@ -239,7 +242,7 @@ OvsCtHandleFtp(PNET_BUFFER_LIST curNbl,
char *nextHdr = NULL;
int index = 0;
int isIpv6AddressFamily = 0;
- char ftpStr[1024] = {0x00};
+ char ftpStr[512] = {0x00};
RtlCopyMemory(ftpStr, req, strlen(req));
for (curHdr = ftpStr; *curHdr != '|'; curHdr++);
diff --git a/datapath-windows/ovsext/Conntrack-related.c b/datapath-windows/ovsext/Conntrack-related.c
index f985c7631..99b1553da 100644
--- a/datapath-windows/ovsext/Conntrack-related.c
+++ b/datapath-windows/ovsext/Conntrack-related.c
@@ -40,6 +40,7 @@ OvsCtRelatedKeyAreSame(OVS_CT_KEY incomingKey, OVS_CT_KEY entryKey)
/* FTP PASV - Client initiates the connection from unknown port */
if ((incomingKey.dl_type == entryKey.dl_type) &&
(incomingKey.dl_type == htons(ETH_TYPE_IPV4)) &&
+ (incomingKey.nw_proto == IPPROTO_TCP) &&
(incomingKey.dst.addr.ipv4 == entryKey.src.addr.ipv4) &&
(incomingKey.dst.port == entryKey.src.port) &&
(incomingKey.src.addr.ipv4 == entryKey.dst.addr.ipv4) &&
@@ -49,6 +50,7 @@ OvsCtRelatedKeyAreSame(OVS_CT_KEY incomingKey, OVS_CT_KEY entryKey)
if ((incomingKey.dl_type == entryKey.dl_type) &&
(incomingKey.dl_type == htons(ETH_TYPE_IPV6)) &&
+ (incomingKey.nw_proto == IPPROTO_TCP) &&
!memcmp(&(incomingKey.dst.addr.ipv6), &(entryKey.src.addr.ipv6),
sizeof(incomingKey.dst.addr.ipv6)) &&
(incomingKey.dst.port == entryKey.src.port) &&
@@ -65,6 +67,7 @@ OvsCtRelatedKeyAreSame(OVS_CT_KEY incomingKey, OVS_CT_KEY entryKey)
*/
if ((incomingKey.dl_type == entryKey.dl_type) &&
(incomingKey.dl_type == htons(ETH_TYPE_IPV4)) &&
+ (incomingKey.nw_proto == IPPROTO_TCP) &&
(incomingKey.src.addr.ipv4 == entryKey.src.addr.ipv4) &&
(incomingKey.dst.addr.ipv4 == entryKey.dst.addr.ipv4) &&
(incomingKey.dst.port == entryKey.dst.port) &&
@@ -74,6 +77,7 @@ OvsCtRelatedKeyAreSame(OVS_CT_KEY incomingKey, OVS_CT_KEY entryKey)
if ((incomingKey.dl_type == entryKey.dl_type) &&
(incomingKey.dl_type == htons(ETH_TYPE_IPV6)) &&
+ (incomingKey.nw_proto == IPPROTO_TCP) &&
!memcmp(&(incomingKey.src.addr.ipv6), &(entryKey.src.addr.ipv6),
sizeof(incomingKey.src.addr.ipv6)) &&
!memcmp(&(incomingKey.dst.addr.ipv6), &(entryKey.dst.addr.ipv6),
@@ -83,6 +87,31 @@ OvsCtRelatedKeyAreSame(OVS_CT_KEY incomingKey, OVS_CT_KEY entryKey)
return TRUE;
}
+ /* Tftp protocol */
+ if ((incomingKey.dl_type == entryKey.dl_type) &&
+ (incomingKey.dl_type == htons(ETH_TYPE_IPV4)) &&
+ (incomingKey.nw_proto == IPPROTO_UDP) &&
+ !memcmp(&(incomingKey.src.addr.ipv4), &(entryKey.src.addr.ipv4),
+ sizeof(incomingKey.src.addr.ipv4)) &&
+ !memcmp(&(incomingKey.dst.addr.ipv4), &(entryKey.dst.addr.ipv4),
+ sizeof(incomingKey.dst.addr.ipv4)) &&
+ (incomingKey.dst.port == entryKey.dst.port) &&
+ (incomingKey.nw_proto == entryKey.nw_proto)) {
+ return TRUE;
+ }
+
+ if ((incomingKey.dl_type == entryKey.dl_type) &&
+ (incomingKey.dl_type == htons(ETH_TYPE_IPV6)) &&
+ (incomingKey.nw_proto == IPPROTO_UDP) &&
+ !memcmp(&(incomingKey.src.addr.ipv6), &(entryKey.src.addr.ipv6),
+ sizeof(incomingKey.src.addr.ipv6)) &&
+ !memcmp(&(incomingKey.dst.addr.ipv6), &(entryKey.dst.addr.ipv6),
+ sizeof(incomingKey.dst.addr.ipv6)) &&
+ (incomingKey.dst.port == entryKey.dst.port) &&
+ (incomingKey.nw_proto == entryKey.nw_proto)) {
+ return TRUE;
+ }
+
return FALSE;
}
@@ -165,7 +194,6 @@ OvsCtRelatedEntryCreate(UINT8 ipProto,
}
UINT32 hash = OvsExtractCtRelatedKeyHash(&entry->key);
-
NdisAcquireRWLockWrite(ovsCtRelatedLockObj, &lockState, 0);
InsertHeadList(&ovsCtRelatedTable[hash & CT_HASH_TABLE_MASK],
&entry->link);
diff --git a/datapath-windows/ovsext/Conntrack-tcp.c b/datapath-windows/ovsext/Conntrack-tcp.c
index a468c3e6b..77370531c 100644
--- a/datapath-windows/ovsext/Conntrack-tcp.c
+++ b/datapath-windows/ovsext/Conntrack-tcp.c
@@ -37,6 +37,8 @@
*/
#include "Conntrack.h"
+#include "NetProto.h"
+#include "PacketParser.h"
#include <stddef.h>
struct tcp_peer {
@@ -577,3 +579,54 @@ done:
NlMsgEndNested(nlBuf, offset);
return status;
}
+
+NDIS_STATUS
+OvsCtHandleTftp(PNET_BUFFER_LIST curNbl, OvsFlowKey *key,
+ OVS_PACKET_HDR_INFO *layers, UINT64 currentTime,
+ POVS_CT_ENTRY entry)
+{
+ UDPHdr udpStorage;
+ const UDPHdr *udp = NULL;
+ struct ct_addr serverIp;
+ struct ct_addr clientIp;
+ NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+
+ udp = OvsGetUdp(curNbl, layers->l4Offset, &udpStorage);
+ if (!udp) {
+ return NDIS_STATUS_INVALID_PACKET;
+ }
+
+ RtlZeroMemory(&serverIp, sizeof(serverIp));
+ RtlZeroMemory(&clientIp, sizeof(clientIp));
+
+ if (OvsCtRelatedLookup(entry->key, currentTime)) {
+ return NDIS_STATUS_SUCCESS;
+ }
+
+ if (layers->isIPv4) {
+ serverIp.ipv4 = key->ipKey.nwDst;
+ clientIp.ipv4 = key->ipKey.nwSrc;
+ status = OvsCtRelatedEntryCreate(key->ipKey.nwProto,
+ key->l2.dlType,
+ serverIp,
+ clientIp,
+ 0,
+ udp->source,
+ currentTime,
+ entry);
+ } else {
+ serverIp.ipv6 = key->ipv6Key.ipv6Dst;
+ clientIp.ipv6 = key->ipv6Key.ipv6Src;
+ status = OvsCtRelatedEntryCreate(key->ipv6Key.nwProto,
+ key->l2.dlType,
+ serverIp,
+ clientIp,
+ 0,
+ udp->source,
+ currentTime,
+ entry);
+ }
+
+ return status;
+}
+
diff --git a/datapath-windows/ovsext/Conntrack.c b/datapath-windows/ovsext/Conntrack.c
index 471bf961b..1f3929894 100644
--- a/datapath-windows/ovsext/Conntrack.c
+++ b/datapath-windows/ovsext/Conntrack.c
@@ -874,13 +874,25 @@ OvsCtSetupLookupCtx(OvsFlowKey *flowKey,
return NDIS_STATUS_INVALID_PACKET;
}
+ /* It's only designed for unNat traffic, when reverse traffic comes,
+ * find the unNat table, if found the nat entry, based on the nat entry
+ * restore the conntrack, it will be stored in the ctx->key and then use the
+ * ctx->key lookup the conntrack table to find the corresponded
+ * entry with the traffic.*/
natEntry = OvsNatLookup(&ctx->key, TRUE);
if (natEntry) {
- /* Translate address first for reverse NAT */
+ /* initial direction 20::1 -> 20::9, reverse direction 21::3 -> 20::1
+ * 20::9 could be regarded as nat ip, before convert, ctx->key value
+ * is "21::3 -> 20::1", after convert, ctx->key value is
+ * "20::9->20::1" */
ctx->key = natEntry->ctEntry->key;
OvsCtKeyReverse(&ctx->key);
} else {
- if (flowKey->l2.dlType == htons(ETH_TYPE_IPV4)) {
+ if (OvsNatLookup(&ctx->key, FALSE)) {
+ /* Do nothing here, this branch here used to exclude traffic
+ * described in https://github.com/openvswitch/ovs-issues/issues/237
+ * */
+ } else if (flowKey->l2.dlType == htons(ETH_TYPE_IPV4)) {
OvsPickupCtTupleAsLookupKey(&(ctx->key), zone, flowKey);
}
}
@@ -903,6 +915,18 @@ OvsDetectFtp6Packet(OvsFlowKey *key) {
ntohs(key->ipv6Key.l4.tpSrc) == IPPORT_FTP));
}
+static __inline BOOLEAN
+OvsDetectTftpPacket(OvsFlowKey *key) {
+ return (key->ipKey.nwProto == IPPROTO_UDP &&
+ (ntohs(key->ipKey.l4.tpDst) == IPPORT_TFTP));
+}
+
+static __inline BOOLEAN
+OvsDetectTftp6Packet(OvsFlowKey *key) {
+ return (key->ipv6Key.nwProto == IPPROTO_UDP &&
+ (ntohs(key->ipv6Key.l4.tpDst) == IPPORT_TFTP));
+}
+
/*
*----------------------------------------------------------------------------
* OvsProcessConntrackEntry
@@ -989,7 +1013,9 @@ OvsProcessConntrackEntry(OvsForwardingContext *fwdCtx,
if (entry) {
NdisAcquireSpinLock(&(entry->lock));
if ((layers->isIPv6 && key->ipv6Key.nwProto == IPPROTO_TCP) ||
- (!(layers->isIPv6) && key->ipKey.nwProto == IPPROTO_TCP)) {
+ (!(layers->isIPv6) && key->ipKey.nwProto == IPPROTO_TCP) ||
+ (layers->isIPv6 && key->ipv6Key.nwProto == IPPROTO_UDP) ||
+ (!(layers->isIPv6) && key->ipKey.nwProto == IPPROTO_UDP)) {
/* Update the related bit if there is a parent */
if (entry->parent) {
state |= OVS_CS_F_RELATED;
@@ -1156,12 +1182,11 @@ OvsCtExecute_(OvsForwardingContext *fwdCtx,
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
BOOLEAN triggerUpdateEvent = FALSE;
BOOLEAN entryCreated = FALSE;
- BOOLEAN isFtpPacket = FALSE;
- BOOLEAN isFtpRequestDirection = FALSE;
POVS_CT_ENTRY entry = NULL;
POVS_CT_ENTRY parent = NULL;
PNET_BUFFER_LIST curNbl = fwdCtx->curNbl;
OvsConntrackKeyLookupCtx ctx = { 0 };
+ CT_HELPER_METHOD helpMethod = CT_HELPER_NONE;
LOCK_STATE_EX lockStateTable;
UINT64 currentTime;
NdisGetCurrentSystemTime((LARGE_INTEGER *) &currentTime);
@@ -1241,32 +1266,52 @@ OvsCtExecute_(OvsForwardingContext *fwdCtx,
OvsCtSetMarkLabel(key, entry, mark, labels, &triggerUpdateEvent);
+ if (helper && RtlEqualMemory(helper, "ftp", sizeof("ftp"))) {
+ helpMethod = CT_HELPER_FTP;
+ } else if (helper && RtlEqualMemory(helper, "tftp", sizeof("tftp"))) {
+ helpMethod = CT_HELPER_TFTP;
+ }
+
+ /* This code section was added to compatible with the old version,
+ * because old version regard all traffic to port 21 as ftp traffic,
+ * no need to add alg field in ct. Thus, the code was added to keep the
+ * same behavior for ftp and tftp.*/
if (layers->isIPv6) {
- isFtpPacket = OvsDetectFtp6Packet(key);
- if (ntohs(key->ipv6Key.l4.tpDst) == IPPORT_FTP) {
- isFtpRequestDirection = TRUE;
+ if (OvsDetectFtp6Packet(key)) {
+ helpMethod = CT_HELPER_FTP;
+ }
+
+ if (OvsDetectTftp6Packet(key)) {
+ helpMethod = CT_HELPER_TFTP;
}
} else {
- isFtpPacket = OvsDetectFtpPacket(key);
- if (ntohs(key->ipKey.l4.tpDst) == IPPORT_FTP) {
- isFtpRequestDirection = TRUE;
+ if (OvsDetectFtpPacket(key)) {
+ helpMethod = CT_HELPER_FTP;
+ }
+
+ if (OvsDetectTftpPacket(key)) {
+ helpMethod = CT_HELPER_TFTP;
}
}
- if (isFtpPacket) {
- /* FTP parser will always be loaded */
- status = OvsCtHandleFtp(curNbl, key, layers, currentTime, entry,
- isFtpRequestDirection);
+ if (helpMethod == CT_HELPER_FTP) {
+ status = OvsCtHandleFtp(curNbl, key, layers, currentTime, entry);
if (status != NDIS_STATUS_SUCCESS) {
OVS_LOG_ERROR("Error while parsing the FTP packet");
}
}
+ if (helpMethod == CT_HELPER_TFTP) {
+ status = OvsCtHandleTftp(curNbl, key, layers, currentTime, entry);
+ if (status != NDIS_STATUS_SUCCESS) {
+ OVS_LOG_ERROR("Error while parsing the TFTP packet");
+ }
+ }
+
parent = entry->parent;
/* The entry should have the same helper name with parent's */
if (!entry->helper_name &&
(helper || (parent && parent->helper_name))) {
-
helper = helper ? helper : parent->helper_name;
entry->helper_name = OvsAllocateMemoryWithTag(strlen(helper) + 1,
OVS_CT_POOL_TAG);
diff --git a/datapath-windows/ovsext/Conntrack.h b/datapath-windows/ovsext/Conntrack.h
index b68a54f30..deb51c0bc 100644
--- a/datapath-windows/ovsext/Conntrack.h
+++ b/datapath-windows/ovsext/Conntrack.h
@@ -80,6 +80,12 @@ typedef enum _NAT_ACTION {
NAT_ACTION_DST_PORT = 1 << 4,
} NAT_ACTION;
+typedef enum _CT_HELPER_METHOD {
+ CT_HELPER_NONE = 0,
+ CT_HELPER_FTP = 1,
+ CT_HELPER_TFTP = 2,
+} CT_HELPER_METHOD;
+
typedef struct _OVS_CT_KEY {
struct ct_endpoint src;
struct ct_endpoint dst;
@@ -218,11 +224,10 @@ NDIS_STATUS OvsCtRelatedEntryCreate(UINT8 ipProto,
UINT64 currentTime,
POVS_CT_ENTRY parent);
POVS_CT_ENTRY OvsCtRelatedLookup(OVS_CT_KEY key, UINT64 currentTime);
-
-NDIS_STATUS OvsCtHandleFtp(PNET_BUFFER_LIST curNbl,
- OvsFlowKey *key,
- OVS_PACKET_HDR_INFO *layers,
- UINT64 currentTime,
- POVS_CT_ENTRY entry,
- BOOLEAN request);
+NDIS_STATUS OvsCtHandleFtp(PNET_BUFFER_LIST curNbl, OvsFlowKey *key,
+ OVS_PACKET_HDR_INFO *layers, UINT64 currentTime,
+ POVS_CT_ENTRY entry);
+NDIS_STATUS OvsCtHandleTftp(PNET_BUFFER_LIST curNbl, OvsFlowKey *key,
+ OVS_PACKET_HDR_INFO *layers, UINT64 currentTime,
+ POVS_CT_ENTRY entry);
#endif /* __OVS_CONNTRACK_H_ */
diff --git a/include/windows/netinet/in.h b/include/windows/netinet/in.h
index e4169994b..bae9f8cee 100644
--- a/include/windows/netinet/in.h
+++ b/include/windows/netinet/in.h
@@ -19,5 +19,6 @@
#define IPPROTO_GRE 47
#define IPPORT_FTP 21
+#define IPPORT_TFTP 69
#endif /* netinet/in.h */