Message ID | 1518472957-6020-1-git-send-email-yihung.wei@gmail.com |
---|---|
State | Accepted |
Headers | show |
Series | [ovs-dev] conntrack: Support conntrack flush by ct 5-tuple | expand |
Thanks Yi-hung I will try it out. Darrell On Mon, Feb 12, 2018 at 2:02 PM, Yi-Hung Wei <yihung.wei@gmail.com> wrote: > This patch adds support of flushing a conntrack entry specified by the > conntrack 5-tuple in dpif-netdev. > > Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com> > --- > Respin this patch since userspace conntrack now clears out the expectation > when a conntrack entry is deleted. > --- > lib/conntrack.c | 72 ++++++++++++++++++++++++++++++ > ++++++++++ > lib/conntrack.h | 3 ++ > lib/dpif-netdev.c | 2 +- > tests/system-kmod-macros.at | 8 ----- > tests/system-traffic.at | 1 - > tests/system-userspace-macros.at | 10 ------ > 6 files changed, 76 insertions(+), 20 deletions(-) > > diff --git a/lib/conntrack.c b/lib/conntrack.c > index fe5fd0fe8be1..c05b3901d7af 100644 > --- a/lib/conntrack.c > +++ b/lib/conntrack.c > @@ -2368,6 +2368,10 @@ delete_conn(struct conn *conn) > free(conn); > } > > +/* Convert a conntrack address 'a' into an IP address 'b' based on > 'dl_type'. > + * > + * Note that 'dl_type' should be either "ETH_TYPE_IP" or "ETH_TYPE_IPv6" > + * in network-byte order. */ > static void > ct_endpoint_to_ct_dpif_inet_addr(const struct ct_addr *a, > union ct_dpif_inet_addr *b, > @@ -2380,6 +2384,22 @@ ct_endpoint_to_ct_dpif_inet_addr(const struct > ct_addr *a, > } > } > > +/* Convert an IP address 'a' into a conntrack address 'b' based on > 'dl_type'. > + * > + * Note that 'dl_type' should be either "ETH_TYPE_IP" or "ETH_TYPE_IPv6" > + * in network-byte order. */ > +static void > +ct_dpif_inet_addr_to_ct_endpoint(const union ct_dpif_inet_addr *a, > + struct ct_addr *b, > + ovs_be16 dl_type) > +{ > + if (dl_type == htons(ETH_TYPE_IP)) { > + b->ipv4_aligned = a->ip; > + } else if (dl_type == htons(ETH_TYPE_IPV6)){ > + b->ipv6_aligned = a->in6; > + } > +} > + > static void > conn_key_to_tuple(const struct conn_key *key, struct ct_dpif_tuple *tuple) > { > @@ -2405,6 +2425,35 @@ conn_key_to_tuple(const struct conn_key *key, > struct ct_dpif_tuple *tuple) > } > > static void > +tuple_to_conn_key(const struct ct_dpif_tuple *tuple, uint16_t zone, > + struct conn_key *key) > +{ > + if (tuple->l3_type == AF_INET) { > + key->dl_type = htons(ETH_TYPE_IP); > + } else if (tuple->l3_type == AF_INET6) { > + key->dl_type = htons(ETH_TYPE_IPV6); > + } > + key->nw_proto = tuple->ip_proto; > + ct_dpif_inet_addr_to_ct_endpoint(&tuple->src, &key->src.addr, > + key->dl_type); > + ct_dpif_inet_addr_to_ct_endpoint(&tuple->dst, &key->dst.addr, > + key->dl_type); > + > + if (tuple->ip_proto == IPPROTO_ICMP || tuple->ip_proto == > IPPROTO_ICMPV6) { > + key->src.icmp_id = tuple->icmp_id; > + key->src.icmp_type = tuple->icmp_type; > + key->src.icmp_code = tuple->icmp_code; > + key->dst.icmp_id = tuple->icmp_id; > + key->dst.icmp_type = reverse_icmp_type(tuple->icmp_type); > + key->dst.icmp_code = tuple->icmp_code; > + } else { > + key->src.port = tuple->src_port; > + key->dst.port = tuple->dst_port; > + } > + key->zone = zone; > +} > + > +static void > conn_to_ct_dpif_entry(const struct conn *conn, struct ct_dpif_entry > *entry, > long long now, int bkt) > { > @@ -2517,6 +2566,29 @@ conntrack_flush(struct conntrack *ct, const > uint16_t *zone) > } > > int > +conntrack_flush_tuple(struct conntrack *ct, const struct ct_dpif_tuple > *tuple, > + uint16_t zone) > +{ > + struct conn_lookup_ctx ctx; > + int error = 0; > + > + memset(&ctx, 0, sizeof(ctx)); > + tuple_to_conn_key(tuple, zone, &ctx.key); > + ctx.hash = conn_key_hash(&ctx.key, ct->hash_basis); > + unsigned bucket = hash_to_bucket(ctx.hash); > + > + ct_lock_lock(&ct->buckets[bucket].lock); > + conn_key_lookup(&ct->buckets[bucket], &ctx, time_msec()); > + if (ctx.conn) { > + conn_clean(ct, ctx.conn, &ct->buckets[bucket]); > + } else { > + error = ENOENT; > + } > + ct_lock_unlock(&ct->buckets[bucket].lock); > + return error; > +} > + > +int > conntrack_set_maxconns(struct conntrack *ct, uint32_t maxconns) > { > atomic_store_relaxed(&ct->n_conn_limit, maxconns); > diff --git a/lib/conntrack.h b/lib/conntrack.h > index ac650304a41f..e3a5dcc8023f 100644 > --- a/lib/conntrack.h > +++ b/lib/conntrack.h > @@ -109,6 +109,7 @@ struct conntrack_dump { > }; > > struct ct_dpif_entry; > +struct ct_dpif_tuple; > > int conntrack_dump_start(struct conntrack *, struct conntrack_dump *, > const uint16_t *pzone, int *); > @@ -116,6 +117,8 @@ int conntrack_dump_next(struct conntrack_dump *, > struct ct_dpif_entry *); > int conntrack_dump_done(struct conntrack_dump *); > > int conntrack_flush(struct conntrack *, const uint16_t *zone); > +int conntrack_flush_tuple(struct conntrack *, const struct ct_dpif_tuple > *, > + uint16_t zone); > int conntrack_set_maxconns(struct conntrack *ct, uint32_t maxconns); > int conntrack_get_maxconns(struct conntrack *ct, uint32_t *maxconns); > int conntrack_get_nconns(struct conntrack *ct, uint32_t *nconns); > diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c > index ba62128c758c..b06caa281afc 100644 > --- a/lib/dpif-netdev.c > +++ b/lib/dpif-netdev.c > @@ -5842,7 +5842,7 @@ dpif_netdev_ct_flush(struct dpif *dpif, const > uint16_t *zone, > struct dp_netdev *dp = get_dp_netdev(dpif); > > if (tuple) { > - return EOPNOTSUPP; > + return conntrack_flush_tuple(&dp->conntrack, tuple, zone ? *zone > : 0); > } > return conntrack_flush(&dp->conntrack, zone); > } > diff --git a/tests/system-kmod-macros.at b/tests/system-kmod-macros.at > index 12b0adf7190e..f23a4063375c 100644 > --- a/tests/system-kmod-macros.at > +++ b/tests/system-kmod-macros.at > @@ -97,14 +97,6 @@ m4_define([CHECK_CONNTRACK_LOCAL_STACK]) > # > m4_define([CHECK_CONNTRACK_NAT]) > > -# CHECK_CT_DPIF_FLUSH_BY_CT_TUPLE() > -# > -# Perform requirements checks for running ovs-dpctl flush-conntrack by > -# conntrack 5-tuple test. The kernel datapath does support this > -# feature. Will remove this check after both kernel and userspace datapath > -# support it. > -m4_define([CHECK_CT_DPIF_FLUSH_BY_CT_TUPLE]) > - > # CHECK_CT_DPIF_SET_GET_MAXCONNS() > # > # Perform requirements checks for running ovs-dpctl ct-set-maxconns or > diff --git a/tests/system-traffic.at b/tests/system-traffic.at > index dbd56405d1fd..2afadec15827 100644 > --- a/tests/system-traffic.at > +++ b/tests/system-traffic.at > @@ -834,7 +834,6 @@ AT_CLEANUP > > AT_SETUP([conntrack - ct flush by 5-tuple]) > CHECK_CONNTRACK() > -CHECK_CT_DPIF_FLUSH_BY_CT_TUPLE() > OVS_TRAFFIC_VSWITCHD_START() > > ADD_NAMESPACES(at_ns0, at_ns1) > diff --git a/tests/system-userspace-macros.at b/tests/system-userspace- > macros.at > index 20a8635f9e39..00e1f817ff78 100644 > --- a/tests/system-userspace-macros.at > +++ b/tests/system-userspace-macros.at > @@ -100,16 +100,6 @@ m4_define([CHECK_CONNTRACK_LOCAL_STACK], > # > m4_define([CHECK_CONNTRACK_NAT]) > > -# CHECK_CT_DPIF_FLUSH_BY_CT_TUPLE() > -# > -# Perform requirements checks for running ovs-dpctl flush-conntrack by > -# conntrack 5-tuple test. The userspace datapath does not support > -# this feature yet. > -m4_define([CHECK_CT_DPIF_FLUSH_BY_CT_TUPLE], > -[ > - AT_SKIP_IF([:]) > -]) > - > # CHECK_CT_DPIF_SET_GET_MAXCONNS() > # > # Perform requirements checks for running ovs-dpctl ct-set-maxconns or > -- > 2.7.4 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev >
Nice. Acked-by: Darrell Ball <dlu998@gmail.com> On Mon, Feb 12, 2018 at 4:26 PM, Darrell Ball <dlu998@gmail.com> wrote: > Thanks Yi-hung > > I will try it out. > > Darrell > > On Mon, Feb 12, 2018 at 2:02 PM, Yi-Hung Wei <yihung.wei@gmail.com> wrote: > >> This patch adds support of flushing a conntrack entry specified by the >> conntrack 5-tuple in dpif-netdev. >> >> Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com> >> --- >> Respin this patch since userspace conntrack now clears out the expectation >> when a conntrack entry is deleted. >> --- >> lib/conntrack.c | 72 ++++++++++++++++++++++++++++++ >> ++++++++++ >> lib/conntrack.h | 3 ++ >> lib/dpif-netdev.c | 2 +- >> tests/system-kmod-macros.at | 8 ----- >> tests/system-traffic.at | 1 - >> tests/system-userspace-macros.at | 10 ------ >> 6 files changed, 76 insertions(+), 20 deletions(-) >> >> diff --git a/lib/conntrack.c b/lib/conntrack.c >> index fe5fd0fe8be1..c05b3901d7af 100644 >> --- a/lib/conntrack.c >> +++ b/lib/conntrack.c >> @@ -2368,6 +2368,10 @@ delete_conn(struct conn *conn) >> free(conn); >> } >> >> +/* Convert a conntrack address 'a' into an IP address 'b' based on >> 'dl_type'. >> + * >> + * Note that 'dl_type' should be either "ETH_TYPE_IP" or "ETH_TYPE_IPv6" >> + * in network-byte order. */ >> static void >> ct_endpoint_to_ct_dpif_inet_addr(const struct ct_addr *a, >> union ct_dpif_inet_addr *b, >> @@ -2380,6 +2384,22 @@ ct_endpoint_to_ct_dpif_inet_addr(const struct >> ct_addr *a, >> } >> } >> >> +/* Convert an IP address 'a' into a conntrack address 'b' based on >> 'dl_type'. >> + * >> + * Note that 'dl_type' should be either "ETH_TYPE_IP" or "ETH_TYPE_IPv6" >> + * in network-byte order. */ >> +static void >> +ct_dpif_inet_addr_to_ct_endpoint(const union ct_dpif_inet_addr *a, >> + struct ct_addr *b, >> + ovs_be16 dl_type) >> +{ >> + if (dl_type == htons(ETH_TYPE_IP)) { >> + b->ipv4_aligned = a->ip; >> + } else if (dl_type == htons(ETH_TYPE_IPV6)){ >> + b->ipv6_aligned = a->in6; >> + } >> +} >> + >> static void >> conn_key_to_tuple(const struct conn_key *key, struct ct_dpif_tuple >> *tuple) >> { >> @@ -2405,6 +2425,35 @@ conn_key_to_tuple(const struct conn_key *key, >> struct ct_dpif_tuple *tuple) >> } >> >> static void >> +tuple_to_conn_key(const struct ct_dpif_tuple *tuple, uint16_t zone, >> + struct conn_key *key) >> +{ >> + if (tuple->l3_type == AF_INET) { >> + key->dl_type = htons(ETH_TYPE_IP); >> + } else if (tuple->l3_type == AF_INET6) { >> + key->dl_type = htons(ETH_TYPE_IPV6); >> + } >> + key->nw_proto = tuple->ip_proto; >> + ct_dpif_inet_addr_to_ct_endpoint(&tuple->src, &key->src.addr, >> + key->dl_type); >> + ct_dpif_inet_addr_to_ct_endpoint(&tuple->dst, &key->dst.addr, >> + key->dl_type); >> + >> + if (tuple->ip_proto == IPPROTO_ICMP || tuple->ip_proto == >> IPPROTO_ICMPV6) { >> + key->src.icmp_id = tuple->icmp_id; >> + key->src.icmp_type = tuple->icmp_type; >> + key->src.icmp_code = tuple->icmp_code; >> + key->dst.icmp_id = tuple->icmp_id; >> + key->dst.icmp_type = reverse_icmp_type(tuple->icmp_type); >> + key->dst.icmp_code = tuple->icmp_code; >> + } else { >> + key->src.port = tuple->src_port; >> + key->dst.port = tuple->dst_port; >> + } >> + key->zone = zone; >> +} >> + >> +static void >> conn_to_ct_dpif_entry(const struct conn *conn, struct ct_dpif_entry >> *entry, >> long long now, int bkt) >> { >> @@ -2517,6 +2566,29 @@ conntrack_flush(struct conntrack *ct, const >> uint16_t *zone) >> } >> >> int >> +conntrack_flush_tuple(struct conntrack *ct, const struct ct_dpif_tuple >> *tuple, >> + uint16_t zone) >> +{ >> + struct conn_lookup_ctx ctx; >> + int error = 0; >> + >> + memset(&ctx, 0, sizeof(ctx)); >> + tuple_to_conn_key(tuple, zone, &ctx.key); >> + ctx.hash = conn_key_hash(&ctx.key, ct->hash_basis); >> + unsigned bucket = hash_to_bucket(ctx.hash); >> + >> + ct_lock_lock(&ct->buckets[bucket].lock); >> + conn_key_lookup(&ct->buckets[bucket], &ctx, time_msec()); >> + if (ctx.conn) { >> + conn_clean(ct, ctx.conn, &ct->buckets[bucket]); >> + } else { >> + error = ENOENT; >> + } >> + ct_lock_unlock(&ct->buckets[bucket].lock); >> + return error; >> +} >> + >> +int >> conntrack_set_maxconns(struct conntrack *ct, uint32_t maxconns) >> { >> atomic_store_relaxed(&ct->n_conn_limit, maxconns); >> diff --git a/lib/conntrack.h b/lib/conntrack.h >> index ac650304a41f..e3a5dcc8023f 100644 >> --- a/lib/conntrack.h >> +++ b/lib/conntrack.h >> @@ -109,6 +109,7 @@ struct conntrack_dump { >> }; >> >> struct ct_dpif_entry; >> +struct ct_dpif_tuple; >> >> int conntrack_dump_start(struct conntrack *, struct conntrack_dump *, >> const uint16_t *pzone, int *); >> @@ -116,6 +117,8 @@ int conntrack_dump_next(struct conntrack_dump *, >> struct ct_dpif_entry *); >> int conntrack_dump_done(struct conntrack_dump *); >> >> int conntrack_flush(struct conntrack *, const uint16_t *zone); >> +int conntrack_flush_tuple(struct conntrack *, const struct ct_dpif_tuple >> *, >> + uint16_t zone); >> int conntrack_set_maxconns(struct conntrack *ct, uint32_t maxconns); >> int conntrack_get_maxconns(struct conntrack *ct, uint32_t *maxconns); >> int conntrack_get_nconns(struct conntrack *ct, uint32_t *nconns); >> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c >> index ba62128c758c..b06caa281afc 100644 >> --- a/lib/dpif-netdev.c >> +++ b/lib/dpif-netdev.c >> @@ -5842,7 +5842,7 @@ dpif_netdev_ct_flush(struct dpif *dpif, const >> uint16_t *zone, >> struct dp_netdev *dp = get_dp_netdev(dpif); >> >> if (tuple) { >> - return EOPNOTSUPP; >> + return conntrack_flush_tuple(&dp->conntrack, tuple, zone ? >> *zone : 0); >> } >> return conntrack_flush(&dp->conntrack, zone); >> } >> diff --git a/tests/system-kmod-macros.at b/tests/system-kmod-macros.at >> index 12b0adf7190e..f23a4063375c 100644 >> --- a/tests/system-kmod-macros.at >> +++ b/tests/system-kmod-macros.at >> @@ -97,14 +97,6 @@ m4_define([CHECK_CONNTRACK_LOCAL_STACK]) >> # >> m4_define([CHECK_CONNTRACK_NAT]) >> >> -# CHECK_CT_DPIF_FLUSH_BY_CT_TUPLE() >> -# >> -# Perform requirements checks for running ovs-dpctl flush-conntrack by >> -# conntrack 5-tuple test. The kernel datapath does support this >> -# feature. Will remove this check after both kernel and userspace >> datapath >> -# support it. >> -m4_define([CHECK_CT_DPIF_FLUSH_BY_CT_TUPLE]) >> - >> # CHECK_CT_DPIF_SET_GET_MAXCONNS() >> # >> # Perform requirements checks for running ovs-dpctl ct-set-maxconns or >> diff --git a/tests/system-traffic.at b/tests/system-traffic.at >> index dbd56405d1fd..2afadec15827 100644 >> --- a/tests/system-traffic.at >> +++ b/tests/system-traffic.at >> @@ -834,7 +834,6 @@ AT_CLEANUP >> >> AT_SETUP([conntrack - ct flush by 5-tuple]) >> CHECK_CONNTRACK() >> -CHECK_CT_DPIF_FLUSH_BY_CT_TUPLE() >> OVS_TRAFFIC_VSWITCHD_START() >> >> ADD_NAMESPACES(at_ns0, at_ns1) >> diff --git a/tests/system-userspace-macros.at b/tests/ >> system-userspace-macros.at >> index 20a8635f9e39..00e1f817ff78 100644 >> --- a/tests/system-userspace-macros.at >> +++ b/tests/system-userspace-macros.at >> @@ -100,16 +100,6 @@ m4_define([CHECK_CONNTRACK_LOCAL_STACK], >> # >> m4_define([CHECK_CONNTRACK_NAT]) >> >> -# CHECK_CT_DPIF_FLUSH_BY_CT_TUPLE() >> -# >> -# Perform requirements checks for running ovs-dpctl flush-conntrack by >> -# conntrack 5-tuple test. The userspace datapath does not support >> -# this feature yet. >> -m4_define([CHECK_CT_DPIF_FLUSH_BY_CT_TUPLE], >> -[ >> - AT_SKIP_IF([:]) >> -]) >> - >> # CHECK_CT_DPIF_SET_GET_MAXCONNS() >> # >> # Perform requirements checks for running ovs-dpctl ct-set-maxconns or >> -- >> 2.7.4 >> >> _______________________________________________ >> dev mailing list >> dev@openvswitch.org >> https://mail.openvswitch.org/mailman/listinfo/ovs-dev >> > >
Thanks Yi-Hung and Darrell. I applied this to master. On Mon, Feb 12, 2018 at 05:12:24PM -0800, Darrell Ball wrote: > Nice. > > Acked-by: Darrell Ball <dlu998@gmail.com> > > On Mon, Feb 12, 2018 at 4:26 PM, Darrell Ball <dlu998@gmail.com> wrote: > > > Thanks Yi-hung > > > > I will try it out. > > > > Darrell > > > > On Mon, Feb 12, 2018 at 2:02 PM, Yi-Hung Wei <yihung.wei@gmail.com> wrote: > > > >> This patch adds support of flushing a conntrack entry specified by the > >> conntrack 5-tuple in dpif-netdev. > >> > >> Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com> > >> --- > >> Respin this patch since userspace conntrack now clears out the expectation > >> when a conntrack entry is deleted. > >> --- > >> lib/conntrack.c | 72 ++++++++++++++++++++++++++++++ > >> ++++++++++ > >> lib/conntrack.h | 3 ++ > >> lib/dpif-netdev.c | 2 +- > >> tests/system-kmod-macros.at | 8 ----- > >> tests/system-traffic.at | 1 - > >> tests/system-userspace-macros.at | 10 ------ > >> 6 files changed, 76 insertions(+), 20 deletions(-) > >> > >> diff --git a/lib/conntrack.c b/lib/conntrack.c > >> index fe5fd0fe8be1..c05b3901d7af 100644 > >> --- a/lib/conntrack.c > >> +++ b/lib/conntrack.c > >> @@ -2368,6 +2368,10 @@ delete_conn(struct conn *conn) > >> free(conn); > >> } > >> > >> +/* Convert a conntrack address 'a' into an IP address 'b' based on > >> 'dl_type'. > >> + * > >> + * Note that 'dl_type' should be either "ETH_TYPE_IP" or "ETH_TYPE_IPv6" > >> + * in network-byte order. */ > >> static void > >> ct_endpoint_to_ct_dpif_inet_addr(const struct ct_addr *a, > >> union ct_dpif_inet_addr *b, > >> @@ -2380,6 +2384,22 @@ ct_endpoint_to_ct_dpif_inet_addr(const struct > >> ct_addr *a, > >> } > >> } > >> > >> +/* Convert an IP address 'a' into a conntrack address 'b' based on > >> 'dl_type'. > >> + * > >> + * Note that 'dl_type' should be either "ETH_TYPE_IP" or "ETH_TYPE_IPv6" > >> + * in network-byte order. */ > >> +static void > >> +ct_dpif_inet_addr_to_ct_endpoint(const union ct_dpif_inet_addr *a, > >> + struct ct_addr *b, > >> + ovs_be16 dl_type) > >> +{ > >> + if (dl_type == htons(ETH_TYPE_IP)) { > >> + b->ipv4_aligned = a->ip; > >> + } else if (dl_type == htons(ETH_TYPE_IPV6)){ > >> + b->ipv6_aligned = a->in6; > >> + } > >> +} > >> + > >> static void > >> conn_key_to_tuple(const struct conn_key *key, struct ct_dpif_tuple > >> *tuple) > >> { > >> @@ -2405,6 +2425,35 @@ conn_key_to_tuple(const struct conn_key *key, > >> struct ct_dpif_tuple *tuple) > >> } > >> > >> static void > >> +tuple_to_conn_key(const struct ct_dpif_tuple *tuple, uint16_t zone, > >> + struct conn_key *key) > >> +{ > >> + if (tuple->l3_type == AF_INET) { > >> + key->dl_type = htons(ETH_TYPE_IP); > >> + } else if (tuple->l3_type == AF_INET6) { > >> + key->dl_type = htons(ETH_TYPE_IPV6); > >> + } > >> + key->nw_proto = tuple->ip_proto; > >> + ct_dpif_inet_addr_to_ct_endpoint(&tuple->src, &key->src.addr, > >> + key->dl_type); > >> + ct_dpif_inet_addr_to_ct_endpoint(&tuple->dst, &key->dst.addr, > >> + key->dl_type); > >> + > >> + if (tuple->ip_proto == IPPROTO_ICMP || tuple->ip_proto == > >> IPPROTO_ICMPV6) { > >> + key->src.icmp_id = tuple->icmp_id; > >> + key->src.icmp_type = tuple->icmp_type; > >> + key->src.icmp_code = tuple->icmp_code; > >> + key->dst.icmp_id = tuple->icmp_id; > >> + key->dst.icmp_type = reverse_icmp_type(tuple->icmp_type); > >> + key->dst.icmp_code = tuple->icmp_code; > >> + } else { > >> + key->src.port = tuple->src_port; > >> + key->dst.port = tuple->dst_port; > >> + } > >> + key->zone = zone; > >> +} > >> + > >> +static void > >> conn_to_ct_dpif_entry(const struct conn *conn, struct ct_dpif_entry > >> *entry, > >> long long now, int bkt) > >> { > >> @@ -2517,6 +2566,29 @@ conntrack_flush(struct conntrack *ct, const > >> uint16_t *zone) > >> } > >> > >> int > >> +conntrack_flush_tuple(struct conntrack *ct, const struct ct_dpif_tuple > >> *tuple, > >> + uint16_t zone) > >> +{ > >> + struct conn_lookup_ctx ctx; > >> + int error = 0; > >> + > >> + memset(&ctx, 0, sizeof(ctx)); > >> + tuple_to_conn_key(tuple, zone, &ctx.key); > >> + ctx.hash = conn_key_hash(&ctx.key, ct->hash_basis); > >> + unsigned bucket = hash_to_bucket(ctx.hash); > >> + > >> + ct_lock_lock(&ct->buckets[bucket].lock); > >> + conn_key_lookup(&ct->buckets[bucket], &ctx, time_msec()); > >> + if (ctx.conn) { > >> + conn_clean(ct, ctx.conn, &ct->buckets[bucket]); > >> + } else { > >> + error = ENOENT; > >> + } > >> + ct_lock_unlock(&ct->buckets[bucket].lock); > >> + return error; > >> +} > >> + > >> +int > >> conntrack_set_maxconns(struct conntrack *ct, uint32_t maxconns) > >> { > >> atomic_store_relaxed(&ct->n_conn_limit, maxconns); > >> diff --git a/lib/conntrack.h b/lib/conntrack.h > >> index ac650304a41f..e3a5dcc8023f 100644 > >> --- a/lib/conntrack.h > >> +++ b/lib/conntrack.h > >> @@ -109,6 +109,7 @@ struct conntrack_dump { > >> }; > >> > >> struct ct_dpif_entry; > >> +struct ct_dpif_tuple; > >> > >> int conntrack_dump_start(struct conntrack *, struct conntrack_dump *, > >> const uint16_t *pzone, int *); > >> @@ -116,6 +117,8 @@ int conntrack_dump_next(struct conntrack_dump *, > >> struct ct_dpif_entry *); > >> int conntrack_dump_done(struct conntrack_dump *); > >> > >> int conntrack_flush(struct conntrack *, const uint16_t *zone); > >> +int conntrack_flush_tuple(struct conntrack *, const struct ct_dpif_tuple > >> *, > >> + uint16_t zone); > >> int conntrack_set_maxconns(struct conntrack *ct, uint32_t maxconns); > >> int conntrack_get_maxconns(struct conntrack *ct, uint32_t *maxconns); > >> int conntrack_get_nconns(struct conntrack *ct, uint32_t *nconns); > >> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c > >> index ba62128c758c..b06caa281afc 100644 > >> --- a/lib/dpif-netdev.c > >> +++ b/lib/dpif-netdev.c > >> @@ -5842,7 +5842,7 @@ dpif_netdev_ct_flush(struct dpif *dpif, const > >> uint16_t *zone, > >> struct dp_netdev *dp = get_dp_netdev(dpif); > >> > >> if (tuple) { > >> - return EOPNOTSUPP; > >> + return conntrack_flush_tuple(&dp->conntrack, tuple, zone ? > >> *zone : 0); > >> } > >> return conntrack_flush(&dp->conntrack, zone); > >> } > >> diff --git a/tests/system-kmod-macros.at b/tests/system-kmod-macros.at > >> index 12b0adf7190e..f23a4063375c 100644 > >> --- a/tests/system-kmod-macros.at > >> +++ b/tests/system-kmod-macros.at > >> @@ -97,14 +97,6 @@ m4_define([CHECK_CONNTRACK_LOCAL_STACK]) > >> # > >> m4_define([CHECK_CONNTRACK_NAT]) > >> > >> -# CHECK_CT_DPIF_FLUSH_BY_CT_TUPLE() > >> -# > >> -# Perform requirements checks for running ovs-dpctl flush-conntrack by > >> -# conntrack 5-tuple test. The kernel datapath does support this > >> -# feature. Will remove this check after both kernel and userspace > >> datapath > >> -# support it. > >> -m4_define([CHECK_CT_DPIF_FLUSH_BY_CT_TUPLE]) > >> - > >> # CHECK_CT_DPIF_SET_GET_MAXCONNS() > >> # > >> # Perform requirements checks for running ovs-dpctl ct-set-maxconns or > >> diff --git a/tests/system-traffic.at b/tests/system-traffic.at > >> index dbd56405d1fd..2afadec15827 100644 > >> --- a/tests/system-traffic.at > >> +++ b/tests/system-traffic.at > >> @@ -834,7 +834,6 @@ AT_CLEANUP > >> > >> AT_SETUP([conntrack - ct flush by 5-tuple]) > >> CHECK_CONNTRACK() > >> -CHECK_CT_DPIF_FLUSH_BY_CT_TUPLE() > >> OVS_TRAFFIC_VSWITCHD_START() > >> > >> ADD_NAMESPACES(at_ns0, at_ns1) > >> diff --git a/tests/system-userspace-macros.at b/tests/ > >> system-userspace-macros.at > >> index 20a8635f9e39..00e1f817ff78 100644 > >> --- a/tests/system-userspace-macros.at > >> +++ b/tests/system-userspace-macros.at > >> @@ -100,16 +100,6 @@ m4_define([CHECK_CONNTRACK_LOCAL_STACK], > >> # > >> m4_define([CHECK_CONNTRACK_NAT]) > >> > >> -# CHECK_CT_DPIF_FLUSH_BY_CT_TUPLE() > >> -# > >> -# Perform requirements checks for running ovs-dpctl flush-conntrack by > >> -# conntrack 5-tuple test. The userspace datapath does not support > >> -# this feature yet. > >> -m4_define([CHECK_CT_DPIF_FLUSH_BY_CT_TUPLE], > >> -[ > >> - AT_SKIP_IF([:]) > >> -]) > >> - > >> # CHECK_CT_DPIF_SET_GET_MAXCONNS() > >> # > >> # Perform requirements checks for running ovs-dpctl ct-set-maxconns or > >> -- > >> 2.7.4 > >> > >> _______________________________________________ > >> dev mailing list > >> dev@openvswitch.org > >> https://mail.openvswitch.org/mailman/listinfo/ovs-dev > >> > > > > > _______________________________________________ > dev mailing list > dev@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
diff --git a/lib/conntrack.c b/lib/conntrack.c index fe5fd0fe8be1..c05b3901d7af 100644 --- a/lib/conntrack.c +++ b/lib/conntrack.c @@ -2368,6 +2368,10 @@ delete_conn(struct conn *conn) free(conn); } +/* Convert a conntrack address 'a' into an IP address 'b' based on 'dl_type'. + * + * Note that 'dl_type' should be either "ETH_TYPE_IP" or "ETH_TYPE_IPv6" + * in network-byte order. */ static void ct_endpoint_to_ct_dpif_inet_addr(const struct ct_addr *a, union ct_dpif_inet_addr *b, @@ -2380,6 +2384,22 @@ ct_endpoint_to_ct_dpif_inet_addr(const struct ct_addr *a, } } +/* Convert an IP address 'a' into a conntrack address 'b' based on 'dl_type'. + * + * Note that 'dl_type' should be either "ETH_TYPE_IP" or "ETH_TYPE_IPv6" + * in network-byte order. */ +static void +ct_dpif_inet_addr_to_ct_endpoint(const union ct_dpif_inet_addr *a, + struct ct_addr *b, + ovs_be16 dl_type) +{ + if (dl_type == htons(ETH_TYPE_IP)) { + b->ipv4_aligned = a->ip; + } else if (dl_type == htons(ETH_TYPE_IPV6)){ + b->ipv6_aligned = a->in6; + } +} + static void conn_key_to_tuple(const struct conn_key *key, struct ct_dpif_tuple *tuple) { @@ -2405,6 +2425,35 @@ conn_key_to_tuple(const struct conn_key *key, struct ct_dpif_tuple *tuple) } static void +tuple_to_conn_key(const struct ct_dpif_tuple *tuple, uint16_t zone, + struct conn_key *key) +{ + if (tuple->l3_type == AF_INET) { + key->dl_type = htons(ETH_TYPE_IP); + } else if (tuple->l3_type == AF_INET6) { + key->dl_type = htons(ETH_TYPE_IPV6); + } + key->nw_proto = tuple->ip_proto; + ct_dpif_inet_addr_to_ct_endpoint(&tuple->src, &key->src.addr, + key->dl_type); + ct_dpif_inet_addr_to_ct_endpoint(&tuple->dst, &key->dst.addr, + key->dl_type); + + if (tuple->ip_proto == IPPROTO_ICMP || tuple->ip_proto == IPPROTO_ICMPV6) { + key->src.icmp_id = tuple->icmp_id; + key->src.icmp_type = tuple->icmp_type; + key->src.icmp_code = tuple->icmp_code; + key->dst.icmp_id = tuple->icmp_id; + key->dst.icmp_type = reverse_icmp_type(tuple->icmp_type); + key->dst.icmp_code = tuple->icmp_code; + } else { + key->src.port = tuple->src_port; + key->dst.port = tuple->dst_port; + } + key->zone = zone; +} + +static void conn_to_ct_dpif_entry(const struct conn *conn, struct ct_dpif_entry *entry, long long now, int bkt) { @@ -2517,6 +2566,29 @@ conntrack_flush(struct conntrack *ct, const uint16_t *zone) } int +conntrack_flush_tuple(struct conntrack *ct, const struct ct_dpif_tuple *tuple, + uint16_t zone) +{ + struct conn_lookup_ctx ctx; + int error = 0; + + memset(&ctx, 0, sizeof(ctx)); + tuple_to_conn_key(tuple, zone, &ctx.key); + ctx.hash = conn_key_hash(&ctx.key, ct->hash_basis); + unsigned bucket = hash_to_bucket(ctx.hash); + + ct_lock_lock(&ct->buckets[bucket].lock); + conn_key_lookup(&ct->buckets[bucket], &ctx, time_msec()); + if (ctx.conn) { + conn_clean(ct, ctx.conn, &ct->buckets[bucket]); + } else { + error = ENOENT; + } + ct_lock_unlock(&ct->buckets[bucket].lock); + return error; +} + +int conntrack_set_maxconns(struct conntrack *ct, uint32_t maxconns) { atomic_store_relaxed(&ct->n_conn_limit, maxconns); diff --git a/lib/conntrack.h b/lib/conntrack.h index ac650304a41f..e3a5dcc8023f 100644 --- a/lib/conntrack.h +++ b/lib/conntrack.h @@ -109,6 +109,7 @@ struct conntrack_dump { }; struct ct_dpif_entry; +struct ct_dpif_tuple; int conntrack_dump_start(struct conntrack *, struct conntrack_dump *, const uint16_t *pzone, int *); @@ -116,6 +117,8 @@ int conntrack_dump_next(struct conntrack_dump *, struct ct_dpif_entry *); int conntrack_dump_done(struct conntrack_dump *); int conntrack_flush(struct conntrack *, const uint16_t *zone); +int conntrack_flush_tuple(struct conntrack *, const struct ct_dpif_tuple *, + uint16_t zone); int conntrack_set_maxconns(struct conntrack *ct, uint32_t maxconns); int conntrack_get_maxconns(struct conntrack *ct, uint32_t *maxconns); int conntrack_get_nconns(struct conntrack *ct, uint32_t *nconns); diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index ba62128c758c..b06caa281afc 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -5842,7 +5842,7 @@ dpif_netdev_ct_flush(struct dpif *dpif, const uint16_t *zone, struct dp_netdev *dp = get_dp_netdev(dpif); if (tuple) { - return EOPNOTSUPP; + return conntrack_flush_tuple(&dp->conntrack, tuple, zone ? *zone : 0); } return conntrack_flush(&dp->conntrack, zone); } diff --git a/tests/system-kmod-macros.at b/tests/system-kmod-macros.at index 12b0adf7190e..f23a4063375c 100644 --- a/tests/system-kmod-macros.at +++ b/tests/system-kmod-macros.at @@ -97,14 +97,6 @@ m4_define([CHECK_CONNTRACK_LOCAL_STACK]) # m4_define([CHECK_CONNTRACK_NAT]) -# CHECK_CT_DPIF_FLUSH_BY_CT_TUPLE() -# -# Perform requirements checks for running ovs-dpctl flush-conntrack by -# conntrack 5-tuple test. The kernel datapath does support this -# feature. Will remove this check after both kernel and userspace datapath -# support it. -m4_define([CHECK_CT_DPIF_FLUSH_BY_CT_TUPLE]) - # CHECK_CT_DPIF_SET_GET_MAXCONNS() # # Perform requirements checks for running ovs-dpctl ct-set-maxconns or diff --git a/tests/system-traffic.at b/tests/system-traffic.at index dbd56405d1fd..2afadec15827 100644 --- a/tests/system-traffic.at +++ b/tests/system-traffic.at @@ -834,7 +834,6 @@ AT_CLEANUP AT_SETUP([conntrack - ct flush by 5-tuple]) CHECK_CONNTRACK() -CHECK_CT_DPIF_FLUSH_BY_CT_TUPLE() OVS_TRAFFIC_VSWITCHD_START() ADD_NAMESPACES(at_ns0, at_ns1) diff --git a/tests/system-userspace-macros.at b/tests/system-userspace-macros.at index 20a8635f9e39..00e1f817ff78 100644 --- a/tests/system-userspace-macros.at +++ b/tests/system-userspace-macros.at @@ -100,16 +100,6 @@ m4_define([CHECK_CONNTRACK_LOCAL_STACK], # m4_define([CHECK_CONNTRACK_NAT]) -# CHECK_CT_DPIF_FLUSH_BY_CT_TUPLE() -# -# Perform requirements checks for running ovs-dpctl flush-conntrack by -# conntrack 5-tuple test. The userspace datapath does not support -# this feature yet. -m4_define([CHECK_CT_DPIF_FLUSH_BY_CT_TUPLE], -[ - AT_SKIP_IF([:]) -]) - # CHECK_CT_DPIF_SET_GET_MAXCONNS() # # Perform requirements checks for running ovs-dpctl ct-set-maxconns or
This patch adds support of flushing a conntrack entry specified by the conntrack 5-tuple in dpif-netdev. Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com> --- Respin this patch since userspace conntrack now clears out the expectation when a conntrack entry is deleted. --- lib/conntrack.c | 72 ++++++++++++++++++++++++++++++++++++++++ lib/conntrack.h | 3 ++ lib/dpif-netdev.c | 2 +- tests/system-kmod-macros.at | 8 ----- tests/system-traffic.at | 1 - tests/system-userspace-macros.at | 10 ------ 6 files changed, 76 insertions(+), 20 deletions(-)