summaryrefslogtreecommitdiff
path: root/lib/conntrack.c
diff options
context:
space:
mode:
authorDumitru Ceara <dceara@redhat.com>2020-03-19 20:21:16 +0100
committerIlya Maximets <i.maximets@ovn.org>2020-03-24 15:49:12 +0100
commitaf8169b42d796365ed798a7bcd3af483521a2bee (patch)
treeb9c25b0bcb8fc02186f4602114267748195f3e13 /lib/conntrack.c
parentecbc7f0aa2e112afc5ce63cf8a20ebd41e20b73b (diff)
downloadopenvswitch-af8169b42d796365ed798a7bcd3af483521a2bee.tar.gz
conntrack: Reset ct_state when entering a new zone.
When a new conntrack zone is entered, the ct_state field is zeroed in order to avoid using state information from different zones. One such scenario is when a packet is double NATed. Assuming two zones and 3 flows performing the following actions in order on the packet: 1. ct(zone=5,nat), recirc 2. ct(zone=1), recirc 3. ct(zone=1,nat) If at step #1 the packet matches an existing NAT entry, it will get translated and pkt->md.ct_state is set to CS_DST_NAT or CS_SRC_NAT. At step #2 the new tuple might match an existing connection and pkt->md.ct_zone is set to 1. If at step #3 the packet matches an existing NAT entry in zone 1, handle_nat() will be called to perform the translation but it will return early because the packet's zone matches the conntrack zone and the ct_state field still contains CS_DST_NAT or CS_SRC_NAT from the translations in zone 5. In order to reliably detect when a packet enters a new conntrack zone we also need to make sure that the pkt->md.ct_zone is properly initialized if pkt->md.ct_state is non-zero. This already happens for most cases. The only exception is when matched conntrack connection is of type CT_CONN_TYPE_UN_NAT and the master connection is missing. To cover this path we now call write_ct_md() in that case too. Remove setting the CS_TRACKED flag as in this case as it will be done by the new call to write_ct_md(). CC: Darrell Ball <dlu998@gmail.com> Fixes: 286de2729955 ("dpdk: Userspace Datapath: Introduce NAT Support.") Acked-by: Ilya Maximets <i.maximets@ovn.org> Acked-by: Aaron Conole <aconole@redhat.com> Signed-off-by: Dumitru Ceara <dceara@redhat.com> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Diffstat (limited to 'lib/conntrack.c')
-rw-r--r--lib/conntrack.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/lib/conntrack.c b/lib/conntrack.c
index 001a37ff6..0cbc8f6d2 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -1277,6 +1277,11 @@ process_one(struct conntrack *ct, struct dp_packet *pkt,
const struct nat_action_info_t *nat_action_info,
ovs_be16 tp_src, ovs_be16 tp_dst, const char *helper)
{
+ /* Reset ct_state whenever entering a new zone. */
+ if (pkt->md.ct_state && pkt->md.ct_zone != zone) {
+ pkt->md.ct_state = 0;
+ }
+
bool create_new_conn = false;
conn_key_lookup(ct, &ctx->key, ctx->hash, now, &ctx->conn, &ctx->reply);
struct conn *conn = ctx->conn;
@@ -1300,7 +1305,8 @@ process_one(struct conntrack *ct, struct dp_packet *pkt,
conn_key_lookup(ct, &ctx->key, hash, now, &conn, &ctx->reply);
if (!conn) {
- pkt->md.ct_state |= CS_TRACKED | CS_INVALID;
+ pkt->md.ct_state |= CS_INVALID;
+ write_ct_md(pkt, zone, NULL, NULL, NULL);
char *log_msg = xasprintf("Missing master conn %p", rev_conn);
ct_print_conn_info(rev_conn, log_msg, VLL_INFO, true, true);
free(log_msg);