mirror of
https://github.com/openvswitch/ovs
synced 2025-09-03 07:45:30 +00:00
conntrack: Fix conntrack new state
In connection tracking system, a connection is established if we
see packets from both directions. However, in userspace datapath's
conntrack, if we send a connection setup packet in one direction
twice, it will make the connection to be in established state.
This patch fixes the aforementioned issue, and adds a system traffic
test for UDP and TCP traffic to avoid regression.
Fixes: a489b16854
("conntrack: New userspace connection tracker.")
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: William Tu <u9012063@gmail.com>
This commit is contained in:
@@ -47,16 +47,18 @@ other_conn_update(struct conntrack *ct, struct conn *conn_,
|
|||||||
struct dp_packet *pkt OVS_UNUSED, bool reply, long long now)
|
struct dp_packet *pkt OVS_UNUSED, bool reply, long long now)
|
||||||
{
|
{
|
||||||
struct conn_other *conn = conn_other_cast(conn_);
|
struct conn_other *conn = conn_other_cast(conn_);
|
||||||
|
enum ct_update_res ret = CT_UPDATE_VALID;
|
||||||
|
|
||||||
if (reply && conn->state != OTHERS_BIDIR) {
|
if (reply && conn->state != OTHERS_BIDIR) {
|
||||||
conn->state = OTHERS_BIDIR;
|
conn->state = OTHERS_BIDIR;
|
||||||
} else if (conn->state == OTHERS_FIRST) {
|
} else if (conn->state == OTHERS_FIRST) {
|
||||||
conn->state = OTHERS_MULTIPLE;
|
conn->state = OTHERS_MULTIPLE;
|
||||||
|
ret = CT_UPDATE_VALID_NEW;
|
||||||
}
|
}
|
||||||
|
|
||||||
conn_update_expiration(ct, &conn->up, other_timeouts[conn->state], now);
|
conn_update_expiration(ct, &conn->up, other_timeouts[conn->state], now);
|
||||||
|
|
||||||
return CT_UPDATE_VALID;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@@ -124,6 +124,7 @@ enum ct_update_res {
|
|||||||
CT_UPDATE_INVALID,
|
CT_UPDATE_INVALID,
|
||||||
CT_UPDATE_VALID,
|
CT_UPDATE_VALID,
|
||||||
CT_UPDATE_NEW,
|
CT_UPDATE_NEW,
|
||||||
|
CT_UPDATE_VALID_NEW,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Timeouts: all the possible timeout states passed to update_expiration()
|
/* Timeouts: all the possible timeout states passed to update_expiration()
|
||||||
|
@@ -181,11 +181,16 @@ tcp_conn_update(struct conntrack *ct, struct conn *conn_,
|
|||||||
return CT_UPDATE_INVALID;
|
return CT_UPDATE_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((tcp_flags & (TCP_SYN | TCP_ACK)) == TCP_SYN)
|
if ((tcp_flags & (TCP_SYN | TCP_ACK)) == TCP_SYN) {
|
||||||
&& dst->state >= CT_DPIF_TCPS_FIN_WAIT_2
|
if (dst->state >= CT_DPIF_TCPS_FIN_WAIT_2
|
||||||
&& src->state >= CT_DPIF_TCPS_FIN_WAIT_2) {
|
&& src->state >= CT_DPIF_TCPS_FIN_WAIT_2) {
|
||||||
src->state = dst->state = CT_DPIF_TCPS_CLOSED;
|
src->state = dst->state = CT_DPIF_TCPS_CLOSED;
|
||||||
return CT_UPDATE_NEW;
|
return CT_UPDATE_NEW;
|
||||||
|
} else if (src->state <= CT_DPIF_TCPS_SYN_SENT) {
|
||||||
|
src->state = CT_DPIF_TCPS_SYN_SENT;
|
||||||
|
conn_update_expiration(ct, &conn->up, CT_TM_TCP_FIRST_PACKET, now);
|
||||||
|
return CT_UPDATE_NEW;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src->wscale & CT_WSCALE_FLAG
|
if (src->wscale & CT_WSCALE_FLAG
|
||||||
|
@@ -1110,6 +1110,9 @@ conn_update_state(struct conntrack *ct, struct dp_packet *pkt,
|
|||||||
ovs_mutex_unlock(&ct->ct_lock);
|
ovs_mutex_unlock(&ct->ct_lock);
|
||||||
create_new_conn = true;
|
create_new_conn = true;
|
||||||
break;
|
break;
|
||||||
|
case CT_UPDATE_VALID_NEW:
|
||||||
|
pkt->md.ct_state |= CS_NEW;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
OVS_NOT_REACHED();
|
OVS_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@@ -2290,6 +2290,47 @@ tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=
|
|||||||
OVS_TRAFFIC_VSWITCHD_STOP
|
OVS_TRAFFIC_VSWITCHD_STOP
|
||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
|
||||||
|
AT_SETUP([conntrack - new connections])
|
||||||
|
CHECK_CONNTRACK()
|
||||||
|
OVS_TRAFFIC_VSWITCHD_START()
|
||||||
|
|
||||||
|
ADD_NAMESPACES(at_ns0, at_ns1)
|
||||||
|
|
||||||
|
ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
|
||||||
|
ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
|
||||||
|
|
||||||
|
AT_DATA([flows1.txt], [dnl
|
||||||
|
table=0, priority=1,action=drop
|
||||||
|
table=0, priority=10,arp,action=normal
|
||||||
|
table=0, priority=100,tcp,action=ct(table=1)
|
||||||
|
table=0, priority=100,udp,action=ct(table=1)
|
||||||
|
table=1, priority=100,in_port=1,tcp,ct_state=+trk+new,action=ct(commit)
|
||||||
|
table=1, priority=100,in_port=1,udp,ct_state=+trk+new,action=ct(commit)
|
||||||
|
table=1, priority=100,in_port=1,ct_state=+trk+est,action=2
|
||||||
|
table=1, priority=100,in_port=2,ct_state=+trk+est,action=1
|
||||||
|
])
|
||||||
|
|
||||||
|
ovs-appctl vlog/set dbg
|
||||||
|
|
||||||
|
AT_CHECK([ovs-ofctl --bundle add-flows br0 flows1.txt])
|
||||||
|
|
||||||
|
dnl TCP traffic from ns0 to ns1 should fail.
|
||||||
|
OVS_START_L7([at_ns1], [http])
|
||||||
|
NS_CHECK_EXEC([at_ns0], [wget 10.1.1.2 -t 3 -T 1 --retry-connrefused -v -o wget0.log], [4])
|
||||||
|
|
||||||
|
dnl Send UDP packet on port 1 twice.
|
||||||
|
AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=1 packet=50540000000a50540000000908004500001c000000000011a4cd0a0101010a0101020001000200080000 actions=resubmit(,0)"])
|
||||||
|
AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=1 packet=50540000000a50540000000908004500001c000000000011a4cd0a0101010a0101020001000200080000 actions=resubmit(,0)"])
|
||||||
|
|
||||||
|
dnl There should not be any packet that matches the established ct_state.
|
||||||
|
AT_CHECK([ovs-ofctl dump-flows br0 "table=1 in_port=1,ct_state=+trk+est" | ofctl_strip], [0], [dnl
|
||||||
|
NXST_FLOW reply:
|
||||||
|
table=1, priority=100,ct_state=+est+trk,in_port=1 actions=output:2
|
||||||
|
])
|
||||||
|
|
||||||
|
OVS_TRAFFIC_VSWITCHD_STOP
|
||||||
|
AT_CLEANUP
|
||||||
|
|
||||||
AT_SETUP([conntrack - ICMP related])
|
AT_SETUP([conntrack - ICMP related])
|
||||||
AT_SKIP_IF([test $HAVE_NC = no])
|
AT_SKIP_IF([test $HAVE_NC = no])
|
||||||
CHECK_CONNTRACK()
|
CHECK_CONNTRACK()
|
||||||
|
Reference in New Issue
Block a user