Hi, Paolo well done.
the patch looks good to me. and I am going through your other patches. I wonder maybe finally we need a *conn_flags* to store all the informations containing NAT, cleaned flag, etc. Paolo Valerio <[email protected]> 于2021年11月30日周二 02:06写道: > From: Peng He <[email protected]> > > Currently, when doing NAT, the userspace conntrack will use an extra > conn for the two directions in a flow. However, each conn has actually > the two keys for both orig and rev directions. This patch introduces a > key_node[CT_DIR_MAX] member in the conn which consists of key and a > cmap_node for hash lookup. Both keys can now be accessed in the > following way: > > conn->key_node[CT_DIR_{FWD,REV}].key > > similarly to what Aaron Conole suggested. > > This patch avoids the extra allocation for nat_conn, and makes > userspace code cleaner. > > Signed-off-by: Peng He <[email protected]> > Co-authored-by: Paolo Valerio <[email protected]> > Signed-off-by: Paolo Valerio <[email protected]> > --- > Initial patch: > > > https://patchwork.ozlabs.org/project/openvswitch/patch/[email protected]/ > --- > lib/conntrack-private.h | 20 +- > lib/conntrack-tp.c | 6 - > lib/conntrack.c | 499 > ++++++++++++++++++++--------------------------- > 3 files changed, 229 insertions(+), 296 deletions(-) > > diff --git a/lib/conntrack-private.h b/lib/conntrack-private.h > index 34c688821..ea5ba3d9e 100644 > --- a/lib/conntrack-private.h > +++ b/lib/conntrack-private.h > @@ -48,9 +48,16 @@ struct ct_endpoint { > * hashing in ct_endpoint_hash_add(). */ > BUILD_ASSERT_DECL(sizeof(struct ct_endpoint) == sizeof(union ct_addr) + > 4); > > +enum key_dir { > + CT_DIR_FWD = 0, > + CT_DIR_REV, > + CT_DIR_MAX, > +}; > + > /* Changes to this structure need to be reflected in conn_key_hash() > * and conn_key_cmp(). */ > struct conn_key { > + enum key_dir dir; > struct ct_endpoint src; > struct ct_endpoint dst; > > @@ -86,21 +93,19 @@ struct alg_exp_node { > bool nat_rpl_dst; > }; > > -enum OVS_PACKED_ENUM ct_conn_type { > - CT_CONN_TYPE_DEFAULT, > - CT_CONN_TYPE_UN_NAT, > +struct conn_key_node { > + struct conn_key key; > + struct cmap_node cm_node; > }; > > struct conn { > /* Immutable data. */ > - struct conn_key key; > - struct conn_key rev_key; > + struct conn_key_node key_node[CT_DIR_MAX]; > struct conn_key parent_key; /* Only used for orig_tuple support. */ > struct ovs_list exp_node; > - struct cmap_node cm_node; > + > uint16_t nat_action; > char *alg; > - struct conn *nat_conn; /* The NAT 'conn' context, if there is one. */ > > /* Mutable data. */ > struct ovs_mutex lock; /* Guards all mutable fields. */ > @@ -120,7 +125,6 @@ struct conn { > > /* Immutable data. */ > bool alg_related; /* True if alg data connection. */ > - enum ct_conn_type conn_type; > > uint32_t tp_id; /* Timeout policy ID. */ > }; > diff --git a/lib/conntrack-tp.c b/lib/conntrack-tp.c > index c2245038b..9ecb06978 100644 > --- a/lib/conntrack-tp.c > +++ b/lib/conntrack-tp.c > @@ -282,7 +282,8 @@ conn_update_expiration(struct conntrack *ct, struct > conn *conn, > ovs_mutex_lock(&conn->lock); > VLOG_DBG_RL(&rl, "Update timeout %s zone=%u with policy id=%d " > "val=%u sec.", > - ct_timeout_str[tm], conn->key.zone, conn->tp_id, val); > + ct_timeout_str[tm], conn->key_node[CT_DIR_FWD].key.zone, > + conn->tp_id, val); > > conn_update_expiration__(ct, conn, tm, now, val); > } > @@ -313,7 +314,8 @@ conn_init_expiration(struct conntrack *ct, struct conn > *conn, > } > > VLOG_DBG_RL(&rl, "Init timeout %s zone=%u with policy id=%d val=%u > sec.", > - ct_timeout_str[tm], conn->key.zone, conn->tp_id, val); > + ct_timeout_str[tm], conn->key_node[CT_DIR_FWD].key.zone, > + conn->tp_id, val); > > conn_init_expiration__(ct, conn, tm, now, val); > } > diff --git a/lib/conntrack.c b/lib/conntrack.c > index 983f824d2..a284c57c0 100644 > --- a/lib/conntrack.c > +++ b/lib/conntrack.c > @@ -96,7 +96,6 @@ static struct conn *new_conn(struct conntrack *ct, > struct dp_packet *pkt, > uint32_t tp_id); > static void delete_conn_cmn(struct conn *); > static void delete_conn(struct conn *); > -static void delete_conn_one(struct conn *conn); > static enum ct_update_res conn_update(struct conntrack *ct, struct conn > *conn, > struct dp_packet *pkt, > struct conn_lookup_ctx *ctx, > @@ -110,8 +109,7 @@ static void set_label(struct dp_packet *, struct conn > *, > static void *clean_thread_main(void *f_); > > static bool > -nat_get_unique_tuple(struct conntrack *ct, const struct conn *conn, > - struct conn *nat_conn, > +nat_get_unique_tuple(struct conntrack *ct, struct conn *conn, > const struct nat_action_info_t *nat_info); > > static uint8_t > @@ -231,61 +229,6 @@ conn_key_cmp(const struct conn_key *key1, const > struct conn_key *key2) > return 1; > } > > -static void > -ct_print_conn_info(const struct conn *c, const char *log_msg, > - enum vlog_level vll, bool force, bool rl_on) > -{ > -#define CT_VLOG(RL_ON, LEVEL, ...) > \ > - do { > \ > - if (RL_ON) { > \ > - static struct vlog_rate_limit rl_ = VLOG_RATE_LIMIT_INIT(5, > 5); \ > - vlog_rate_limit(&this_module, LEVEL, &rl_, __VA_ARGS__); > \ > - } else { > \ > - vlog(&this_module, LEVEL, __VA_ARGS__); > \ > - } > \ > - } while (0) > - > - if (OVS_UNLIKELY(force || vlog_is_enabled(&this_module, vll))) { > - if (c->key.dl_type == htons(ETH_TYPE_IP)) { > - CT_VLOG(rl_on, vll, "%s: src ip "IP_FMT" dst ip "IP_FMT" rev > src " > - "ip "IP_FMT" rev dst ip "IP_FMT" src/dst ports " > - "%"PRIu16"/%"PRIu16" rev src/dst ports " > - "%"PRIu16"/%"PRIu16" zone/rev zone " > - "%"PRIu16"/%"PRIu16" nw_proto/rev nw_proto " > - "%"PRIu8"/%"PRIu8, log_msg, > - IP_ARGS(c->key.src.addr.ipv4), > - IP_ARGS(c->key.dst.addr.ipv4), > - IP_ARGS(c->rev_key.src.addr.ipv4), > - IP_ARGS(c->rev_key.dst.addr.ipv4), > - ntohs(c->key.src.port), ntohs(c->key.dst.port), > - ntohs(c->rev_key.src.port), > ntohs(c->rev_key.dst.port), > - c->key.zone, c->rev_key.zone, c->key.nw_proto, > - c->rev_key.nw_proto); > - } else { > - char ip6_s[INET6_ADDRSTRLEN]; > - inet_ntop(AF_INET6, &c->key.src.addr.ipv6, ip6_s, sizeof > ip6_s); > - char ip6_d[INET6_ADDRSTRLEN]; > - inet_ntop(AF_INET6, &c->key.dst.addr.ipv6, ip6_d, sizeof > ip6_d); > - char ip6_rs[INET6_ADDRSTRLEN]; > - inet_ntop(AF_INET6, &c->rev_key.src.addr.ipv6, ip6_rs, > - sizeof ip6_rs); > - char ip6_rd[INET6_ADDRSTRLEN]; > - inet_ntop(AF_INET6, &c->rev_key.dst.addr.ipv6, ip6_rd, > - sizeof ip6_rd); > - > - CT_VLOG(rl_on, vll, "%s: src ip %s dst ip %s rev src ip %s" > - " rev dst ip %s src/dst ports %"PRIu16"/%"PRIu16 > - " rev src/dst ports %"PRIu16"/%"PRIu16" zone/rev zone > " > - "%"PRIu16"/%"PRIu16" nw_proto/rev nw_proto " > - "%"PRIu8"/%"PRIu8, log_msg, ip6_s, ip6_d, ip6_rs, > - ip6_rd, ntohs(c->key.src.port), > ntohs(c->key.dst.port), > - ntohs(c->rev_key.src.port), > ntohs(c->rev_key.dst.port), > - c->key.zone, c->rev_key.zone, c->key.nw_proto, > - c->rev_key.nw_proto); > - } > - } > -} > - > /* Initializes the connection tracker 'ct'. The caller is responsible for > * calling 'conntrack_destroy()', when the instance is not needed anymore > */ > struct conntrack * > @@ -467,34 +410,28 @@ zone_limit_delete(struct conntrack *ct, uint16_t > zone) > } > > static void > -conn_clean_cmn(struct conntrack *ct, struct conn *conn) > +conn_clean(struct conntrack *ct, struct conn *conn) > OVS_REQUIRES(ct->ct_lock) > { > + struct zone_limit *zl; > + uint32_t hash; > + > if (conn->alg) { > - expectation_clean(ct, &conn->key); > + expectation_clean(ct, &conn->key_node[CT_DIR_FWD].key); > } > > - uint32_t hash = conn_key_hash(&conn->key, ct->hash_basis); > - cmap_remove(&ct->conns, &conn->cm_node, hash); > + hash = conn_key_hash(&conn->key_node[CT_DIR_FWD].key, ct->hash_basis); > + cmap_remove(&ct->conns, &conn->key_node[CT_DIR_FWD].cm_node, hash); > > - struct zone_limit *zl = zone_limit_lookup(ct, conn->admit_zone); > + zl = zone_limit_lookup(ct, conn->admit_zone); > if (zl && zl->czl.zone_limit_seq == conn->zone_limit_seq) { > atomic_count_dec(&zl->czl.count); > } > -} > > -/* Must be called with 'conn' of 'conn_type' CT_CONN_TYPE_DEFAULT. Also > - * removes the associated nat 'conn' from the lookup datastructures. */ > -static void > -conn_clean(struct conntrack *ct, struct conn *conn) > - OVS_REQUIRES(ct->ct_lock) > -{ > - ovs_assert(conn->conn_type == CT_CONN_TYPE_DEFAULT); > - > - conn_clean_cmn(ct, conn); > - if (conn->nat_conn) { > - uint32_t hash = conn_key_hash(&conn->nat_conn->key, > ct->hash_basis); > - cmap_remove(&ct->conns, &conn->nat_conn->cm_node, hash); > + if (conn->nat_action) { > + hash = conn_key_hash(&conn->key_node[CT_DIR_REV].key, > + ct->hash_basis); > + cmap_remove(&ct->conns, &conn->key_node[CT_DIR_REV].cm_node, > hash); > } > ovs_list_remove(&conn->exp_node); > conn->cleaned = true; > @@ -502,33 +439,26 @@ conn_clean(struct conntrack *ct, struct conn *conn) > atomic_count_dec(&ct->n_conn); > } > > -static void > -conn_clean_one(struct conntrack *ct, struct conn *conn) > - OVS_REQUIRES(ct->ct_lock) > -{ > - conn_clean_cmn(ct, conn); > - if (conn->conn_type == CT_CONN_TYPE_DEFAULT) { > - ovs_list_remove(&conn->exp_node); > - conn->cleaned = true; > - atomic_count_dec(&ct->n_conn); > - } > - ovsrcu_postpone(delete_conn_one, conn); > -} > - > /* Destroys the connection tracker 'ct' and frees all the allocated > memory. > * The caller of this function must already have shut down packet input > * and PMD threads (which would have been quiesced). */ > void > conntrack_destroy(struct conntrack *ct) > { > + struct conn_key_node *keyn; > struct conn *conn; > + > latch_set(&ct->clean_thread_exit); > pthread_join(ct->clean_thread, NULL); > latch_destroy(&ct->clean_thread_exit); > > ovs_mutex_lock(&ct->ct_lock); > - CMAP_FOR_EACH (conn, cm_node, &ct->conns) { > - conn_clean_one(ct, conn); > + CMAP_FOR_EACH (keyn, cm_node, &ct->conns) { > + if (keyn->key.dir != CT_DIR_FWD) { > + continue; > + } > + conn = CONTAINER_OF(keyn, struct conn, key_node[keyn->key.dir]); > + conn_clean(ct, conn); > } > cmap_destroy(&ct->conns); > > @@ -573,31 +503,31 @@ conn_key_lookup(struct conntrack *ct, const struct > conn_key *key, > uint32_t hash, long long now, struct conn **conn_out, > bool *reply) > { > - struct conn *conn; > + struct conn_key_node *keyn; > + struct conn *conn = NULL; > bool found = false; > > - CMAP_FOR_EACH_WITH_HASH (conn, cm_node, hash, &ct->conns) { > - if (!conn_key_cmp(&conn->key, key) && !conn_expired(conn, now)) { > - found = true; > - if (reply) { > - *reply = false; > - } > - break; > - } > - if (!conn_key_cmp(&conn->rev_key, key) && !conn_expired(conn, > now)) { > - found = true; > - if (reply) { > - *reply = true; > + CMAP_FOR_EACH_WITH_HASH (keyn, cm_node, hash, &ct->conns) { > + conn = CONTAINER_OF(keyn, struct conn, key_node[keyn->key.dir]); > + for (int i = CT_DIR_FWD; i < CT_DIR_MAX; i++) { > + if (!conn_key_cmp(&conn->key_node[i].key, key) && > + !conn_expired(conn, now)) { > + found = true; > + if (reply) { > + *reply = i; > + } > + goto out_found; > } > - break; > } > } > > +out_found: > if (found && conn_out) { > *conn_out = conn; > } else if (conn_out) { > *conn_out = NULL; > } > + > return found; > } > > @@ -631,7 +561,7 @@ write_ct_md(struct dp_packet *pkt, uint16_t zone, > const struct conn *conn, > if (conn->alg_related) { > key = &conn->parent_key; > } else { > - key = &conn->key; > + key = &conn->key_node[CT_DIR_FWD].key; > } > } else if (alg_exp) { > pkt->md.ct_mark = alg_exp->parent_mark; > @@ -754,21 +684,24 @@ handle_alg_ctl(struct conntrack *ct, const struct > conn_lookup_ctx *ctx, > static void > pat_packet(struct dp_packet *pkt, const struct conn *conn) > { > + const struct conn_key *rev_key = &conn->key_node[CT_DIR_REV].key, > + *key = &conn->key_node[CT_DIR_FWD].key; > + > if (conn->nat_action & NAT_ACTION_SRC) { > - if (conn->key.nw_proto == IPPROTO_TCP) { > + if (key->nw_proto == IPPROTO_TCP) { > struct tcp_header *th = dp_packet_l4(pkt); > - packet_set_tcp_port(pkt, conn->rev_key.dst.port, th->tcp_dst); > - } else if (conn->key.nw_proto == IPPROTO_UDP) { > + packet_set_tcp_port(pkt, rev_key->dst.port, th->tcp_dst); > + } else if (key->nw_proto == IPPROTO_UDP) { > struct udp_header *uh = dp_packet_l4(pkt); > - packet_set_udp_port(pkt, conn->rev_key.dst.port, uh->udp_dst); > + packet_set_udp_port(pkt, rev_key->dst.port, uh->udp_dst); > } > } else if (conn->nat_action & NAT_ACTION_DST) { > - if (conn->key.nw_proto == IPPROTO_TCP) { > - packet_set_tcp_port(pkt, conn->rev_key.dst.port, > - conn->rev_key.src.port); > - } else if (conn->key.nw_proto == IPPROTO_UDP) { > - packet_set_udp_port(pkt, conn->rev_key.dst.port, > - conn->rev_key.src.port); > + if (key->nw_proto == IPPROTO_TCP) { > + packet_set_tcp_port(pkt, rev_key->dst.port, > + rev_key->src.port); > + } else if (key->nw_proto == IPPROTO_UDP) { > + packet_set_udp_port(pkt, rev_key->dst.port, > + rev_key->src.port); > } > } > } > @@ -776,32 +709,35 @@ pat_packet(struct dp_packet *pkt, const struct conn > *conn) > static void > nat_packet(struct dp_packet *pkt, const struct conn *conn, bool related) > { > + const struct conn_key *rev_key = &conn->key_node[CT_DIR_REV].key, > + *key = &conn->key_node[CT_DIR_FWD].key; > + > if (conn->nat_action & NAT_ACTION_SRC) { > pkt->md.ct_state |= CS_SRC_NAT; > - if (conn->key.dl_type == htons(ETH_TYPE_IP)) { > + if (key->dl_type == htons(ETH_TYPE_IP)) { > struct ip_header *nh = dp_packet_l3(pkt); > packet_set_ipv4_addr(pkt, &nh->ip_src, > - conn->rev_key.dst.addr.ipv4); > + rev_key->dst.addr.ipv4); > } else { > struct ovs_16aligned_ip6_hdr *nh6 = dp_packet_l3(pkt); > - packet_set_ipv6_addr(pkt, conn->key.nw_proto, > + packet_set_ipv6_addr(pkt, key->nw_proto, > nh6->ip6_src.be32, > - &conn->rev_key.dst.addr.ipv6, true); > + &rev_key->dst.addr.ipv6, true); > } > if (!related) { > pat_packet(pkt, conn); > } > } else if (conn->nat_action & NAT_ACTION_DST) { > pkt->md.ct_state |= CS_DST_NAT; > - if (conn->key.dl_type == htons(ETH_TYPE_IP)) { > + if (key->dl_type == htons(ETH_TYPE_IP)) { > struct ip_header *nh = dp_packet_l3(pkt); > packet_set_ipv4_addr(pkt, &nh->ip_dst, > - conn->rev_key.src.addr.ipv4); > + rev_key->src.addr.ipv4); > } else { > struct ovs_16aligned_ip6_hdr *nh6 = dp_packet_l3(pkt); > - packet_set_ipv6_addr(pkt, conn->key.nw_proto, > + packet_set_ipv6_addr(pkt, key->nw_proto, > nh6->ip6_dst.be32, > - &conn->rev_key.src.addr.ipv6, true); > + &rev_key->src.addr.ipv6, true); > } > if (!related) { > pat_packet(pkt, conn); > @@ -812,19 +748,21 @@ nat_packet(struct dp_packet *pkt, const struct conn > *conn, bool related) > static void > un_pat_packet(struct dp_packet *pkt, const struct conn *conn) > { > + const struct conn_key *key = &conn->key_node[CT_DIR_FWD].key; > + > if (conn->nat_action & NAT_ACTION_SRC) { > - if (conn->key.nw_proto == IPPROTO_TCP) { > + if (key->nw_proto == IPPROTO_TCP) { > struct tcp_header *th = dp_packet_l4(pkt); > - packet_set_tcp_port(pkt, th->tcp_src, conn->key.src.port); > - } else if (conn->key.nw_proto == IPPROTO_UDP) { > + packet_set_tcp_port(pkt, th->tcp_src, key->src.port); > + } else if (key->nw_proto == IPPROTO_UDP) { > struct udp_header *uh = dp_packet_l4(pkt); > - packet_set_udp_port(pkt, uh->udp_src, conn->key.src.port); > + packet_set_udp_port(pkt, uh->udp_src, key->src.port); > } > } else if (conn->nat_action & NAT_ACTION_DST) { > - if (conn->key.nw_proto == IPPROTO_TCP) { > - packet_set_tcp_port(pkt, conn->key.dst.port, > conn->key.src.port); > - } else if (conn->key.nw_proto == IPPROTO_UDP) { > - packet_set_udp_port(pkt, conn->key.dst.port, > conn->key.src.port); > + if (key->nw_proto == IPPROTO_TCP) { > + packet_set_tcp_port(pkt, key->dst.port, key->src.port); > + } else if (key->nw_proto == IPPROTO_UDP) { > + packet_set_udp_port(pkt, key->dst.port, key->src.port); > } > } > } > @@ -832,23 +770,25 @@ un_pat_packet(struct dp_packet *pkt, const struct > conn *conn) > static void > reverse_pat_packet(struct dp_packet *pkt, const struct conn *conn) > { > + const struct conn_key *key = &conn->key_node[CT_DIR_FWD].key; > + > if (conn->nat_action & NAT_ACTION_SRC) { > - if (conn->key.nw_proto == IPPROTO_TCP) { > + if (key->nw_proto == IPPROTO_TCP) { > struct tcp_header *th_in = dp_packet_l4(pkt); > - packet_set_tcp_port(pkt, conn->key.src.port, > + packet_set_tcp_port(pkt, key->src.port, > th_in->tcp_dst); > - } else if (conn->key.nw_proto == IPPROTO_UDP) { > + } else if (key->nw_proto == IPPROTO_UDP) { > struct udp_header *uh_in = dp_packet_l4(pkt); > - packet_set_udp_port(pkt, conn->key.src.port, > + packet_set_udp_port(pkt, key->src.port, > uh_in->udp_dst); > } > } else if (conn->nat_action & NAT_ACTION_DST) { > - if (conn->key.nw_proto == IPPROTO_TCP) { > - packet_set_tcp_port(pkt, conn->key.src.port, > - conn->key.dst.port); > - } else if (conn->key.nw_proto == IPPROTO_UDP) { > - packet_set_udp_port(pkt, conn->key.src.port, > - conn->key.dst.port); > + if (key->nw_proto == IPPROTO_TCP) { > + packet_set_tcp_port(pkt, key->src.port, > + key->dst.port); > + } else if (key->nw_proto == IPPROTO_UDP) { > + packet_set_udp_port(pkt, key->src.port, > + key->dst.port); > } > } > } > @@ -856,6 +796,7 @@ reverse_pat_packet(struct dp_packet *pkt, const struct > conn *conn) > static void > reverse_nat_packet(struct dp_packet *pkt, const struct conn *conn) > { > + const struct conn_key *key = &conn->key_node[CT_DIR_FWD].key; > char *tail = dp_packet_tail(pkt); > uint16_t pad = dp_packet_l2_pad_size(pkt); > struct conn_key inner_key; > @@ -863,7 +804,7 @@ reverse_nat_packet(struct dp_packet *pkt, const struct > conn *conn) > uint16_t orig_l3_ofs = pkt->l3_ofs; > uint16_t orig_l4_ofs = pkt->l4_ofs; > > - if (conn->key.dl_type == htons(ETH_TYPE_IP)) { > + if (key->dl_type == htons(ETH_TYPE_IP)) { > struct ip_header *nh = dp_packet_l3(pkt); > struct icmp_header *icmp = dp_packet_l4(pkt); > struct ip_header *inner_l3 = (struct ip_header *) (icmp + 1); > @@ -876,10 +817,10 @@ reverse_nat_packet(struct dp_packet *pkt, const > struct conn *conn) > > if (conn->nat_action & NAT_ACTION_SRC) { > packet_set_ipv4_addr(pkt, &inner_l3->ip_src, > - conn->key.src.addr.ipv4); > + key->src.addr.ipv4); > } else if (conn->nat_action & NAT_ACTION_DST) { > packet_set_ipv4_addr(pkt, &inner_l3->ip_dst, > - conn->key.dst.addr.ipv4); > + key->dst.addr.ipv4); > } > > reverse_pat_packet(pkt, conn); > @@ -899,13 +840,13 @@ reverse_nat_packet(struct dp_packet *pkt, const > struct conn *conn) > pkt->l4_ofs += inner_l4 - (char *) icmp6; > > if (conn->nat_action & NAT_ACTION_SRC) { > - packet_set_ipv6_addr(pkt, conn->key.nw_proto, > + packet_set_ipv6_addr(pkt, key->nw_proto, > inner_l3_6->ip6_src.be32, > - &conn->key.src.addr.ipv6, true); > + &key->src.addr.ipv6, true); > } else if (conn->nat_action & NAT_ACTION_DST) { > - packet_set_ipv6_addr(pkt, conn->key.nw_proto, > + packet_set_ipv6_addr(pkt, key->nw_proto, > inner_l3_6->ip6_dst.be32, > - &conn->key.dst.addr.ipv6, true); > + &key->dst.addr.ipv6, true); > } > reverse_pat_packet(pkt, conn); > icmp6->icmp6_base.icmp6_cksum = 0; > @@ -920,17 +861,19 @@ static void > un_nat_packet(struct dp_packet *pkt, const struct conn *conn, > bool related) > { > + const struct conn_key *key = &conn->key_node[CT_DIR_FWD].key; > + > if (conn->nat_action & NAT_ACTION_SRC) { > pkt->md.ct_state |= CS_DST_NAT; > - if (conn->key.dl_type == htons(ETH_TYPE_IP)) { > + if (key->dl_type == htons(ETH_TYPE_IP)) { > struct ip_header *nh = dp_packet_l3(pkt); > packet_set_ipv4_addr(pkt, &nh->ip_dst, > - conn->key.src.addr.ipv4); > + key->src.addr.ipv4); > } else { > struct ovs_16aligned_ip6_hdr *nh6 = dp_packet_l3(pkt); > - packet_set_ipv6_addr(pkt, conn->key.nw_proto, > + packet_set_ipv6_addr(pkt, key->nw_proto, > nh6->ip6_dst.be32, > - &conn->key.src.addr.ipv6, true); > + &key->src.addr.ipv6, true); > } > > if (OVS_UNLIKELY(related)) { > @@ -940,15 +883,15 @@ un_nat_packet(struct dp_packet *pkt, const struct > conn *conn, > } > } else if (conn->nat_action & NAT_ACTION_DST) { > pkt->md.ct_state |= CS_SRC_NAT; > - if (conn->key.dl_type == htons(ETH_TYPE_IP)) { > + if (key->dl_type == htons(ETH_TYPE_IP)) { > struct ip_header *nh = dp_packet_l3(pkt); > packet_set_ipv4_addr(pkt, &nh->ip_src, > - conn->key.dst.addr.ipv4); > + key->dst.addr.ipv4); > } else { > struct ovs_16aligned_ip6_hdr *nh6 = dp_packet_l3(pkt); > - packet_set_ipv6_addr(pkt, conn->key.nw_proto, > + packet_set_ipv6_addr(pkt, key->nw_proto, > nh6->ip6_src.be32, > - &conn->key.dst.addr.ipv6, true); > + &key->dst.addr.ipv6, true); > } > > if (OVS_UNLIKELY(related)) { > @@ -966,7 +909,7 @@ conn_seq_skew_set(struct conntrack *ct, const struct > conn *conn_in, > { > struct conn *conn; > ovs_mutex_unlock(&conn_in->lock); > - conn_lookup(ct, &conn_in->key, now, &conn, NULL); > + conn_lookup(ct, &conn_in->key_node[CT_DIR_FWD].key, now, &conn, NULL); > ovs_mutex_lock(&conn_in->lock); > > if (conn && seq_skew) { > @@ -1004,7 +947,7 @@ conn_not_found(struct conntrack *ct, struct dp_packet > *pkt, > OVS_REQUIRES(ct->ct_lock) > { > struct conn *nc = NULL; > - struct conn *nat_conn = NULL; > + uint32_t rev_hash = ctx->hash; > > if (!valid_new(pkt, &ctx->key)) { > pkt->md.ct_state = CS_INVALID; > @@ -1018,6 +961,8 @@ conn_not_found(struct conntrack *ct, struct dp_packet > *pkt, > } > > if (commit) { > + struct conn_key_node *fwd_key_node, *rev_key_node; > + > struct zone_limit *zl = zone_limit_lookup_or_default(ct, > > ctx->key.zone); > if (zl && atomic_count_get(&zl->czl.count) >= zl->czl.limit) { > @@ -1032,9 +977,12 @@ conn_not_found(struct conntrack *ct, struct > dp_packet *pkt, > } > > nc = new_conn(ct, pkt, &ctx->key, now, tp_id); > - memcpy(&nc->key, &ctx->key, sizeof nc->key); > - memcpy(&nc->rev_key, &nc->key, sizeof nc->rev_key); > - conn_key_reverse(&nc->rev_key); > + fwd_key_node = &nc->key_node[CT_DIR_FWD]; > + rev_key_node = &nc->key_node[CT_DIR_REV]; > + memcpy(&fwd_key_node->key, &ctx->key, sizeof fwd_key_node->key); > + memcpy(&rev_key_node->key, &fwd_key_node->key, > + sizeof rev_key_node->key); > + conn_key_reverse(&rev_key_node->key); > > if (ct_verify_helper(helper, ct_alg_ctl)) { > nc->alg = nullable_xstrdup(helper); > @@ -1049,45 +997,33 @@ conn_not_found(struct conntrack *ct, struct > dp_packet *pkt, > > if (nat_action_info) { > nc->nat_action = nat_action_info->nat_action; > - nat_conn = xzalloc(sizeof *nat_conn); > > if (alg_exp) { > if (alg_exp->nat_rpl_dst) { > - nc->rev_key.dst.addr = alg_exp->alg_nat_repl_addr; > + rev_key_node->key.dst.addr = > alg_exp->alg_nat_repl_addr; > nc->nat_action = NAT_ACTION_SRC; > } else { > - nc->rev_key.src.addr = alg_exp->alg_nat_repl_addr; > + rev_key_node->key.src.addr = > alg_exp->alg_nat_repl_addr; > nc->nat_action = NAT_ACTION_DST; > } > } else { > - memcpy(nat_conn, nc, sizeof *nat_conn); > - bool nat_res = nat_get_unique_tuple(ct, nc, nat_conn, > - nat_action_info); > + bool nat_res = nat_get_unique_tuple(ct, nc, > nat_action_info); > > if (!nat_res) { > goto nat_res_exhaustion; > } > - > - /* Update nc with nat adjustments made to nat_conn by > - * nat_get_unique_tuple(). */ > - memcpy(nc, nat_conn, sizeof *nc); > } > > nat_packet(pkt, nc, ctx->icmp_related); > - memcpy(&nat_conn->key, &nc->rev_key, sizeof nat_conn->key); > - memcpy(&nat_conn->rev_key, &nc->key, sizeof > nat_conn->rev_key); > - nat_conn->conn_type = CT_CONN_TYPE_UN_NAT; > - nat_conn->nat_action = 0; > - nat_conn->alg = NULL; > - nat_conn->nat_conn = NULL; > - uint32_t nat_hash = conn_key_hash(&nat_conn->key, > ct->hash_basis); > - cmap_insert(&ct->conns, &nat_conn->cm_node, nat_hash); > + rev_hash = conn_key_hash(&rev_key_node->key, ct->hash_basis); > + rev_key_node->key.dir = CT_DIR_REV; > + cmap_insert(&ct->conns, &rev_key_node->cm_node, rev_hash); > } > > - nc->nat_conn = nat_conn; > ovs_mutex_init_adaptive(&nc->lock); > - nc->conn_type = CT_CONN_TYPE_DEFAULT; > - cmap_insert(&ct->conns, &nc->cm_node, ctx->hash); > + fwd_key_node->key.dir = CT_DIR_FWD; > + cmap_insert(&ct->conns, &fwd_key_node->cm_node, ctx->hash); > + > atomic_count_inc(&ct->n_conn); > ctx->conn = nc; /* For completeness. */ > if (zl) { > @@ -1107,7 +1043,6 @@ conn_not_found(struct conntrack *ct, struct > dp_packet *pkt, > * firewall rules or a separate firewall. Also using zone > partitioning > * can limit DoS impact. */ > nat_res_exhaustion: > - free(nat_conn); > ovs_list_remove(&nc->exp_node); > delete_conn_cmn(nc); > static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5); > @@ -1121,7 +1056,6 @@ conn_update_state(struct conntrack *ct, struct > dp_packet *pkt, > struct conn_lookup_ctx *ctx, struct conn *conn, > long long now) > { > - ovs_assert(conn->conn_type == CT_CONN_TYPE_DEFAULT); > bool create_new_conn = false; > > if (ctx->icmp_related) { > @@ -1149,7 +1083,8 @@ conn_update_state(struct conntrack *ct, struct > dp_packet *pkt, > break; > case CT_UPDATE_NEW: > ovs_mutex_lock(&ct->ct_lock); > - if (conn_lookup(ct, &conn->key, now, NULL, NULL)) { > + if (conn_lookup(ct, &conn->key_node[CT_DIR_FWD].key, > + now, NULL, NULL)) { > conn_clean(ct, conn); > } > ovs_mutex_unlock(&ct->ct_lock); > @@ -1330,11 +1265,12 @@ initial_conn_lookup(struct conntrack *ct, struct > conn_lookup_ctx *ctx, > if (natted) { > if (OVS_LIKELY(ctx->conn)) { > ctx->reply = !ctx->reply; > - ctx->key = ctx->reply ? ctx->conn->rev_key : ctx->conn->key; > + ctx->key = ctx->conn->key_node[ctx->reply ? > + CT_DIR_REV : CT_DIR_FWD].key; > ctx->hash = conn_key_hash(&ctx->key, ct->hash_basis); > } else { > /* A lookup failure does not necessarily imply that an > - * error occurred, it may simply indicate that a conn got > + * error occurred, it may simply indicate that a ctx->conn got > * removed during the recirculation. */ > COVERAGE_INC(conntrack_lookup_natted_miss); > conn_key_reverse(&ctx->key); > @@ -1364,32 +1300,14 @@ process_one(struct conntrack *ct, struct dp_packet > *pkt, > /* Delete found entry if in wrong direction. 'force' implies commit. > */ > if (OVS_UNLIKELY(force && ctx->reply && conn)) { > ovs_mutex_lock(&ct->ct_lock); > - if (conn_lookup(ct, &conn->key, now, NULL, NULL)) { > + if (conn_lookup(ct, &conn->key_node[CT_DIR_FWD].key, > + now, NULL, NULL)) { > conn_clean(ct, conn); > } > ovs_mutex_unlock(&ct->ct_lock); > conn = NULL; > } > > - if (OVS_LIKELY(conn)) { > - if (conn->conn_type == CT_CONN_TYPE_UN_NAT) { > - > - ctx->reply = true; > - struct conn *rev_conn = conn; /* Save for debugging. */ > - uint32_t hash = conn_key_hash(&conn->rev_key, ct->hash_basis); > - conn_key_lookup(ct, &ctx->key, hash, now, &conn, &ctx->reply); > - > - if (!conn) { > - pkt->md.ct_state |= CS_INVALID; > - write_ct_md(pkt, zone, NULL, NULL, NULL); > - char *log_msg = xasprintf("Missing parent conn %p", > rev_conn); > - ct_print_conn_info(rev_conn, log_msg, VLL_INFO, true, > true); > - free(log_msg); > - return; > - } > - } > - } > - > enum ct_alg_ctl_type ct_alg_ctl = get_alg_ctl_type(pkt, tp_src, > tp_dst, > helper); > > @@ -1482,7 +1400,8 @@ conntrack_execute(struct conntrack *ct, struct > dp_packet_batch *pkt_batch, > struct conn *conn = packet->md.conn; > if (OVS_UNLIKELY(packet->md.ct_state == CS_INVALID)) { > write_ct_md(packet, zone, NULL, NULL, NULL); > - } else if (conn && conn->key.zone == zone && !force > + } else if (conn && > + conn->key_node[CT_DIR_FWD].key.zone == zone && !force > && !get_alg_ctl_type(packet, tp_src, tp_dst, helper)) { > process_one_fast(zone, setmark, setlabel, nat_action_info, > conn, packet); > @@ -2263,7 +2182,7 @@ nat_ipv6_addr_increment(struct in6_addr *ipv6, > uint32_t increment) > } > > static uint32_t > -nat_range_hash(const struct conn *conn, uint32_t basis, > +nat_range_hash(struct conn_key *key, uint32_t basis, > const struct nat_action_info_t *nat_info) > { > uint32_t hash = basis; > @@ -2273,11 +2192,11 @@ nat_range_hash(const struct conn *conn, uint32_t > basis, > hash = hash_add(hash, > (nat_info->max_port << 16) > | nat_info->min_port); > - hash = ct_endpoint_hash_add(hash, &conn->key.src); > - hash = ct_endpoint_hash_add(hash, &conn->key.dst); > - hash = hash_add(hash, (OVS_FORCE uint32_t) conn->key.dl_type); > - hash = hash_add(hash, conn->key.nw_proto); > - hash = hash_add(hash, conn->key.zone); > + hash = ct_endpoint_hash_add(hash, &key->src); > + hash = ct_endpoint_hash_add(hash, &key->dst); > + hash = hash_add(hash, (OVS_FORCE uint32_t) key->dl_type); > + hash = hash_add(hash, key->nw_proto); > + hash = hash_add(hash, key->zone); > > /* The purpose of the second parameter is to distinguish hashes of > data of > * different length; our data always has the same length so there is > no > @@ -2343,7 +2262,7 @@ get_addr_in_range(union ct_addr *min, union ct_addr > *max, > } > > static void > -get_initial_addr(const struct conn *conn, union ct_addr *min, > +get_initial_addr(struct conn_key *key, union ct_addr *min, > union ct_addr *max, union ct_addr *curr, > uint32_t hash, bool ipv4, > const struct nat_action_info_t *nat_info) > @@ -2353,9 +2272,9 @@ get_initial_addr(const struct conn *conn, union > ct_addr *min, > /* All-zero case. */ > if (!memcmp(min, &zero_ip, sizeof *min)) { > if (nat_info->nat_action & NAT_ACTION_SRC) { > - *curr = conn->key.src.addr; > + *curr = key->src.addr; > } else if (nat_info->nat_action & NAT_ACTION_DST) { > - *curr = conn->key.dst.addr; > + *curr = key->dst.addr; > } > } else { > get_addr_in_range(min, max, curr, hash, ipv4); > @@ -2438,39 +2357,42 @@ next_addr_in_range_guarded(union ct_addr *curr, > union ct_addr *min, > * > * If none can be found, return exhaustion to the caller. */ > static bool > -nat_get_unique_tuple(struct conntrack *ct, const struct conn *conn, > - struct conn *nat_conn, > +nat_get_unique_tuple(struct conntrack *ct, struct conn *conn, > const struct nat_action_info_t *nat_info) > { > union ct_addr min_addr = {0}, max_addr = {0}, curr_addr = {0}, > guard_addr = {0}; > - uint32_t hash = nat_range_hash(conn, ct->hash_basis, nat_info); > - bool pat_proto = conn->key.nw_proto == IPPROTO_TCP || > - conn->key.nw_proto == IPPROTO_UDP; > + struct conn_key *fwd_key = &conn->key_node[CT_DIR_FWD].key, > + *rev_key = &conn->key_node[CT_DIR_REV].key; > + bool pat_proto = fwd_key->nw_proto == IPPROTO_TCP || > + fwd_key->nw_proto == IPPROTO_UDP; > uint16_t min_dport, max_dport, curr_dport; > uint16_t min_sport, max_sport, curr_sport; > + uint32_t hash; > + > + hash = nat_range_hash(fwd_key, ct->hash_basis, nat_info); > > min_addr = nat_info->min_addr; > max_addr = nat_info->max_addr; > > - get_initial_addr(conn, &min_addr, &max_addr, &curr_addr, hash, > - (conn->key.dl_type == htons(ETH_TYPE_IP)), nat_info); > + get_initial_addr(fwd_key, &min_addr, &max_addr, &curr_addr, hash, > + (fwd_key->dl_type == htons(ETH_TYPE_IP)), nat_info); > > /* Save the address we started from so that > * we can stop once we reach it. */ > guard_addr = curr_addr; > > - set_sport_range(nat_info, &conn->key, hash, &curr_sport, > + set_sport_range(nat_info, fwd_key, hash, &curr_sport, > &min_sport, &max_sport); > - set_dport_range(nat_info, &conn->key, hash, &curr_dport, > + set_dport_range(nat_info, fwd_key, hash, &curr_dport, > &min_dport, &max_dport); > > another_round: > - store_addr_to_key(&curr_addr, &nat_conn->rev_key, > + store_addr_to_key(&curr_addr, rev_key, > nat_info->nat_action); > > if (!pat_proto) { > - if (!conn_lookup(ct, &nat_conn->rev_key, > + if (!conn_lookup(ct, rev_key, > time_msec(), NULL, NULL)) { > return true; > } > @@ -2479,10 +2401,10 @@ another_round: > } > > FOR_EACH_PORT_IN_RANGE(curr_dport, min_dport, max_dport) { > - nat_conn->rev_key.src.port = htons(curr_dport); > + rev_key->src.port = htons(curr_dport); > FOR_EACH_PORT_IN_RANGE(curr_sport, min_sport, max_sport) { > - nat_conn->rev_key.dst.port = htons(curr_sport); > - if (!conn_lookup(ct, &nat_conn->rev_key, > + rev_key->dst.port = htons(curr_sport); > + if (!conn_lookup(ct, rev_key, > time_msec(), NULL, NULL)) { > return true; > } > @@ -2494,7 +2416,7 @@ another_round: > next_addr: > if (next_addr_in_range_guarded(&curr_addr, &min_addr, > &max_addr, &guard_addr, > - conn->key.dl_type == > htons(ETH_TYPE_IP))) { > + fwd_key->dl_type == > htons(ETH_TYPE_IP))) { > return false; > } > > @@ -2506,9 +2428,9 @@ conn_update(struct conntrack *ct, struct conn *conn, > struct dp_packet *pkt, > struct conn_lookup_ctx *ctx, long long now) > { > ovs_mutex_lock(&conn->lock); > + uint8_t nw_proto = conn->key_node[CT_DIR_FWD].key.nw_proto; > enum ct_update_res update_res = > - l4_protos[conn->key.nw_proto]->conn_update(ct, conn, pkt, > ctx->reply, > - now); > + l4_protos[nw_proto]->conn_update(ct, conn, pkt, ctx->reply, now); > ovs_mutex_unlock(&conn->lock); > return update_res; > } > @@ -2516,13 +2438,10 @@ conn_update(struct conntrack *ct, struct conn > *conn, struct dp_packet *pkt, > static bool > conn_expired(struct conn *conn, long long now) > { > - if (conn->conn_type == CT_CONN_TYPE_DEFAULT) { > - ovs_mutex_lock(&conn->lock); > - bool expired = now >= conn->expiration ? true : false; > - ovs_mutex_unlock(&conn->lock); > - return expired; > - } > - return false; > + ovs_mutex_lock(&conn->lock); > + bool expired = now >= conn->expiration ? true : false; > + ovs_mutex_unlock(&conn->lock); > + return expired; > } > > static bool > @@ -2548,19 +2467,7 @@ delete_conn_cmn(struct conn *conn) > static void > delete_conn(struct conn *conn) > { > - ovs_assert(conn->conn_type == CT_CONN_TYPE_DEFAULT); > ovs_mutex_destroy(&conn->lock); > - free(conn->nat_conn); > - delete_conn_cmn(conn); > -} > - > -/* Only used by conn_clean_one(). */ > -static void > -delete_conn_one(struct conn *conn) > -{ > - if (conn->conn_type == CT_CONN_TYPE_DEFAULT) { > - ovs_mutex_destroy(&conn->lock); > - } > delete_conn_cmn(conn); > } > > @@ -2652,11 +2559,14 @@ static void > conn_to_ct_dpif_entry(const struct conn *conn, struct ct_dpif_entry > *entry, > long long now) > { > + const struct conn_key *key = &conn->key_node[CT_DIR_FWD].key, > + *rev_key = &conn->key_node[CT_DIR_REV].key; > + > memset(entry, 0, sizeof *entry); > - conn_key_to_tuple(&conn->key, &entry->tuple_orig); > - conn_key_to_tuple(&conn->rev_key, &entry->tuple_reply); > + conn_key_to_tuple(key, &entry->tuple_orig); > + conn_key_to_tuple(rev_key, &entry->tuple_reply); > > - entry->zone = conn->key.zone; > + entry->zone = key->zone; > > ovs_mutex_lock(&conn->lock); > entry->mark = conn->mark; > @@ -2664,7 +2574,7 @@ conn_to_ct_dpif_entry(const struct conn *conn, > struct ct_dpif_entry *entry, > > long long expiration = conn->expiration - now; > > - struct ct_l4_proto *class = l4_protos[conn->key.nw_proto]; > + struct ct_l4_proto *class = l4_protos[key->nw_proto]; > if (class->conn_get_protoinfo) { > class->conn_get_protoinfo(conn, &entry->protoinfo); > } > @@ -2712,10 +2622,12 @@ conntrack_dump_next(struct conntrack_dump *dump, > struct ct_dpif_entry *entry) > if (!cm_node) { > break; > } > + struct conn_key_node *keyn; > struct conn *conn; > - INIT_CONTAINER(conn, cm_node, cm_node); > - if ((!dump->filter_zone || conn->key.zone == dump->zone) && > - (conn->conn_type != CT_CONN_TYPE_UN_NAT)) { > + INIT_CONTAINER(keyn, cm_node, cm_node); > + conn = CONTAINER_OF(keyn, struct conn, key_node[keyn->key.dir]); > + if ((!dump->filter_zone || keyn->key.zone == dump->zone) && > + (keyn->key.dir == CT_DIR_FWD)) { > conn_to_ct_dpif_entry(conn, entry, now); > return 0; > } > @@ -2733,12 +2645,17 @@ conntrack_dump_done(struct conntrack_dump *dump > OVS_UNUSED) > int > conntrack_flush(struct conntrack *ct, const uint16_t *zone) > { > + struct conn_key_node *keyn; > struct conn *conn; > > ovs_mutex_lock(&ct->ct_lock); > - CMAP_FOR_EACH (conn, cm_node, &ct->conns) { > - if (!zone || *zone == conn->key.zone) { > - conn_clean_one(ct, conn); > + CMAP_FOR_EACH (keyn, cm_node, &ct->conns) { > + if (keyn->key.dir != CT_DIR_FWD) { > + continue; > + } > + conn = CONTAINER_OF(keyn, struct conn, key_node[keyn->key.dir]); > + if (!zone || *zone == keyn->key.zone) { > + conn_clean(ct, conn); > } > } > ovs_mutex_unlock(&ct->ct_lock); > @@ -2759,10 +2676,10 @@ conntrack_flush_tuple(struct conntrack *ct, const > struct ct_dpif_tuple *tuple, > ovs_mutex_lock(&ct->ct_lock); > conn_lookup(ct, &key, time_msec(), &conn, NULL); > > - if (conn && conn->conn_type == CT_CONN_TYPE_DEFAULT) { > + if (conn) { > conn_clean(ct, conn); > } else { > - VLOG_WARN("Must flush tuple using the original pre-NATed tuple"); > + VLOG_WARN("Tuple not found"); > error = ENOENT; > } > > @@ -2906,50 +2823,52 @@ expectation_create(struct conntrack *ct, ovs_be16 > dst_port, > const struct conn *parent_conn, bool reply, bool > src_ip_wc, > bool skip_nat) > { > + const struct conn_key *pconn_key = > &parent_conn->key_node[CT_DIR_FWD].key, > + *pconn_rev_key = &parent_conn->key_node[CT_DIR_REV].key; > union ct_addr src_addr; > union ct_addr dst_addr; > union ct_addr alg_nat_repl_addr; > struct alg_exp_node *alg_exp_node = xzalloc(sizeof *alg_exp_node); > > if (reply) { > - src_addr = parent_conn->key.src.addr; > - dst_addr = parent_conn->key.dst.addr; > + src_addr = pconn_key->src.addr; > + dst_addr = pconn_key->dst.addr; > alg_exp_node->nat_rpl_dst = true; > if (skip_nat) { > alg_nat_repl_addr = dst_addr; > } else if (parent_conn->nat_action & NAT_ACTION_DST) { > - alg_nat_repl_addr = parent_conn->rev_key.src.addr; > + alg_nat_repl_addr = pconn_rev_key->src.addr; > alg_exp_node->nat_rpl_dst = false; > } else { > - alg_nat_repl_addr = parent_conn->rev_key.dst.addr; > + alg_nat_repl_addr = pconn_rev_key->dst.addr; > } > } else { > - src_addr = parent_conn->rev_key.src.addr; > - dst_addr = parent_conn->rev_key.dst.addr; > + src_addr = pconn_rev_key->src.addr; > + dst_addr = pconn_rev_key->dst.addr; > alg_exp_node->nat_rpl_dst = false; > if (skip_nat) { > alg_nat_repl_addr = src_addr; > } else if (parent_conn->nat_action & NAT_ACTION_DST) { > - alg_nat_repl_addr = parent_conn->key.dst.addr; > + alg_nat_repl_addr = pconn_key->dst.addr; > alg_exp_node->nat_rpl_dst = true; > } else { > - alg_nat_repl_addr = parent_conn->key.src.addr; > + alg_nat_repl_addr = pconn_key->src.addr; > } > } > if (src_ip_wc) { > memset(&src_addr, 0, sizeof src_addr); > } > > - alg_exp_node->key.dl_type = parent_conn->key.dl_type; > - alg_exp_node->key.nw_proto = parent_conn->key.nw_proto; > - alg_exp_node->key.zone = parent_conn->key.zone; > + alg_exp_node->key.dl_type = pconn_key->dl_type; > + alg_exp_node->key.nw_proto = pconn_key->nw_proto; > + alg_exp_node->key.zone = pconn_key->zone; > alg_exp_node->key.src.addr = src_addr; > alg_exp_node->key.dst.addr = dst_addr; > alg_exp_node->key.src.port = ALG_WC_SRC_PORT; > alg_exp_node->key.dst.port = dst_port; > alg_exp_node->parent_mark = parent_conn->mark; > alg_exp_node->parent_label = parent_conn->label; > - memcpy(&alg_exp_node->parent_key, &parent_conn->key, > + memcpy(&alg_exp_node->parent_key, pconn_key, > sizeof alg_exp_node->parent_key); > /* Take the write lock here because it is almost 100% > * likely that the lookup will fail and > @@ -3201,12 +3120,16 @@ process_ftp_ctl_v4(struct conntrack *ct, > > switch (mode) { > case CT_FTP_MODE_ACTIVE: > - *v4_addr_rep = conn_for_expectation->rev_key.dst.addr.ipv4; > - conn_ipv4_addr = conn_for_expectation->key.src.addr.ipv4; > + *v4_addr_rep = > + conn_for_expectation->key_node[CT_DIR_REV].key.dst.addr.ipv4; > + conn_ipv4_addr = > + conn_for_expectation->key_node[CT_DIR_FWD].key.src.addr.ipv4; > break; > case CT_FTP_MODE_PASSIVE: > - *v4_addr_rep = conn_for_expectation->key.dst.addr.ipv4; > - conn_ipv4_addr = conn_for_expectation->rev_key.src.addr.ipv4; > + *v4_addr_rep = > + conn_for_expectation->key_node[CT_DIR_FWD].key.dst.addr.ipv4; > + conn_ipv4_addr = > + conn_for_expectation->key_node[CT_DIR_REV].key.src.addr.ipv4; > break; > case CT_TFTP_MODE: > default: > @@ -3306,17 +3229,20 @@ process_ftp_ctl_v6(struct conntrack *ct, > > switch (*mode) { > case CT_FTP_MODE_ACTIVE: > - *v6_addr_rep = conn_for_expectation->rev_key.dst.addr; > + *v6_addr_rep = > + conn_for_expectation->key_node[CT_DIR_REV].key.dst.addr; > /* Although most servers will block this exploit, there may be > some > * less well managed. */ > if (memcmp(&ip6_addr, &v6_addr_rep->ipv6, sizeof ip6_addr) && > - memcmp(&ip6_addr, &conn_for_expectation->key.src.addr.ipv6, > + memcmp(&ip6_addr, > + > &conn_for_expectation->key_node[CT_DIR_FWD].key.src.addr.ipv6, > sizeof ip6_addr)) { > return CT_FTP_CTL_INVALID; > } > break; > case CT_FTP_MODE_PASSIVE: > - *v6_addr_rep = conn_for_expectation->key.dst.addr; > + *v6_addr_rep = > + conn_for_expectation->key_node[CT_DIR_FWD].key.dst.addr; > break; > case CT_TFTP_MODE: > default: > @@ -3477,7 +3403,8 @@ handle_tftp_ctl(struct conntrack *ct, > long long now OVS_UNUSED, enum ftp_ctl_pkt ftp_ctl > OVS_UNUSED, > bool nat OVS_UNUSED) > { > - expectation_create(ct, conn_for_expectation->key.src.port, > + expectation_create(ct, > + > conn_for_expectation->key_node[CT_DIR_FWD].key.src.port, > conn_for_expectation, > !!(pkt->md.ct_state & CS_REPLY_DIR), false, false); > } > > -- hepeng _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
