On Wed, Oct 25, 2023 at 12:25 AM Ilya Maximets <i.maxim...@ovn.org> wrote:
> On 10/18/23 08:28, Ales Musil wrote: > > Extend the current NX_CT_FLUSH with four additional fields, > > that allow to match on CT entry "mark" or "labels". This > > is encoded as separate TLV values which is backward compatible. > > Versions that do not support them will simply ignore it. > > Hmm. Just noticed that. This doesn't seem right. If unknown > property is passed, OVS should fail with OFPPROP_UNKNOWN(). > This probably should be a separate fix that we'll need to > backport to stable versions. If user requests flushing a > specific label, we should not flush everything just because > we do not understand the request. > > Some more comments inline. > > Best regards, Ilya Maximets. > Hi Ilya, thank you for the review. It makes sense to report unknown values, it's a bit unfortunate because now we will probably need an additional feature flag to indicate that this is supported WDYT? I'll wait with v4 until the feature flag is resolved. > > > > > Extend also the ovs-dpctl and ovs-ofctl command line tools with > > option to specify those two matching parameters for the "ct-flush" > > command. > > > > Reported-at: https://issues.redhat.com/browse/FDP-55 > > Signed-off-by: Ales Musil <amu...@redhat.com> > > --- > > v3: Rebase on top of current master. > > v2: Make sure that the mask decoding matches the dpctl/ovs-ofctl > interface. > > --- > > include/openflow/nicira-ext.h | 4 + > > include/openvswitch/ofp-ct.h | 9 +- > > lib/ct-dpif.c | 12 ++- > > lib/dpctl.c | 5 +- > > lib/ofp-ct.c | 151 +++++++++++++++++++++++++++++++++- > > tests/ofp-print.at | 56 +++++++++++++ > > tests/ovs-ofctl.at | 32 +++++++ > > tests/system-traffic.at | 112 ++++++++++++++++--------- > > utilities/ovs-ofctl.8.in | 13 +-- > > utilities/ovs-ofctl.c | 5 +- > > 10 files changed, 344 insertions(+), 55 deletions(-) > > The change needs a NEWS entry. > > > > > diff --git a/include/openflow/nicira-ext.h > b/include/openflow/nicira-ext.h > > index 768775898..959845ce6 100644 > > --- a/include/openflow/nicira-ext.h > > +++ b/include/openflow/nicira-ext.h > > @@ -1075,6 +1075,10 @@ enum nx_ct_flush_tlv_type { > > * by 'enum nx_ct_flush_tuple_tlv_type'*/ > > /* Primitive types. */ > > NXT_CT_ZONE_ID = 2, /* be16 zone id. */ > > + NXT_CT_MARK = 3, /* be32 mark. */ > > + NXT_CT_MARK_MASK = 4, /* be32 mark mask. */ > > + NXT_CT_LABELS = 5, /* be128 labels. */ > > + NXT_CT_LABELS_MASK = 6, /* be128 labels mask. */ > > }; > > > > /* CT flush nested TLVs. */ > > diff --git a/include/openvswitch/ofp-ct.h b/include/openvswitch/ofp-ct.h > > index cd6192e6f..d57b62678 100644 > > --- a/include/openvswitch/ofp-ct.h > > +++ b/include/openvswitch/ofp-ct.h > > @@ -51,11 +51,16 @@ struct ofp_ct_match { > > > > struct ofp_ct_tuple tuple_orig; > > struct ofp_ct_tuple tuple_reply; > > + > > + uint32_t mark; > > + uint32_t mark_mask; > > + > > + ovs_u128 labels; > > + ovs_u128 labels_mask; > > }; > > > > bool ofp_ct_match_is_zero(const struct ofp_ct_match *); > > -bool ofp_ct_tuple_is_zero(const struct ofp_ct_tuple *, uint8_t > ip_proto); > > -bool ofp_ct_tuple_is_five_tuple(const struct ofp_ct_tuple *, uint8_t > ip_proto); > > +bool ofp_ct_match_is_five_tuple(const struct ofp_ct_match *); > > > > void ofp_ct_match_format(struct ds *, const struct ofp_ct_match *); > > bool ofp_ct_match_parse(const char **, int argc, struct ds *, > > diff --git a/lib/ct-dpif.c b/lib/ct-dpif.c > > index f59c6e560..0fd14b99f 100644 > > --- a/lib/ct-dpif.c > > +++ b/lib/ct-dpif.c > > @@ -269,6 +269,15 @@ ct_dpif_entry_cmp(const struct ct_dpif_entry *entry, > > return false; > > } > > > > + if ((match->mark & match->mark_mask) != (entry->mark & > match->mark_mask)) { > > + return false; > > + } > > + > > + if (!ovs_u128_equals(ovs_u128_and(match->labels, > match->labels_mask), > > + ovs_u128_and(entry->labels, > match->labels_mask))) { > > + return false; > > + } > > + > > return true; > > } > > > > @@ -295,8 +304,7 @@ ct_dpif_flush_tuple(struct dpif *dpif, const > uint16_t *zone, > > > > /* If we have full five tuple in original and empty reply tuple just > > * do the flush over original tuple directly. */ > > - if (ofp_ct_tuple_is_five_tuple(&match->tuple_orig, match->ip_proto) > && > > - ofp_ct_tuple_is_zero(&match->tuple_reply, match->ip_proto)) { > > + if (ofp_ct_match_is_five_tuple(match)) { > > struct ct_dpif_tuple tuple; > > > > ct_dpif_tuple_from_ofp_ct_tuple(&match->tuple_orig, &tuple, > > diff --git a/lib/dpctl.c b/lib/dpctl.c > > index bbab5881e..9d28a91ba 100644 > > --- a/lib/dpctl.c > > +++ b/lib/dpctl.c > > @@ -2981,8 +2981,9 @@ static const struct dpctl_command all_commands[] = > { > > 0, 4, dpctl_dump_conntrack, DP_RO }, > > { "dump-conntrack-exp", "[dp] [zone=N]", > > 0, 2, dpctl_dump_conntrack_exp, DP_RO }, > > - { "flush-conntrack", "[dp] [zone=N] [ct-orig-tuple] > [ct-reply-tuple]", > > - 0, 4, dpctl_flush_conntrack, DP_RW }, > > + { "flush-conntrack", "[dp] [zone=N] [mark=X[/M]] [labels=Y[/N]] " > > + "[ct-orig-tuple [ct-reply-tuple]]", > > + 0, 6, dpctl_flush_conntrack, DP_RW }, > > { "cache-get-size", "[dp]", 0, 1, dpctl_cache_get_size, DP_RO }, > > { "cache-set-size", "dp cache <size>", 3, 3, dpctl_cache_set_size, > DP_RW }, > > { "ct-stats-show", "[dp] [zone=N]", > > diff --git a/lib/ofp-ct.c b/lib/ofp-ct.c > > index 32aeb5455..344f7a0b2 100644 > > --- a/lib/ofp-ct.c > > +++ b/lib/ofp-ct.c > > @@ -50,7 +50,7 @@ ofp_ct_tuple_format(struct ds *ds, const struct > ofp_ct_tuple *tuple, > > } > > } > > > > -bool > > +static bool > > ofp_ct_tuple_is_zero(const struct ofp_ct_tuple *tuple, uint8_t ip_proto) > > { > > bool is_zero = ipv6_is_zero(&tuple->src) && > ipv6_is_zero(&tuple->dst); > > @@ -62,7 +62,7 @@ ofp_ct_tuple_is_zero(const struct ofp_ct_tuple *tuple, > uint8_t ip_proto) > > return is_zero; > > } > > > > -bool > > +static bool > > ofp_ct_tuple_is_five_tuple(const struct ofp_ct_tuple *tuple, uint8_t > ip_proto) > > { > > /* First check if we have address. */ > > @@ -75,17 +75,63 @@ ofp_ct_tuple_is_five_tuple(const struct ofp_ct_tuple > *tuple, uint8_t ip_proto) > > return five_tuple; > > } > > > > +static bool > > +ofp_ct_match_mark_is_zero(const struct ofp_ct_match *match) > > +{ > > + return !match->mark && !match->mark_mask; > > If the mask is zero, why do we care about the value? > We don't, but I don't see any harm in checking both. > > > +} > > + > > +static bool > > +ofp_ct_match_labels_is_zero(const struct ofp_ct_match *match) > > +{ > > + return ovs_u128_is_zero(match->labels) && > > + ovs_u128_is_zero(match->labels_mask); > > ditto. > > > +} > > + > > +bool > > +ofp_ct_match_is_five_tuple(const struct ofp_ct_match *match) > > +{ > > + return ofp_ct_tuple_is_five_tuple(&match->tuple_orig, > match->ip_proto) && > > + ofp_ct_tuple_is_zero(&match->tuple_reply, match->ip_proto) && > > + ofp_ct_match_mark_is_zero(match) && > > + ofp_ct_match_labels_is_zero(match); > > +} > > + > > bool > > ofp_ct_match_is_zero(const struct ofp_ct_match *match) > > { > > return !match->ip_proto && !match->l3_type && > > ofp_ct_tuple_is_zero(&match->tuple_orig, match->ip_proto) && > > - ofp_ct_tuple_is_zero(&match->tuple_reply, match->ip_proto); > > + ofp_ct_tuple_is_zero(&match->tuple_reply, match->ip_proto) && > > + ofp_ct_match_mark_is_zero(match) && > > + ofp_ct_match_labels_is_zero(match); > > } > > > > void > > ofp_ct_match_format(struct ds *ds, const struct ofp_ct_match *match) > > { > > + if (!ofp_ct_match_mark_is_zero(match)) { > > + ds_put_format(ds, "mark=%#"PRIx32, match->mark); > > + if (match->mark_mask != UINT32_MAX) { > > + ds_put_format(ds, "/%#"PRIx32, match->mark_mask); > > + } > > + ds_put_char(ds, ' '); > > + } > > + > > + if (!ofp_ct_match_labels_is_zero(match)) { > > + ovs_be128 be_value = hton128(match->labels); > > + ovs_be128 be_mask = hton128(match->labels_mask); > > + > > + ds_put_cstr(ds, "labels="); > > + ds_put_hex(ds, &be_value, sizeof be_value); > > + > > + if (!ovs_u128_is_ones(match->labels_mask)) { > > + ds_put_char(ds, '/'); > > + ds_put_hex(ds, &be_mask, sizeof be_mask); > > + } > > + ds_put_char(ds, ' '); > > + } > > + > > ds_put_cstr(ds, "'"); > > ofp_ct_tuple_format(ds, &match->tuple_orig, match->ip_proto, > > match->l3_type); > > @@ -95,6 +141,23 @@ ofp_ct_match_format(struct ds *ds, const struct > ofp_ct_match *match) > > ds_put_cstr(ds, "'"); > > } > > > > +static inline bool > > +ofp_ct_masked_parse(const char *s, uint8_t *val, size_t val_len, > > + uint8_t *mask, size_t mask_len) > > +{ > > + char *tail; > > + if (!parse_int_string(s, val, val_len, &tail)) { > > + if (*tail != '/' || parse_int_string(tail + 1, mask, > > + mask_len, &tail)) { > > + memset(mask, UINT8_MAX, mask_len); > > + } > > + > > + return true; > > + } > > + > > + return false; > > +} > > + > > /* Parses a specification of a conntrack 5-tuple from 's' into 'tuple'. > > * Returns true on success. Otherwise, returns false and puts the error > > * message in 'ds'. */ > > @@ -236,6 +299,40 @@ ofp_ct_match_parse(const char **argv, int argc, > struct ds *ds, > > args--; > > } > > > > + /* Parse mark. */ > > + if (args && !strncmp(argv[argc - args], "mark=", 5)) { > > + const char *s = argv[argc - args] + 5; > > + ovs_be32 mark_be; > > + ovs_be32 mask_be; > > + > > + if (ofp_ct_masked_parse(s, (uint8_t *) &mark_be, sizeof mark_be, > > + (uint8_t *) &mask_be, sizeof mask_be)) { > > + match->mark = ntohl(mark_be); > > + match->mark_mask = ntohl(mask_be); > > + } else { > > + ds_put_cstr(ds, "failed to parse mark"); > > + return false; > > + } > > + args--; > > + } > > + > > + /* Parse labels. */ > > + if (args && !strncmp(argv[argc - args], "labels=", 7)) { > > + const char *s = argv[argc - args] + 7; > > + ovs_be128 labels_be; > > + ovs_be128 mask_be; > > + > > + if (ofp_ct_masked_parse(s, (uint8_t *) &labels_be, sizeof > labels_be, > > + (uint8_t *) &mask_be, sizeof mask_be)) > { > > + match->labels = ntoh128(labels_be); > > + match->labels_mask = ntoh128(mask_be); > > + } else { > > + ds_put_cstr(ds, "failed to parse labels"); > > + return false; > > + } > > + args--; > > + } > > + > > /* Parse ct tuples. */ > > for (int i = 0; i < 2; i++) { > > if (!args) { > > @@ -382,6 +479,7 @@ enum ofperr > > ofp_ct_match_decode(struct ofp_ct_match *match, bool *with_zone, > > uint16_t *zone_id, const struct ofp_header *oh) > > { > > + uint32_t tlv_flags = 0; > > struct ofpbuf msg = ofpbuf_const_initializer(oh, ntohs(oh->length)); > > ofpraw_pull_assert(&msg); > > > > @@ -422,11 +520,43 @@ ofp_ct_match_decode(struct ofp_ct_match *match, > bool *with_zone, > > } > > error = ofpprop_parse_u16(&property, zone_id); > > break; > > + > > + case NXT_CT_MARK: > > + error = ofpprop_parse_u32(&property, &match->mark); > > + break; > > + > > + case NXT_CT_MARK_MASK: > > + error = ofpprop_parse_u32(&property, &match->mark_mask); > > + break; > > + > > + case NXT_CT_LABELS: > > + error = ofpprop_parse_u128(&property, &match->labels); > > + break; > > + > > + case NXT_CT_LABELS_MASK: > > + error = ofpprop_parse_u128(&property, &match->labels_mask); > > + break; > > } > > > > if (error) { > > return error; > > } > > + > > + if (type < (sizeof tlv_flags * CHAR_BIT)) { > > + tlv_flags |= (1 << type); > > The right size of this expression will have the type 'int', which is > signed. Left side is unsigned. Better use UINT32_C(1). > Same below. > > > + } > > + } > > + > > + /* Consider the mask being all ones if it's not present but the > value > > + * is specified. */ > > + if (tlv_flags & (1 << NXT_CT_MARK) && > > + !(tlv_flags & (1 << NXT_CT_MARK_MASK))) { > > + match->mark_mask = UINT32_MAX; > > + } > > + > > + if (tlv_flags & (1 << NXT_CT_LABELS) && > > + !(tlv_flags & (1 << NXT_CT_LABELS_MASK))) { > > + match->labels_mask = OVS_U128_MAX; > > } > > > > return 0; > > @@ -450,5 +580,20 @@ ofp_ct_match_encode(const struct ofp_ct_match > *match, uint16_t *zone_id, > > ofpprop_put_u16(msg, NXT_CT_ZONE_ID, *zone_id); > > } > > > > + if (match->mark) { > > + ofpprop_put_u32(msg, NXT_CT_MARK, match->mark); > > + } > > + if (match->mark_mask) { > > + ofpprop_put_u32(msg, NXT_CT_MARK_MASK, match->mark_mask); > > + } > > + > > + if (!ovs_u128_is_zero(match->labels)) { > > + ofpprop_put_u128(msg, NXT_CT_LABELS, match->labels); > > + } > > + > > + if (!ovs_u128_is_zero(match->labels_mask)) { > > + ofpprop_put_u128(msg, NXT_CT_LABELS_MASK, match->labels_mask); > > + } > > These seem to be not very user-friendly. There is no way to distinguish > a zero value for a non-provided one. Users should, probbaly, always > provide a mask here, and so the function will only check for a mask > to be non-zero and put both fields. In case of a full mask, the mask > itself can probably be omitted from the mesage. > > > + > > return msg; > > } > > diff --git a/tests/ofp-print.at b/tests/ofp-print.at > > index 14aa55416..b96ad1fba 100644 > > --- a/tests/ofp-print.at > > +++ b/tests/ofp-print.at > > @@ -4093,6 +4093,62 @@ AT_CHECK([ovs-ofctl ofp-print "\ > > NXT_CT_FLUSH (xid=0x3): zone=13 > 'ct_ipv6_src=::,ct_ipv6_dst=::,ct_tp_src=0,ct_tp_dst=0,ct_nw_proto=6' > 'ct_ipv6_src=::,ct_ipv6_dst=::,ct_tp_src=0,ct_tp_dst=0' > > ]) > > > > +AT_CHECK([ovs-ofctl ofp-print "\ > > +01 04 00 20 00 00 00 03 00 00 23 20 00 00 00 20 \ > > +06 \ > > +00 00 00 00 00 00 00 \ > > +00 03 00 08 00 00 00 ab \ > > +"], [0], [dnl > > +NXT_CT_FLUSH (xid=0x3): zone=0 mark=0xab > 'ct_ipv6_src=::,ct_ipv6_dst=::,ct_tp_src=0,ct_tp_dst=0,ct_nw_proto=6' > 'ct_ipv6_src=::,ct_ipv6_dst=::,ct_tp_src=0,ct_tp_dst=0' > > +]) > > + > > +AT_CHECK([ovs-ofctl ofp-print "\ > > +01 04 00 20 00 00 00 03 00 00 23 20 00 00 00 20 \ > > +06 \ > > +00 00 00 00 00 00 00 \ > > +00 04 00 08 00 00 00 cd \ > > +"], [0], [dnl > > +NXT_CT_FLUSH (xid=0x3): zone=0 mark=0/0xcd > 'ct_ipv6_src=::,ct_ipv6_dst=::,ct_tp_src=0,ct_tp_dst=0,ct_nw_proto=6' > 'ct_ipv6_src=::,ct_ipv6_dst=::,ct_tp_src=0,ct_tp_dst=0' > > +]) > > + > > +AT_CHECK([ovs-ofctl ofp-print "\ > > +01 04 00 28 00 00 00 03 00 00 23 20 00 00 00 20 \ > > +06 \ > > +00 00 00 00 00 00 00 \ > > +00 03 00 08 00 00 00 ab \ > > +00 04 00 08 00 00 00 cd \ > > +"], [0], [dnl > > +NXT_CT_FLUSH (xid=0x3): zone=0 mark=0xab/0xcd > 'ct_ipv6_src=::,ct_ipv6_dst=::,ct_tp_src=0,ct_tp_dst=0,ct_nw_proto=6' > 'ct_ipv6_src=::,ct_ipv6_dst=::,ct_tp_src=0,ct_tp_dst=0' > > +]) > > + > > +AT_CHECK([ovs-ofctl ofp-print "\ > > +01 04 00 30 00 00 00 03 00 00 23 20 00 00 00 20 \ > > +06 \ > > +00 00 00 00 00 00 00 \ > > +00 05 00 14 00 00 00 00 00 00 00 00 00 00 00 00 00 ff ab 00 00 00 00 00 > \ > > +"], [0], [dnl > > +NXT_CT_FLUSH (xid=0x3): zone=0 labels=0xffab00 > 'ct_ipv6_src=::,ct_ipv6_dst=::,ct_tp_src=0,ct_tp_dst=0,ct_nw_proto=6' > 'ct_ipv6_src=::,ct_ipv6_dst=::,ct_tp_src=0,ct_tp_dst=0' > > +]) > > + > > +AT_CHECK([ovs-ofctl ofp-print "\ > > +01 04 00 30 00 00 00 03 00 00 23 20 00 00 00 20 \ > > +06 \ > > +00 00 00 00 00 00 00 \ > > +00 06 00 14 00 00 00 00 00 00 00 00 00 00 00 00 00 ff cd 00 00 00 00 00 > \ > > +"], [0], [dnl > > +NXT_CT_FLUSH (xid=0x3): zone=0 labels=0/0xffcd00 > 'ct_ipv6_src=::,ct_ipv6_dst=::,ct_tp_src=0,ct_tp_dst=0,ct_nw_proto=6' > 'ct_ipv6_src=::,ct_ipv6_dst=::,ct_tp_src=0,ct_tp_dst=0' > > +]) > > + > > +AT_CHECK([ovs-ofctl ofp-print "\ > > +01 04 00 48 00 00 00 03 00 00 23 20 00 00 00 20 \ > > +06 \ > > +00 00 00 00 00 00 00 \ > > +00 05 00 14 00 00 00 00 00 00 00 00 00 00 00 00 00 ff ab 00 00 00 00 00 > \ > > +00 06 00 14 00 00 00 00 00 00 00 00 00 00 00 00 00 ff cd 00 00 00 00 00 > \ > > +"], [0], [dnl > > +NXT_CT_FLUSH (xid=0x3): zone=0 labels=0xffab00/0xffcd00 > 'ct_ipv6_src=::,ct_ipv6_dst=::,ct_tp_src=0,ct_tp_dst=0,ct_nw_proto=6' > 'ct_ipv6_src=::,ct_ipv6_dst=::,ct_tp_src=0,ct_tp_dst=0' > > +]) > > + > > Maybe add a case with both mark and labeles together? > Might also make sense to have some inproperly fomatted message. > > > AT_CHECK([ovs-ofctl ofp-print "\ > > 01 04 00 68 00 00 00 03 00 00 23 20 00 00 00 20 \ > > 06 \ > > diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at > > index 8531b2e2e..39afdb1ab 100644 > > --- a/tests/ovs-ofctl.at > > +++ b/tests/ovs-ofctl.at > > @@ -3307,5 +3307,37 @@ AT_CHECK([ovs-ofctl ct-flush br0]) > > OVS_WAIT_UNTIL([test $(grep -c "|ct_dpif|DBG|.*ct_flush" > ovs-vswitchd.log) -eq 5]) > > AT_CHECK([grep -q "ct_dpif|DBG|.*ct_flush: <all>" ovs-vswitchd.log]) > > > > +AT_CHECK([ovs-ofctl ct-flush br0 mark=0]) > > +OVS_WAIT_UNTIL([test $(grep -c "|ct_dpif|DBG|.*ct_flush" > ovs-vswitchd.log) -eq 6]) > > +AT_CHECK([grep -q "ct_dpif|DBG|.*ct_flush: zone=0 mark=0" > ovs-vswitchd.log]) > > + > > +AT_CHECK([ovs-ofctl ct-flush br0 mark=0/0x5]) > > +OVS_WAIT_UNTIL([test $(grep -c "|ct_dpif|DBG|.*ct_flush" > ovs-vswitchd.log) -eq 7]) > > +AT_CHECK([grep -q "ct_dpif|DBG|.*ct_flush: zone=0 mark=0/0x5" > ovs-vswitchd.log]) > > + > > +AT_CHECK([ovs-ofctl ct-flush br0 mark=0xabc/0xdef]) > > +OVS_WAIT_UNTIL([test $(grep -c "|ct_dpif|DBG|.*ct_flush" > ovs-vswitchd.log) -eq 8]) > > +AT_CHECK([grep -q "ct_dpif|DBG|.*ct_flush: zone=0 mark=0xabc/0xdef" > ovs-vswitchd.log]) > > + > > +AT_CHECK([ovs-ofctl ct-flush br0 labels=0]) > > +OVS_WAIT_UNTIL([test $(grep -c "|ct_dpif|DBG|.*ct_flush" > ovs-vswitchd.log) -eq 9]) > > +AT_CHECK([grep -q "ct_dpif|DBG|.*ct_flush: zone=0 labels=0" > ovs-vswitchd.log]) > > + > > +AT_CHECK([ovs-ofctl ct-flush br0 labels=0/0x5]) > > +OVS_WAIT_UNTIL([test $(grep -c "|ct_dpif|DBG|.*ct_flush" > ovs-vswitchd.log) -eq 10]) > > +AT_CHECK([grep -q "ct_dpif|DBG|.*ct_flush: zone=0 labels=0/0x5" > ovs-vswitchd.log]) > > + > > +AT_CHECK([ovs-ofctl ct-flush br0 labels=0xabc/0xdef]) > > +OVS_WAIT_UNTIL([test $(grep -c "|ct_dpif|DBG|.*ct_flush" > ovs-vswitchd.log) -eq 11]) > > +AT_CHECK([grep -q "ct_dpif|DBG|.*ct_flush: zone=0 labels=0xabc/0xdef" > ovs-vswitchd.log]) > > + > > +AT_CHECK([ovs-ofctl ct-flush br0 zone=5 mark=25 labels=25]) > > +OVS_WAIT_UNTIL([test $(grep -c "|ct_dpif|DBG|.*ct_flush" > ovs-vswitchd.log) -eq 12]) > > +AT_CHECK([grep -q "ct_dpif|DBG|.*ct_flush: zone=5 mark=0x19 > labels=0x19" ovs-vswitchd.log]) > > + > > +AT_CHECK([ovs-ofctl ct-flush br0 zone=5 mark=30/25 labels=30/25]) > > +OVS_WAIT_UNTIL([test $(grep -c "|ct_dpif|DBG|.*ct_flush" > ovs-vswitchd.log) -eq 13]) > > +AT_CHECK([grep -q "ct_dpif|DBG|.*ct_flush: zone=5 mark=0x1e/0x19 > labels=0x1e/0x19" ovs-vswitchd.log]) > > + > > Same here. > > > OVS_VSWITCHD_STOP > > AT_CLEANUP > > diff --git a/tests/system-traffic.at b/tests/system-traffic.at > > index ec65ca5de..c71e25eac 100644 > > --- a/tests/system-traffic.at > > +++ b/tests/system-traffic.at > > @@ -2527,8 +2527,8 @@ ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24") > > AT_DATA([flows.txt], [dnl > > priority=1,action=drop > > priority=10,arp,action=normal > > -priority=100,in_port=1,ip,action=ct(commit),2 > > -priority=100,in_port=2,ip,action=ct(zone=5,commit),1 > > > +priority=100,in_port=1,ip,action=ct(commit,exec(set_field:0xaa->ct_mark)),2 > > > +priority=100,in_port=2,ip,action=ct(zone=5,commit,exec(set_field:0xaa00000000->ct_label)),1 > > ]) > > > > AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt]) > > @@ -2543,7 +2543,7 @@ 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) > > > +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),mark=170 > > ]) > > > > AT_CHECK([FLUSH_CMD > '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']) > > @@ -2555,7 +2555,7 @@ 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 > > > +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,labels=0xaa00000000 > > ]) > > > > AT_CHECK([FLUSH_CMD 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']) > > @@ -2569,7 +2569,7 @@ NS_CHECK_EXEC([at_ns1], [ping -q -c 3 -i 0.3 -w 2 > 10.1.1.1 | FORMAT_PING], [0], > > > > 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,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,labels=0xaa00000000 > > ]) > > > > ICMP_ID=`cat stdout | cut -d ',' -f4 | cut -d '=' -f2` > > @@ -2585,14 +2585,14 @@ AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 > "in_port=2 packet=50540000000a5 > > > > > > 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 > > > +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),mark=170 > > > +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,labels=0xaa00000000 > > ]) > > > > AT_CHECK([FLUSH_CMD 'ct_nw_proto=17,ct_tp_src=1']) > > > > 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 > > > +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,labels=0xaa00000000 > > ]) > > > > AT_CHECK([FLUSH_CMD 'ct_nw_proto=17,ct_tp_src=2']) > > @@ -2605,14 +2605,14 @@ AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 > "in_port=2 packet=50540000000a5 > > > > > > 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 > > > +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),mark=170 > > > +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,labels=0xaa00000000 > > ]) > > > > AT_CHECK([FLUSH_CMD 'ct_nw_proto=17,ct_tp_dst=2']) > > > > 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 > > > +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,labels=0xaa00000000 > > ]) > > > > AT_CHECK([FLUSH_CMD 'ct_nw_proto=17,ct_tp_dst=1']) > > @@ -2625,14 +2625,14 @@ AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 > "in_port=2 packet=50540000000a5 > > > > > > 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 > > > +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),mark=170 > > > +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,labels=0xaa00000000 > > ]) > > > > AT_CHECK([FLUSH_CMD 'ct_nw_src=10.1.1.1']) > > > > 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 > > > +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,labels=0xaa00000000 > > ]) > > > > AT_CHECK([FLUSH_CMD 'ct_nw_src=10.1.1.2']) > > @@ -2645,14 +2645,14 @@ AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 > "in_port=2 packet=50540000000a5 > > > > > > 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 > > > +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),mark=170 > > > +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,labels=0xaa00000000 > > ]) > > > > AT_CHECK([FLUSH_CMD 'ct_nw_dst=10.1.1.2']) > > > > 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 > > > +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,labels=0xaa00000000 > > ]) > > > > AT_CHECK([FLUSH_CMD 'ct_nw_dst=10.1.1.1']) > > @@ -2665,14 +2665,14 @@ AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 > "in_port=2 packet=50540000000a5 > > > > > > 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 > > > +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),mark=170 > > > +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,labels=0xaa00000000 > > ]) > > > > AT_CHECK([FLUSH_CMD '' 'ct_nw_src=10.1.1.2']) > > > > 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 > > > +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,labels=0xaa00000000 > > ]) > > > > AT_CHECK([FLUSH_CMD zone=5 '' 'ct_nw_src=10.1.1.1']) > > @@ -2685,8 +2685,8 @@ AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 > "in_port=2 packet=50540000000a5 > > > > > > 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 > > > +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),mark=170 > > > +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,labels=0xaa00000000 > > ]) > > > > AT_CHECK([FLUSH_CMD]) > > @@ -2698,46 +2698,80 @@ AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 > "in_port=1 packet=50540000000a5 > > AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=2 > packet=50540000000950540000000a08004500003400010000408464410a0101020a010101000200010000000098f29e470100001470e18ccc00000000000a000a00000000 > actions=resubmit(,0)"]) > > > > AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1" | sed > "s/,protoinfo=.*$//" | sort], [0], [dnl > > > -sctp,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) > > > -sctp,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 > > > +sctp,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),mark=170 > > > +sctp,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,labels=0xaa00000000 > > ]) > > > > AT_CHECK([FLUSH_CMD > 'ct_nw_src=10.1.1.1,ct_nw_proto=132,ct_tp_src=1,ct_tp_dst=2']) > > > > AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1" | sed > "s/,protoinfo=.*$//" | sort], [0], [dnl > > > -sctp,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 > > > +sctp,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,labels=0xaa00000000 > > ]) > > > > AT_CHECK([FLUSH_CMD > 'ct_nw_src=10.1.1.2,ct_nw_proto=132,ct_tp_src=2,ct_tp_dst=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 mark and labels > > +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 > > > +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),mark=170 > > > +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,labels=0xaa00000000 > > +]) > > + > > +AT_CHECK([FLUSH_CMD mark=0xaa]) > > + > > +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,labels=0xaa00000000 > > +]) > > + > > +AT_CHECK([FLUSH_CMD labels=0xaa00000000]) > > + > > +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], [1]) > > + > > +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 > > > +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),mark=170 > > > +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,labels=0xaa00000000 > > +]) > > + > > +AT_CHECK([FLUSH_CMD mark=2/2]) > > + > > +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,labels=0xaa00000000 > > ]) > > > > -dnl Test flush with invalid arguments > > +AT_CHECK([FLUSH_CMD labels=0x0200000000/0x0200000000]) > > + > > +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "10\.1\.1\.1"], [1]) > > + > > +dnl Test flush with invalid arguments. > > > > -AT_CHECK([ovs-appctl dpctl/flush-conntrack zone=invalid > 'ct_nw_src=10.1.1.1' 'ct_nw_dst=10.1.1.1'], [2], [ignore], [stderr]) > > +AT_CHECK([FLUSH_CMD zone=invalid 'ct_nw_src=10.1.1.1' > 'ct_nw_dst=10.1.1.1'], [ignore], [ignore], [stderr]) > > AT_CHECK([grep -q "failed to parse zone" stderr]) > > > > -AT_CHECK([ovs-appctl dpctl/flush-conntrack zone=1 > 'ct_nw_src=10.1.1.1,invalid=invalid' 'ct_nw_dst=10.1.1.1'], [2], [ignore], > [stderr]) > > +AT_CHECK([FLUSH_CMD zone=1 'ct_nw_src=10.1.1.1,invalid=invalid' > 'ct_nw_dst=10.1.1.1'], [ignore], [ignore], [stderr]) > > AT_CHECK([grep -q "invalid conntrack tuple field: invalid" stderr]) > > > > -AT_CHECK([ovs-appctl dpctl/flush-conntrack zone=1 'ct_nw_src=invalid' > 'ct_nw_dst=10.1.1.1'], [2], [ignore], [stderr]) > > +AT_CHECK([FLUSH_CMD zone=1 'ct_nw_src=invalid' 'ct_nw_dst=10.1.1.1'], > [ignore], [ignore], [stderr]) > > AT_CHECK([grep -q "failed to parse field ct_nw_src" stderr]) > > > > -AT_CHECK([ovs-appctl dpctl/flush-conntrack zone=1 'ct_nw_src=10.1.1.1' > 'ct_nw_dst=10.1.1.1' invalid], [2], [ignore], [stderr]) > > +AT_CHECK([FLUSH_CMD zone=1 'ct_nw_src=10.1.1.1' 'ct_nw_dst=10.1.1.1' > invalid], [ignore], [ignore], [stderr]) > > AT_CHECK([grep -q "invalid arguments" stderr]) > > > > -AT_CHECK([ovs-appctl dpctl/flush-conntrack $dp zone=1 > 'ct_nw_src=10.1.1.1' 'ct_nw_dst=10.1.1.1' invalid], [2], [ignore], [stderr]) > > -AT_CHECK([grep -q "command takes at most 4 arguments" stderr]) > > +AT_CHECK([FLUSH_CMD zone=1 mark=1 labels=1 'ct_nw_src=10.1.1.1' > 'ct_nw_dst=10.1.1.1' invalid invalid], [ignore], [ignore], [stderr]) > > +AT_CHECK([grep -q "command takes at most 6 arguments" stderr]) > > > > -AT_CHECK([ovs-appctl dpctl/flush-conntrack $dp 'ct_nw_src=10.1.1.1' > 'ct_nw_dst=10.1.1.1' invalid], [2], [ignore], [stderr]) > > -AT_CHECK([grep -q "invalid arguments" stderr]) > > - > > -AT_CHECK([ovs-ofctl ct-flush br0 zone=1 'ct_nw_src=10.1.1.1' > 'ct_nw_dst=10.1.1.1' invalid], [1], [ignore], [stderr]) > > -AT_CHECK([grep -q "command takes at most 4 arguments" stderr]) > > +AT_CHECK([FLUSH_CMD mark=invalid], [ignore], [ignore], [stderr]) > > +AT_CHECK([grep -q "failed to parse mark" stderr]) > > > > -AT_CHECK([ovs-ofctl ct-flush br0 'ct_nw_src=10.1.1.1' > 'ct_nw_dst=10.1.1.1' invalid], [1], [ignore], [stderr]) > > -AT_CHECK([grep -q "invalid arguments" stderr]) > > +AT_CHECK([FLUSH_CMD labels=invalid], [ignore], [ignore], [stderr]) > > +AT_CHECK([grep -q "failed to parse labels" stderr]) > > +]) > > > > OVS_TRAFFIC_VSWITCHD_STOP > > AT_CLEANUP > > diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in > > index 0a611b2ee..9995895ca 100644 > > --- a/utilities/ovs-ofctl.8.in > > +++ b/utilities/ovs-ofctl.8.in > > @@ -296,17 +296,20 @@ Flushes the connection tracking entries in > \fIzone\fR on \fIswitch\fR. > > This command uses an Open vSwitch extension that is only in Open > > vSwitch 2.6 and later. > > . > > -.IP "\fBct\-flush \fIswitch [zone=N] [ct-orig-tuple [ct-reply-tuple]]\fR > > -Flushes the connection entries on \fIswitch\fR based on \fIzone\fR and > > -connection tracking tuples \fIct-[orig|reply]-tuple\fR. > > +.IP "\fBct\-flush \fIswitch [zone=N] [zone=N] [mark=X[/M]] > [labels=Y[/N]] [ct-orig-tuple [ct-reply-tuple]]\fR > > The zone is repeated twice. > > > +Flushes the connection entries on \fIswitch\fR based on \fIzone\fR, > > +\fImark\fR, \fIlabels\fR and connection tracking tuples > > +\fIct-[orig|reply]-tuple\fR. > > .IP > > If \fIct-[orig|reply]-tuple\fR is not provided, flushes all the > connection > > entries. If \fIzone\fR is specified, only flushes the connections in > > -\fIzone\fR. > > +\fIzone\fR. if \fImark\fR or \fIlabels\fR is provided, it will flush > > +only entries that are matching specific \fImark/labels\fR. > > .IP > > If \fIct-[orig|reply]-tuple\fR is provided, flushes the connection entry > > specified by \fIct-[orig|reply]-tuple\fR in \fIzone\fR. The zone > defaults > > -to 0 if it is not provided. The userspace connection tracker requires > flushing > > +to 0 if it is not provided. The \fImark\fR and \fIlabel\fR defaults to > "0/0" > > label*s* > > > +if it is not provided. The userspace connection tracker requires > flushing > > with the original pre-NATed tuple and a warning log will be otherwise > > generated. The tuple can be partial and will remove all connections > that are > > matching on the specified fields. In order to specify only > > diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c > > index 79d42dd0b..de734e9f5 100644 > > --- a/utilities/ovs-ofctl.c > > +++ b/utilities/ovs-ofctl.c > > @@ -5092,8 +5092,9 @@ static const struct ovs_cmdl_command > all_commands[] = { > > { "ct-flush-zone", "switch zone", > > 2, 2, ofctl_ct_flush_zone, OVS_RO }, > > > > - { "ct-flush", "switch [zone=N] [ct-orig-tuple [ct-reply-tuple]]", > > - 1, 4, ofctl_ct_flush, OVS_RO }, > > + { "ct-flush", "switch [zone=N] [mark=X[/M]] [labels=Y[/N]] " > > + "[ct-orig-tuple [ct-reply-tuple]]", > > + 1, 6, ofctl_ct_flush, OVS_RO }, > > Not an issue of this patch, but these commands should be RW. > I'll address that in a separate patch possible with the UNKNOWN error to make it easily backportable. > Also, you missed the update for usage() function. > > > > > { "ofp-parse", "file", > > 1, 1, ofctl_ofp_parse, OVS_RW }, > > Thanks, Ales -- Ales Musil Senior Software Engineer - OVN Core Red Hat EMEA <https://www.redhat.com> amu...@redhat.com <https://red.ht/sig> _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev