On Fri, Dec 16, 2022 at 1:01 PM Paolo Valerio <[email protected]> wrote:
> Ales Musil <[email protected]> writes: > > > Add extension that allows to flush connections from CT > > by specifying fields that the connections should be > > matched against. This allows to match only some fields > > of the connection e.g. source address for orig direrction. > > > > Reported-at: https://bugzilla.redhat.com/2120546 > > Signed-off-by: Ales Musil <[email protected]> > > --- > > v4: Allow ovs-ofctl flush/conntrack without any zone/tuple. > > v3: Rebase on top of master. > > v2: Rebase on top of master. > > Use suggestion from Ilya. > > --- > > NEWS | 3 + > > include/openflow/nicira-ext.h | 30 +++++++ > > include/openvswitch/ofp-msgs.h | 4 + > > include/openvswitch/ofp-util.h | 4 + > > lib/ofp-bundle.c | 1 + > > lib/ofp-ct-util.c | 146 +++++++++++++++++++++++++++++++++ > > lib/ofp-ct-util.h | 9 ++ > > lib/ofp-print.c | 20 +++++ > > lib/ofp-util.c | 25 ++++++ > > lib/rconn.c | 1 + > > ofproto/ofproto-dpif.c | 8 +- > > ofproto/ofproto-provider.h | 7 +- > > ofproto/ofproto.c | 30 ++++++- > > tests/ofp-print.at | 93 +++++++++++++++++++++ > > tests/ovs-ofctl.at | 26 ++++++ > > tests/system-traffic.at | 116 ++++++++++++++------------ > > utilities/ovs-ofctl.c | 38 +++++++++ > > 17 files changed, 503 insertions(+), 58 deletions(-) > > > > diff --git a/NEWS b/NEWS > > index ff8904b02..46b8faa41 100644 > > --- a/NEWS > > +++ b/NEWS > > @@ -16,6 +16,9 @@ Post-v3.0.0 > > by specifying 'max-rate' or '[r]stp-path-cost' accordingly. > > - ovs-dpctl and related ovs-appctl commands: > > * "flush-conntrack" is capable of handling partial 5-tuple. > > + - OpenFlow: > > + * New OpenFlow extension NXT_CT_FLUSH to flush connections > matching > > + the specified fields. > > > > I guess we miss an entry for ovs-ofctl flush-conntrack > > > > > v3.0.0 - 15 Aug 2022 > > diff --git a/include/openflow/nicira-ext.h > b/include/openflow/nicira-ext.h > > index b68804991..32ce56d31 100644 > > --- a/include/openflow/nicira-ext.h > > +++ b/include/openflow/nicira-ext.h > > @@ -1064,4 +1064,34 @@ struct nx_zone_id { > > }; > > OFP_ASSERT(sizeof(struct nx_zone_id) == 8); > > > > +/* CT flush available TLVs. */ > > +enum nx_ct_flush_tlv_type { > > + /* Outer types. */ > > + NXT_CT_ORIG_DIRECTION, /* CT orig direction outer type. */ > > + NXT_CT_REPLY_DIRECTION, /* CT reply direction outer type. */ > > + > > + /* Nested types. */ > > + NXT_CT_SRC, /* CT source IPv6 or mapped IPv4 address. > */ > > + NXT_CT_DST, /* CT destination IPv6 or mapped IPv4 > address. */ > > + NXT_CT_SRC_PORT, /* CT source port. */ > > + NXT_CT_DST_PORT, /* CT destination port. */ > > + NXT_CT_ICMP_ID, /* CT ICMP id. */ > > + NXT_CT_ICMP_TYPE, /* CT ICMP type. */ > > + NXT_CT_ICMP_CODE, /* CT ICMP code. */ > > + > > + /* Primitive types. */ > > + NXT_CT_ZONE_ID, /* CT zone id. */ > > +}; > > + > > +/* NXT_CT_FLUSH. > > + * > > + * Flushes the connection tracking specified by 5-tuple. > > + * The struct should be followed by TLVs specifying the matching > parameters. */ > > +struct nx_ct_flush { > > + uint8_t ip_proto; /* IP protocol. */ > > + uint8_t family; /* L3 address family. */ > > + uint8_t zero[6]; /* Must be zero. */ > > +}; > > +OFP_ASSERT(sizeof(struct nx_ct_flush) == 8); > > + > > #endif /* openflow/nicira-ext.h */ > > diff --git a/include/openvswitch/ofp-msgs.h > b/include/openvswitch/ofp-msgs.h > > index 921a937e5..659b0a3e7 100644 > > --- a/include/openvswitch/ofp-msgs.h > > +++ b/include/openvswitch/ofp-msgs.h > > @@ -526,6 +526,9 @@ enum ofpraw { > > > > /* NXST 1.0+ (4): struct nx_ipfix_stats_reply[]. */ > > OFPRAW_NXST_IPFIX_FLOW_REPLY, > > + > > + /* NXT 1.0+ (32): struct nx_ct_flush, uint8_t[8][]. */ > > + OFPRAW_NXT_CT_FLUSH, > > }; > > > > /* Decoding messages into OFPRAW_* values. */ > > @@ -772,6 +775,7 @@ enum ofptype { > > OFPTYPE_IPFIX_FLOW_STATS_REQUEST, /* OFPRAW_NXST_IPFIX_FLOW_REQUEST > */ > > OFPTYPE_IPFIX_FLOW_STATS_REPLY, /* OFPRAW_NXST_IPFIX_FLOW_REPLY */ > > OFPTYPE_CT_FLUSH_ZONE, /* OFPRAW_NXT_CT_FLUSH_ZONE. */ > > + OFPTYPE_CT_FLUSH, /* OFPRAW_NXT_CT_FLUSH. */ > > > > /* Flow monitor extension. */ > > OFPTYPE_FLOW_MONITOR_CANCEL, /* OFPRAW_NXT_FLOW_MONITOR_CANCEL. > > diff --git a/include/openvswitch/ofp-util.h > b/include/openvswitch/ofp-util.h > > index 84937ae26..e10d90b9f 100644 > > --- a/include/openvswitch/ofp-util.h > > +++ b/include/openvswitch/ofp-util.h > > @@ -65,6 +65,10 @@ struct ofpbuf *ofputil_encode_echo_reply(const struct > ofp_header *); > > > > struct ofpbuf *ofputil_encode_barrier_request(enum ofp_version); > > > > +struct ofpbuf *ofputil_ct_match_encode(const struct ofputil_ct_match > *match, > > + uint16_t *zone_id, > > + enum ofp_version version); > > + > > #ifdef __cplusplus > > } > > #endif > > diff --git a/lib/ofp-bundle.c b/lib/ofp-bundle.c > > index 0161c2bc6..941a8370e 100644 > > --- a/lib/ofp-bundle.c > > +++ b/lib/ofp-bundle.c > > @@ -292,6 +292,7 @@ ofputil_is_bundlable(enum ofptype type) > > case OFPTYPE_IPFIX_FLOW_STATS_REQUEST: > > case OFPTYPE_IPFIX_FLOW_STATS_REPLY: > > case OFPTYPE_CT_FLUSH_ZONE: > > + case OFPTYPE_CT_FLUSH: > > break; > > } > > > > diff --git a/lib/ofp-ct-util.c b/lib/ofp-ct-util.c > > index a10607590..a46798582 100644 > > --- a/lib/ofp-ct-util.c > > +++ b/lib/ofp-ct-util.c > > @@ -23,8 +23,12 @@ > > > > #include "ct-dpif.h" > > #include "ofp-ct-util.h" > > +#include "openflow/nicira-ext.h" > > #include "openvswitch/dynamic-string.h" > > +#include "openvswitch/ofp-msgs.h" > > #include "openvswitch/ofp-parse.h" > > +#include "openvswitch/ofp-errors.h" > > +#include "openvswitch/ofp-prop.h" > > #include "openvswitch/ofp-util.h" > > #include "openvswitch/packets.h" > > > > @@ -324,3 +328,145 @@ error: > > free(copy); > > return false; > > } > > + > > +static enum ofperr > > +ofpprop_pull_value(struct ofpbuf *property, void *value, size_t len) > > +{ > > + if (ofpbuf_msgsize(property) < len) { > > + return OFPERR_OFPBPC_BAD_LEN; > > + } > > + > > + memcpy(value, property->msg, len); > > + > > + return 0; > > +} > > + > > +static enum ofperr > > +ofputil_ct_tuple_decode_nested(struct ofpbuf *property, > > + struct ofputil_ct_tuple *tuple) > > +{ > > + struct ofpbuf nested; > > + enum ofperr error = ofpprop_parse_nested(property, &nested); > > + if (error) { > > + return error; > > + } > > + > > + while (nested.size) { > > + struct ofpbuf inner; > > + uint64_t type; > > + > > + error = ofpprop_pull(&nested, &inner, &type); > > + if (error) { > > + return error; > > + } > > + switch (type) { > > + case NXT_CT_SRC: > > + ofpprop_pull_value(&inner, &tuple->src, sizeof > tuple->src); > > + break; > > + case NXT_CT_DST: > > + ofpprop_pull_value(&inner, &tuple->dst, sizeof > tuple->dst); > > + break; > > + case NXT_CT_SRC_PORT: > > + ofpprop_parse_be16(&inner, &tuple->src_port); > > + break; > > + case NXT_CT_DST_PORT: > > + ofpprop_parse_be16(&inner, &tuple->dst_port); > > + break; > > + case NXT_CT_ICMP_ID: > > + ofpprop_parse_be16(&inner, &tuple->icmp_id); > > + break; > > + case NXT_CT_ICMP_TYPE: > > + ofpprop_parse_u8(&inner, &tuple->icmp_type); > > + break; > > + case NXT_CT_ICMP_CODE: > > + ofpprop_parse_u8(&inner, &tuple->icmp_code); > > + } > > + } > > + > > + return 0; > > +} > > + > > +enum ofperr > > +ofputil_ct_match_decode(struct ofputil_ct_match *match, bool *with_zone, > > + uint16_t *zone_id, const struct ofp_header *oh) > > +{ > > + struct ofpbuf msg = ofpbuf_const_initializer(oh, ntohs(oh->length)); > > + ofpraw_pull_assert(&msg); > > + > > + const struct nx_ct_flush *nx_flush = ofpbuf_pull(&msg, sizeof > *nx_flush); > > + > > + if (!is_all_zeros(nx_flush->zero, sizeof nx_flush->zero)) { > > + return OFPERR_NXBRC_MUST_BE_ZERO; > > + } > > + > > + match->l3_type = nx_flush->family; > > + match->ip_proto = nx_flush->ip_proto; > > + > > + struct ofputil_ct_tuple *orig = &match->tuple_orig; > > + struct ofputil_ct_tuple *reply = &match->tuple_reply; > > + > > + while (msg.size) { > > + struct ofpbuf property; > > + uint64_t type; > > + > > + enum ofperr error = ofpprop_pull(&msg, &property, &type); > > + if (error) { > > + return error; > > + } > > + > > + switch (type) { > > + case NXT_CT_ORIG_DIRECTION: > > + ofputil_ct_tuple_decode_nested(&property, orig); > > + break; > > + case NXT_CT_REPLY_DIRECTION: > > + ofputil_ct_tuple_decode_nested(&property, reply); > > + break; > > + case NXT_CT_ZONE_ID: > > + if (with_zone) { > > + *with_zone = true; > > + } > > + ofpprop_parse_u16(&property, zone_id); > > + break; > > + } > > + } > > + > > + return 0; > > +} > > + > > +void > > +ofputil_ct_tuple_encode(const struct ofputil_ct_tuple *tuple, > > + struct ofpbuf *buf, enum nx_ct_flush_tlv_type > type, > > + uint8_t ip_proto) > > +{ > > + /* 128 B is enough to hold the whole tuple. */ > > + uint8_t stub[128]; > > + struct ofpbuf nested = OFPBUF_STUB_INITIALIZER(stub); > > + > > + if (!ipv6_is_zero(&tuple->src)) { > > + ofpprop_put(&nested, NXT_CT_SRC, &tuple->src, sizeof > tuple->src); > > + } > > + > > + if (!ipv6_is_zero(&tuple->dst)) { > > + ofpprop_put(&nested, NXT_CT_DST, &tuple->dst, sizeof > tuple->dst); > > + } > > + > > + if (ip_proto == IPPROTO_ICMP || ip_proto == IPPROTO_ICMPV6) { > > + ofpprop_put_be16(&nested, NXT_CT_ICMP_ID, tuple->icmp_id); > > + ofpprop_put_u8(&nested, NXT_CT_ICMP_TYPE, tuple->icmp_type); > > + ofpprop_put_u8(&nested, NXT_CT_ICMP_CODE, tuple->icmp_code); > > + } else { > > + if (tuple->src_port) { > > + ofpprop_put_be16(&nested, NXT_CT_SRC_PORT, tuple->src_port); > > + } > > + > > + if (tuple->dst_port) { > > + ofpprop_put_be16(&nested, NXT_CT_DST_PORT, tuple->dst_port); > > + } > > + } > > + > > + if (nested.size) { > > + ofpprop_put_nested(buf, type, &nested); > > + } > > + > > + ofpbuf_uninit(&nested); > > +} > > diff --git a/lib/ofp-ct-util.h b/lib/ofp-ct-util.h > > index 5a5eaf920..f4e4f812e 100644 > > --- a/lib/ofp-ct-util.h > > +++ b/lib/ofp-ct-util.h > > @@ -17,6 +17,7 @@ > > #define OVS_OFP_CT_UTIL_H > > > > #include "ct-dpif.h" > > +#include "openflow/nicira-ext.h" > > #include "openvswitch/ofp-util.h" > > > > bool ofputil_ct_match_cmp(const struct ofputil_ct_match *match, > > @@ -33,4 +34,12 @@ bool ofputil_ct_match_parse(struct ofputil_ct_match > *match, const char *s, > > > > bool ofputil_is_ct_match_zero(const struct ofputil_ct_match *match); > > > > +enum ofperr ofputil_ct_match_decode(struct ofputil_ct_match *match, > > + bool *with_zone, uint16_t *zone_id, > > + const struct ofp_header *oh); > > + > > +void ofputil_ct_tuple_encode(const struct ofputil_ct_tuple *tuple, > > + struct ofpbuf *buf, > > + enum nx_ct_flush_tlv_type type, uint8_t > ip_proto); > > + > > #endif /* lib/ofp-ct-util.h */ > > diff --git a/lib/ofp-print.c b/lib/ofp-print.c > > index bd37fa17a..94bfa7070 100644 > > --- a/lib/ofp-print.c > > +++ b/lib/ofp-print.c > > @@ -36,6 +36,7 @@ > > #include "learn.h" > > #include "multipath.h" > > #include "netdev.h" > > +#include "ofp-ct-util.h" > > #include "nx-match.h" > > #include "odp-util.h" > > #include "openflow/nicira-ext.h" > > @@ -949,6 +950,23 @@ ofp_print_nxt_ct_flush_zone(struct ds *string, > const struct nx_zone_id *nzi) > > return 0; > > } > > > > +static enum ofperr > > +ofp_print_nxt_ct_flush(struct ds *string, const struct ofp_header *oh) > > +{ > > + uint16_t zone_id = 0; > > + struct ofputil_ct_match match = {0}; > > + > > + enum ofperr error = ofputil_ct_match_decode(&match, NULL, &zone_id, > oh); > > + if (error) { > > + return error; > > + } > > + > > + ofputil_ct_match_format(string, &match); > > + ds_put_format(string, ",zone_id=%"PRIu16, zone_id); > > + > > + return 0; > > +} > > + > > static enum ofperr > > ofp_to_string__(const struct ofp_header *oh, > > const struct ofputil_port_map *port_map, > > @@ -1184,6 +1202,8 @@ ofp_to_string__(const struct ofp_header *oh, > > > > case OFPTYPE_CT_FLUSH_ZONE: > > return ofp_print_nxt_ct_flush_zone(string, ofpmsg_body(oh)); > > + case OFPTYPE_CT_FLUSH: > > + return ofp_print_nxt_ct_flush(string, oh); > > } > > > > return 0; > > diff --git a/lib/ofp-util.c b/lib/ofp-util.c > > index a324ceeea..a14cb6860 100644 > > --- a/lib/ofp-util.c > > +++ b/lib/ofp-util.c > > @@ -31,6 +31,7 @@ > > #include "multipath.h" > > #include "netdev.h" > > #include "nx-match.h" > > +#include "ofp-ct-util.h" > > #include "id-pool.h" > > #include "openflow/netronome-ext.h" > > #include "openvswitch/dynamic-string.h" > > @@ -237,3 +238,27 @@ ofputil_encode_barrier_request(enum ofp_version > ofp_version) > > > > return ofpraw_alloc(type, ofp_version, 0); > > } > > + > > +struct ofpbuf * > > +ofputil_ct_match_encode(const struct ofputil_ct_match *match, > > + uint16_t *zone_id, enum ofp_version version) > > +{ > > + struct ofpbuf *msg = ofpraw_alloc(OFPRAW_NXT_CT_FLUSH, version, 0); > > + struct nx_ct_flush *nx_flush = ofpbuf_put_zeros(msg, sizeof > *nx_flush); > > + const struct ofputil_ct_tuple *orig = &match->tuple_orig; > > + const struct ofputil_ct_tuple *reply = &match->tuple_reply; > > + > > + nx_flush->ip_proto = match->ip_proto; > > + nx_flush->family = match->l3_type; > > + > > + ofputil_ct_tuple_encode(orig, msg, NXT_CT_ORIG_DIRECTION, > > + match->ip_proto); > > + ofputil_ct_tuple_encode(reply, msg, NXT_CT_REPLY_DIRECTION, > > + match->ip_proto); > > + > > + if (zone_id) { > > + ofpprop_put_u16(msg, NXT_CT_ZONE_ID, *zone_id); > > + } > > + > > + return msg; > > +} > > diff --git a/lib/rconn.c b/lib/rconn.c > > index a96b2eb8b..4afa21515 100644 > > --- a/lib/rconn.c > > +++ b/lib/rconn.c > > @@ -1426,6 +1426,7 @@ is_admitted_msg(const struct ofpbuf *b) > > case OFPTYPE_IPFIX_FLOW_STATS_REQUEST: > > case OFPTYPE_IPFIX_FLOW_STATS_REPLY: > > case OFPTYPE_CT_FLUSH_ZONE: > > + case OFPTYPE_CT_FLUSH: > > default: > > return true; > > } > > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c > > index f9562dee8..29174a585 100644 > > --- a/ofproto/ofproto-dpif.c > > +++ b/ofproto/ofproto-dpif.c > > @@ -5358,11 +5358,12 @@ type_set_config(const char *type, const struct > smap *other_config) > > } > > > > static void > > -ct_flush(const struct ofproto *ofproto_, const uint16_t *zone) > > +ct_flush(const struct ofproto *ofproto_, const uint16_t *zone, > > + const struct ofputil_ct_match *match) > > { > > struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); > > > > - ct_dpif_flush(ofproto->backer->dpif, zone, NULL); > > + ct_dpif_flush(ofproto->backer->dpif, zone, match); > > } > > > > static struct ct_timeout_policy * > > @@ -5674,6 +5675,9 @@ get_datapath_cap(const char *datapath_type, struct > smap *cap) > > smap_add(cap, "lb_output_action", s.lb_output_action ? "true" : > "false"); > > smap_add(cap, "ct_zero_snat", s.ct_zero_snat ? "true" : "false"); > > smap_add(cap, "add_mpls", s.add_mpls ? "true" : "false"); > > + /* The ct_tuple_flush is implemented on dpif level, so it is > supported > > + * for all backers. */ > > + smap_add(cap, "ct_flush", "true"); > > } > > > > /* Gets timeout policy name in 'backer' based on 'zone', 'dl_type' and > > diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h > > index 7e3fb6698..5e39234f9 100644 > > --- a/ofproto/ofproto-provider.h > > +++ b/ofproto/ofproto-provider.h > > @@ -49,6 +49,7 @@ > > #include "openvswitch/ofp-port.h" > > #include "openvswitch/ofp-switch.h" > > #include "openvswitch/ofp-table.h" > > +#include "openvswitch/ofp-util.h" > > #include "ovs-atomic.h" > > #include "ovs-rcu.h" > > #include "ovs-thread.h" > > @@ -1902,8 +1903,10 @@ struct ofproto_class { > > /* ## Connection tracking ## */ > > /* ## ------------------- ## */ > > /* Flushes the connection tracking tables. If 'zone' is not NULL, > > - * only deletes connections in '*zone'. */ > > - void (*ct_flush)(const struct ofproto *, const uint16_t *zone); > > + * only deletes connections in '*zone'. If 'match' is not NULL, > > + * deletes connections specified by the match. */ > > + void (*ct_flush)(const struct ofproto *, const uint16_t *zone, > > + const struct ofputil_ct_match *match); > > > > /* Sets conntrack timeout policy specified by 'timeout_policy' to > 'zone' > > * in datapath type 'dp_type'. */ > > diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c > > index 3a527683c..c9b222994 100644 > > --- a/ofproto/ofproto.c > > +++ b/ofproto/ofproto.c > > @@ -34,6 +34,7 @@ > > #include "openvswitch/hmap.h" > > #include "netdev.h" > > #include "nx-match.h" > > +#include "ofp-ct-util.h" > > #include "ofproto.h" > > #include "ofproto-provider.h" > > #include "openflow/nicira-ext.h" > > @@ -934,7 +935,31 @@ handle_nxt_ct_flush_zone(struct ofconn *ofconn, > const struct ofp_header *oh) > > > > uint16_t zone = ntohs(nzi->zone_id); > > if (ofproto->ofproto_class->ct_flush) { > > - ofproto->ofproto_class->ct_flush(ofproto, &zone); > > + ofproto->ofproto_class->ct_flush(ofproto, &zone, NULL); > > + } else { > > + return EOPNOTSUPP; > > + } > > + > > + return 0; > > +} > > + > > +static enum ofperr > > +handle_nxt_ct_flush(struct ofconn *ofconn, const struct ofp_header *oh) > > +{ > > + struct ofproto *ofproto = ofconn_get_ofproto(ofconn); > > + struct ofputil_ct_match match = {0}; > > + bool with_zone = false; > > + uint16_t zone_id = 0; > > + > > + enum ofperr error = > > + ofputil_ct_match_decode(&match, &with_zone, &zone_id, oh); > > + if (error) { > > + return error; > > + } > > + > > + if (ofproto->ofproto_class->ct_flush) { > > + ofproto->ofproto_class->ct_flush(ofproto, with_zone ? &zone_id > : NULL, > > + &match); > > } else { > > return EOPNOTSUPP; > > } > > @@ -8787,6 +8812,9 @@ handle_single_part_openflow(struct ofconn *ofconn, > const struct ofp_header *oh, > > case OFPTYPE_CT_FLUSH_ZONE: > > return handle_nxt_ct_flush_zone(ofconn, oh); > > > > + case OFPTYPE_CT_FLUSH: > > + return handle_nxt_ct_flush(ofconn, oh); > > + > > case OFPTYPE_HELLO: > > case OFPTYPE_ERROR: > > case OFPTYPE_FEATURES_REPLY: > > diff --git a/tests/ofp-print.at b/tests/ofp-print.at > > index fe41cc42c..7c6a86133 100644 > > --- a/tests/ofp-print.at > > +++ b/tests/ofp-print.at > > @@ -4073,3 +4073,96 @@ AT_CHECK([ovs-ofctl ofp-print "\ > > NXT_CT_FLUSH_ZONE (xid=0x3): zone_id=13 > > ]) > > AT_CLEANUP > > + > > +AT_SETUP([NXT_CT_FLUSH]) > > +AT_KEYWORDS([ofp-print]) > > +AT_CHECK([ovs-ofctl ofp-print "\ > > +01 04 00 18 00 00 00 03 00 00 23 20 00 00 00 20 \ > > +06 \ > > +02 \ > > +00 00 00 00 00 00 \ > > +"], [0], [dnl > > +NXT_CT_FLUSH (xid=0x3): > l3_type=2,ip_proto=6,orig=(src=::,dst=::,src_port=0,dst_port=0),reply=(src=::,dst=::,src_port=0,dst_port=0),zone_id=0 > > +]) > > + > > +AT_CHECK([ovs-ofctl ofp-print "\ > > +01 04 00 20 00 00 00 03 00 00 23 20 00 00 00 20 \ > > +06 \ > > +02 \ > > +00 00 00 00 00 00 \ > > +00 09 00 08 00 0d 00 00 \ > > +"], [0], [dnl > > +NXT_CT_FLUSH (xid=0x3): > l3_type=2,ip_proto=6,orig=(src=::,dst=::,src_port=0,dst_port=0),reply=(src=::,dst=::,src_port=0,dst_port=0),zone_id=13 > > +]) > > + > > +AT_CHECK([ovs-ofctl ofp-print "\ > > +01 04 00 68 00 00 00 03 00 00 23 20 00 00 00 20 \ > > +06 \ > > +02 \ > > +00 00 00 00 00 00 \ > > +00 09 00 08 00 0d 00 00 \ > > +00 00 00 48 00 00 00 00 \ > > +00 02 00 14 00 00 00 00 00 00 00 00 00 00 ff ff 0a 0a 00 01 00 00 00 00 > \ > > +00 03 00 14 00 00 00 00 00 00 00 00 00 00 ff ff 0a 0a 00 02 00 00 00 00 > \ > > +00 04 00 08 00 50 00 00 \ > > +00 05 00 08 1f 90 00 00 \ > > +"], [0], [dnl > > +NXT_CT_FLUSH (xid=0x3): > l3_type=2,ip_proto=6,orig=(src=10.10.0.1,dst=10.10.0.2,src_port=80,dst_port=8080),reply=(src=::,dst=::,src_port=0,dst_port=0),zone_id=13 > > +]) > > + > > +AT_CHECK([ovs-ofctl ofp-print "\ > > +01 04 00 68 00 00 00 03 00 00 23 20 00 00 00 20 \ > > +06 \ > > +02 \ > > +00 00 00 00 00 00 \ > > +00 09 00 08 00 0d 00 00 \ > > +00 01 00 48 00 00 00 00 \ > > +00 03 00 14 00 00 00 00 00 00 00 00 00 00 ff ff 0a 0a 00 01 00 00 00 00 > \ > > +00 02 00 14 00 00 00 00 00 00 00 00 00 00 ff ff 0a 0a 00 02 00 00 00 00 > \ > > +00 05 00 08 00 50 00 00 \ > > +00 04 00 08 1f 90 00 00 \ > > +"], [0], [dnl > > +NXT_CT_FLUSH (xid=0x3): > l3_type=2,ip_proto=6,orig=(src=::,dst=::,src_port=0,dst_port=0),reply=(src=10.10.0.2,dst=10.10.0.1,src_port=8080,dst_port=80),zone_id=13 > > +]) > > + > > +AT_CHECK([ovs-ofctl ofp-print "\ > > +01 04 00 b0 00 00 00 03 00 00 23 20 00 00 00 20 \ > > +06 \ > > +02 \ > > +00 00 00 00 00 00 \ > > +00 09 00 08 00 0d 00 00 \ > > +00 00 00 48 00 00 00 00 \ > > +00 02 00 14 00 00 00 00 00 00 00 00 00 00 ff ff 0a 0a 00 01 00 00 00 00 > \ > > +00 03 00 14 00 00 00 00 00 00 00 00 00 00 ff ff 0a 0a 00 02 00 00 00 00 > \ > > +00 04 00 08 00 50 00 00 \ > > +00 05 00 08 1f 90 00 00 \ > > +00 01 00 48 00 00 00 00 \ > > +00 03 00 14 00 00 00 00 00 00 00 00 00 00 ff ff 0a 0a 00 01 00 00 00 00 > \ > > +00 02 00 14 00 00 00 00 00 00 00 00 00 00 ff ff 0a 0a 00 02 00 00 00 00 > \ > > +00 05 00 08 00 50 00 00 \ > > +00 04 00 08 1f 90 00 00 \ > > +"], [0], [dnl > > +NXT_CT_FLUSH (xid=0x3): > l3_type=2,ip_proto=6,orig=(src=10.10.0.1,dst=10.10.0.2,src_port=80,dst_port=8080),reply=(src=10.10.0.2,dst=10.10.0.1,src_port=8080,dst_port=80),zone_id=13 > > +]) > > + > > +AT_CHECK([ovs-ofctl ofp-print "\ > > +01 04 00 b8 00 00 00 03 00 00 23 20 00 00 00 20 \ > > +01 \ > > +0a \ > > +00 00 00 00 00 00 \ > > +00 00 00 50 00 00 00 00 \ > > +00 02 00 14 fd 18 00 00 00 00 00 00 00 00 ff ff ab cd 00 01 00 00 00 00 > \ > > +00 03 00 14 fd 18 00 00 00 00 00 00 00 00 ff ff ab cd 00 02 00 00 00 00 > \ > > +00 06 00 08 00 0a 00 00 \ > > +00 07 00 05 01 00 00 00 \ > > +00 08 00 05 02 00 00 00 \ > > +00 01 00 50 00 00 00 00 \ > > +00 02 00 14 fd 18 00 00 00 00 00 00 00 00 ff ff ab cd 00 02 00 00 00 00 > \ > > +00 02 00 14 fd 18 00 00 00 00 00 00 00 00 ff ff ab cd 00 01 00 00 00 00 > \ > > +00 06 00 08 00 0a 00 00 \ > > +00 07 00 05 03 00 00 00 \ > > +00 08 00 05 04 00 00 00 \ > > +"], [0], [dnl > > +NXT_CT_FLUSH (xid=0x3): > l3_type=10,ip_proto=1,orig=(src=fd18::ffff:abcd:1,dst=fd18::ffff:abcd:2,icmp_id=10,icmp_type=1,icmp_code=2),reply=(src=fd18::ffff:abcd:1,dst=::,icmp_id=10,icmp_type=3,icmp_code=4),zone_id=0 > > +]) > > +AT_CLEANUP > > diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at > > index a8934051e..a14912768 100644 > > --- a/tests/ovs-ofctl.at > > +++ b/tests/ovs-ofctl.at > > @@ -3271,3 +3271,29 @@ AT_CHECK([ovs-ofctl -O OpenFlow15 dump-flows br0 > | ofctl_strip | sed '/OFPST_FLO > > > > OVS_VSWITCHD_STOP(["/Flow exceeded the maximum flow statistics reply > size and was excluded from the response set/d"]) > > AT_CLEANUP > > + > > +AT_SETUP([ovs-ofctl ct - flush-conntrack]) > > +OVS_VSWITCHD_START > > + > > +AT_CHECK([ovs-appctl vlog/set ct_dpif:dbg]) > > + > > +# Check flush conntrack with both zone and tuple > > +AT_CHECK([ovs-ofctl flush-conntrack br0 zone=5 > 'ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=1']) > > + > > +OVS_WAIT_UNTIL([test $(grep -c "|ct_dpif|DBG|.*ct_flush" > ovs-vswitchd.log) -eq 1]) > > +AT_CHECK([grep -q "ct_dpif|DBG|.*ct_flush: > l3_type=2,ip_proto=17,orig=(src=10.1.1.1,dst=10.1.1.2,src_port=1,dst_port=0),reply=(src=::,dst=::,src_port=0,dst_port=0) > in zone 5" ovs-vswitchd.log]) > > + > > +# Check flush-conntrack just with tuple > > +AT_CHECK([ovs-ofctl flush-conntrack br0 > 'ct_nw_src=10.1.1.3,ct_nw_dst=10.1.1.4,ct_nw_proto=17,ct_tp_src=1']) > > + > > +OVS_WAIT_UNTIL([test $(grep -c "|ct_dpif|DBG|.*ct_flush" > ovs-vswitchd.log) -eq 2]) > > +AT_CHECK([grep -q "ct_dpif|DBG|.*ct_flush: > l3_type=2,ip_proto=17,orig=(src=10.1.1.3,dst=10.1.1.4,src_port=1,dst_port=0),reply=(src=::,dst=::,src_port=0,dst_port=0) > in zone 0" ovs-vswitchd.log]) > > + > > +# Check flush-conntrack without any tuple and zone > > +AT_CHECK([ovs-ofctl flush-conntrack br0]) > > + > > +OVS_WAIT_UNTIL([test $(grep -c "|ct_dpif|DBG|.*ct_flush" > ovs-vswitchd.log) -eq 3]) > > +AT_CHECK([grep -q "ct_dpif|DBG|.*ct_flush: <all>" ovs-vswitchd.log]) > > + > > +OVS_VSWITCHD_STOP > > +AT_CLEANUP > > diff --git a/tests/system-traffic.at b/tests/system-traffic.at > > index 51903a658..396d81ad9 100644 > > --- a/tests/system-traffic.at > > +++ b/tests/system-traffic.at > > @@ -2250,126 +2250,136 @@ > priority=100,in_port=2,icmp,action=ct(zone=5,commit),1 > > > > AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt]) > > > > -dnl Test UDP from port 1 > > -AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=1 > packet=50540000000a50540000000908004500001c000000000011a4cd0a0101010a0101020001000200080000 > actions=resubmit(,0)"]) > > +flush_conntrack() { > > + if [[ "$1" == "dpctl" ]]; then > > + AT_CHECK([ovs-appctl dpctl/flush-conntrack ${@:2}]) > > + else > > + AT_CHECK([ovs-ofctl flush-conntrack br0 ${@:2}]) > > + fi > > +} > > > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep > "orig=.src=10\.1\.1\.1,"], [], [dnl > > +for type in dpctl ofctl; do > > + AS_BOX([Testing with $type command]) > > + > > + dnl Test UDP from port 1 > > + AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=1 > packet=50540000000a50540000000908004500001c000000000011a4cd0a0101010a0101020001000200080000 > actions=resubmit(,0)"]) > > + > > + AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep > "orig=.src=10\.1\.1\.1,"], [], [dnl > > > udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),reply=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1) > > ]) > > > > -AT_CHECK([ovs-appctl dpctl/flush-conntrack > 'ct_nw_src=10.1.1.2,ct_nw_dst=10.1.1.1,ct_nw_proto=17,ct_tp_src=2,ct_tp_dst=1']) > > + AT_CHECK([flush_conntrack $type > 'ct_nw_src=10.1.1.2,ct_nw_dst=10.1.1.1,ct_nw_proto=17,ct_tp_src=2,ct_tp_dst=1']) > > > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep > "orig=.src=10\.1\.1\.1,"], [1], [dnl > > -]) > > + AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep > "orig=.src=10\.1\.1\.1,"], [1]) > > > > -dnl Test UDP from port 2 > > -AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=2 > packet=50540000000a50540000000908004500001c000000000011a4cd0a0101020a0101010002000100080000 > actions=resubmit(,0)"]) > > > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep > "orig=.src=10\.1\.1\.2,"], [0], [dnl > > + dnl Test UDP from port 2 > > + AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=2 > packet=50540000000a50540000000908004500001c000000000011a4cd0a0101020a0101010002000100080000 > actions=resubmit(,0)"]) > > + > > + AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep > "orig=.src=10\.1\.1\.2,"], [0], [dnl > > > udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),zone=5 > > ]) > > > > -AT_CHECK([ovs-appctl dpctl/flush-conntrack zone=5 > 'ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2']) > > + AT_CHECK([flush_conntrack $type zone=5 > 'ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2']) > > > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2)], [0], > [dnl > > -]) > > + AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2)], > [0]) > > > > -dnl Test ICMP traffic > > -NS_CHECK_EXEC([at_ns1], [ping -q -c 3 -i 0.3 -w 2 10.1.1.1 | > FORMAT_PING], [0], [dnl > > + dnl Test ICMP traffic > > + NS_CHECK_EXEC([at_ns1], [ping -q -c 3 -i 0.3 -w 2 10.1.1.1 | > FORMAT_PING], [0], [dnl > > 3 packets transmitted, 3 received, 0% packet loss, time 0ms > > ]) > > > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep > "orig=.src=10\.1\.1\.2,"], [0], [stdout]) > > -AT_CHECK([cat stdout | FORMAT_CT(10.1.1.1)], [0],[dnl > > + AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep > "orig=.src=10\.1\.1\.2,"], [0], [stdout]) > > + AT_CHECK([cat stdout | FORMAT_CT(10.1.1.1)], [0],[dnl > > > icmp,orig=(src=10.1.1.2,dst=10.1.1.1,id=<cleared>,type=8,code=0),reply=(src=10.1.1.1,dst=10.1.1.2,id=<cleared>,type=0,code=0),zone=5 > > ]) > > > > -ICMP_ID=`cat stdout | cut -d ',' -f4 | cut -d '=' -f2` > > > -ICMP_TUPLE=ct_nw_src=10.1.1.2,ct_nw_dst=10.1.1.1,ct_nw_proto=1,icmp_id=$ICMP_ID,icmp_type=8,icmp_code=0 > > -AT_CHECK([ovs-appctl dpctl/flush-conntrack zone=5 $ICMP_TUPLE]) > > + ICMP_ID=`cat stdout | cut -d ',' -f4 | cut -d '=' -f2` > > + > ICMP_TUPLE=ct_nw_src=10.1.1.2,ct_nw_dst=10.1.1.1,ct_nw_proto=1,icmp_id=$ICMP_ID,icmp_type=8,icmp_code=0 > > + AT_CHECK([flush_conntrack $type zone=5 $ICMP_TUPLE]) > > > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep > "orig=.src=10\.1\.1\.2,"], [1], [dnl > > -]) > > + AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep > "orig=.src=10\.1\.1\.2,"], [1]) > > > > -dnl Test UDP from port 1 and 2, partial flush by src port > > -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=2 > packet=50540000000a50540000000908004500001c000000000011a4cd0a0101020a0101010002000100080000 > actions=resubmit(,0)"]) > > + dnl Test UDP from port 1 and 2, partial flush by src port > > + 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=2 > packet=50540000000a50540000000908004500001c000000000011a4cd0a0101020a0101010002000100080000 > actions=resubmit(,0)"]) > > > > > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1" | sort], > [0], [dnl > > + AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1" | > sort], [0], [dnl > > > udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),reply=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1) > > > udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),zone=5 > > ]) > > > > -AT_CHECK([ovs-appctl dpctl/flush-conntrack > 'ct_nw_proto=17,ct_tp_src=1']) > > + AT_CHECK([flush_conntrack $type 'ct_nw_proto=17,ct_tp_src=1']) > > > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], [0], > [dnl > > + AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], > [0], [dnl > > > udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),zone=5 > > ]) > > > > -AT_CHECK([ovs-appctl dpctl/flush-conntrack > 'ct_nw_proto=17,ct_tp_src=2']) > > + AT_CHECK([flush_conntrack $type 'ct_nw_proto=17,ct_tp_src=2']) > > > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], [1]) > > + AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], > [1]) > > > > -dnl Test UDP from port 1 and 2, partial flush by dst port > > -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=2 > packet=50540000000a50540000000908004500001c000000000011a4cd0a0101020a0101010002000100080000 > actions=resubmit(,0)"]) > > + dnl Test UDP from port 1 and 2, partial flush by dst port > > + 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=2 > packet=50540000000a50540000000908004500001c000000000011a4cd0a0101020a0101010002000100080000 > actions=resubmit(,0)"]) > > > > > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1" | sort], > [0], [dnl > > + AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1" | > sort], [0], [dnl > > > udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),reply=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1) > > > udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),zone=5 > > ]) > > > > -AT_CHECK([ovs-appctl dpctl/flush-conntrack > 'ct_nw_proto=17,ct_tp_dst=2']) > > + AT_CHECK([flush_conntrack $type 'ct_nw_proto=17,ct_tp_dst=2']) > > > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], [0], > [dnl > > + AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], > [0], [dnl > > > udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),zone=5 > > ]) > > > > -AT_CHECK([ovs-appctl dpctl/flush-conntrack > 'ct_nw_proto=17,ct_tp_dst=1']) > > + AT_CHECK([flush_conntrack $type 'ct_nw_proto=17,ct_tp_dst=1']) > > > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], [1]) > > + AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], > [1]) > > > > -dnl Test UDP from port 1 and 2, partial flush by src address > > -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=2 > packet=50540000000a50540000000908004500001c000000000011a4cd0a0101020a0101010002000100080000 > actions=resubmit(,0)"]) > > + dnl Test UDP from port 1 and 2, partial flush by src address > > + 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=2 > packet=50540000000a50540000000908004500001c000000000011a4cd0a0101020a0101010002000100080000 > actions=resubmit(,0)"]) > > > > > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1" | sort], > [0], [dnl > > + AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1" | > sort], [0], [dnl > > > udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),reply=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1) > > > udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),zone=5 > > ]) > > > > -AT_CHECK([ovs-appctl dpctl/flush-conntrack 'ct_nw_src=10.1.1.1']) > > + AT_CHECK([flush_conntrack $type 'ct_nw_src=10.1.1.1']) > > > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], [0], > [dnl > > + AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], > [0], [dnl > > > udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),zone=5 > > ]) > > > > -AT_CHECK([ovs-appctl dpctl/flush-conntrack 'ct_nw_src=10.1.1.2']) > > + AT_CHECK([flush_conntrack $type 'ct_nw_src=10.1.1.2']) > > > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], [1]) > > + AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], > [1]) > > > > -dnl Test UDP from port 1 and 2, partial flush by dst address > > -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=2 > packet=50540000000a50540000000908004500001c000000000011a4cd0a0101020a0101010002000100080000 > actions=resubmit(,0)"]) > > + dnl Test UDP from port 1 and 2, partial flush by dst address > > + 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=2 > packet=50540000000a50540000000908004500001c000000000011a4cd0a0101020a0101010002000100080000 > actions=resubmit(,0)"]) > > > > > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1" | sort], > [0], [dnl > > + AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1" | > sort], [0], [dnl > > > udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),reply=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1) > > > udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),zone=5 > > ]) > > > > -AT_CHECK([ovs-appctl dpctl/flush-conntrack 'ct_nw_dst=10.1.1.2']) > > + AT_CHECK([flush_conntrack $type 'ct_nw_dst=10.1.1.2']) > > > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], [0], > [dnl > > + AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], > [0], [dnl > > > udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2),zone=5 > > ]) > > > > -AT_CHECK([ovs-appctl dpctl/flush-conntrack 'ct_nw_dst=10.1.1.1']) > > + AT_CHECK([flush_conntrack $type 'ct_nw_dst=10.1.1.1']) > > > > -AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], [1]) > > + AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], > [1]) > > +done > > > > OVS_TRAFFIC_VSWITCHD_STOP > > AT_CLEANUP > > diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c > > index fe9114580..8cb0911a2 100644 > > --- a/utilities/ovs-ofctl.c > > +++ b/utilities/ovs-ofctl.c > > @@ -40,6 +40,7 @@ > > #include "fatal-signal.h" > > #include "nx-match.h" > > #include "odp-util.h" > > +#include "ofp-ct-util.h" > > #include "ofp-version-opt.h" > > #include "ofproto/ofproto.h" > > #include "openflow/nicira-ext.h" > > @@ -3050,6 +3051,40 @@ ofctl_ct_flush_zone(struct ovs_cmdl_context *ctx) > > vconn_close(vconn); > > } > > > > +static void > > +ofctl_ct_flush_conntrack(struct ovs_cmdl_context *ctx) > > +{ > > + struct vconn *vconn; > > + struct ofputil_ct_match match = {0}; > > + struct ds ds = DS_EMPTY_INITIALIZER; > > + uint16_t zone; > > + bool with_zone = false; > > + int args = ctx->argc - 2; > > + > > + /* Parse ct tuple */ > > + if (args) { > > + if (!ofputil_ct_match_parse(&match, ctx->argv[ctx->argc - 1], > &ds)) { > > + ovs_fatal(0, "Failed to parse ct-tuple: %s", ds_cstr(&ds)); > > + } > > + args--; > > + } > > + > > + /* Parse zone */ > > + if (args && ovs_scan(ctx->argv[ctx->argc - 2], "zone=%"SCNu16, > &zone)) { > > + with_zone = true; > > + } > > + > > + open_vconn(ctx->argv[1], &vconn); > > + enum ofp_version version = vconn_get_version(vconn); > > + > > + struct ofpbuf *msg = > > + ofputil_ct_match_encode(&match, with_zone ? &zone : NULL, > version); > > + > > + ds_destroy(&ds); > > + transact_noreply(vconn, msg); > > + vconn_close(vconn); > > +} > > + > > static void > > ofctl_dump_ipfix_flow(struct ovs_cmdl_context *ctx) > > { > > @@ -5063,6 +5098,9 @@ static const struct ovs_cmdl_command > all_commands[] = { > > { "ct-flush-zone", "switch zone", > > 2, 2, ofctl_ct_flush_zone, OVS_RO }, > > > > + { "flush-conntrack", "switch [zone=N] [ct-tuple]", > > + 1, 3, ofctl_ct_flush_conntrack, OVS_RO }, > > + > > usage() for this is missing and the entry in utilities/ovs-ofctl.8.in > > > { "ofp-parse", "file", > > 1, 1, ofctl_ofp_parse, OVS_RW }, > > { "ofp-parse-pcap", "pcap", > > -- > > 2.38.1 > > Both addressed in v5, thanks. -- Ales Musil Senior Software Engineer - OVN Core Red Hat EMEA <https://www.redhat.com> [email protected] IM: amusil <https://red.ht/sig> _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
