> On Mar 2, 2017, at 5:34 PM, Joe Stringer <[email protected]> wrote:
> 
> On 28 February 2017 at 17:17, Jarno Rajahalme <[email protected] 
> <mailto:[email protected]>> wrote:
>> Supply the match mask to prerequisities checking when available.  This
>> allows checking for zero-valued matches.  Non-zero valued matches
>> imply the presense of corresponding mask bits, but for zero valued
>> matches we must explicitly check the mask, too.
>> 
>> This is required now only for conntrack validity checking due to the
>> conntrack state having and 'invalid' bit, but not 'valid' bit.  One
>> way to match an valid conntrack state is to match on the 'tracked' bit
>> being one and 'invalid' bit being zero.  The latter requires the
>> corresponding mask bit be verified.
>> 
>> Signed-off-by: Jarno Rajahalme <[email protected]>
>> ---
>> include/openvswitch/meta-flow.h   |  5 ++--
>> include/openvswitch/ofp-actions.h |  4 ++--
>> lib/bundle.c                      |  4 ++--
>> lib/bundle.h                      |  3 ++-
>> lib/learn.c                       | 15 ++++++------
>> lib/learn.h                       |  3 ++-
>> lib/meta-flow.c                   | 38 ++++++++++++++++++++++-------
>> lib/multipath.c                   |  4 ++--
>> lib/multipath.h                   |  3 ++-
>> lib/nx-match.c                    | 17 ++++++-------
>> lib/nx-match.h                    |  6 ++---
>> lib/ofp-actions.c                 | 50 
>> ++++++++++++++++++++-------------------
>> lib/ofp-parse.c                   |  2 +-
>> lib/ofp-util.c                    |  2 +-
>> ofproto/ofproto-dpif-trace.c      | 13 +++++-----
>> ofproto/ofproto.c                 |  5 ++--
>> utilities/ovs-ofctl.c             |  6 ++---
>> 17 files changed, 105 insertions(+), 75 deletions(-)
>> 
>> diff --git a/include/openvswitch/meta-flow.h 
>> b/include/openvswitch/meta-flow.h
>> index 83e2599..aac9945 100644
>> --- a/include/openvswitch/meta-flow.h
>> +++ b/include/openvswitch/meta-flow.h
>> @@ -1898,6 +1898,7 @@ void mf_get_mask(const struct mf_field *, const struct 
>> flow_wildcards *,
>> /* Prerequisites. */
>> bool mf_are_prereqs_ok(const struct mf_field *mf, const struct flow *flow,
>>                        struct flow_wildcards *wc);
>> +bool mf_are_match_prereqs_ok(const struct mf_field *, const struct match *);
>> 
>> static inline bool
>> mf_is_l3_or_higher(const struct mf_field *mf)
>> @@ -1959,8 +1960,8 @@ void mf_subfield_swap(const struct mf_subfield *,
>>                       const struct mf_subfield *,
>>                       struct flow *flow, struct flow_wildcards *);
>> 
>> -enum ofperr mf_check_src(const struct mf_subfield *, const struct flow *);
>> -enum ofperr mf_check_dst(const struct mf_subfield *, const struct flow *);
>> +enum ofperr mf_check_src(const struct mf_subfield *, const struct match *);
>> +enum ofperr mf_check_dst(const struct mf_subfield *, const struct match *);
>> 
>> /* Parsing and formatting. */
>> char *mf_parse(const struct mf_field *, const char *,
> 
> I assume that the above is OK from a library standpoint because we are
> not currently guaranteeing that APIs remain stable between release
> versions, only within the minor revisions of a particular release. IE,
> library users compiling against libopenvswitch from 2.7 will need to
> change their code to compile against libopenvswitch from 2.8.
> 

I did not remember this, but seems all right to me.

>> diff --git a/include/openvswitch/ofp-actions.h 
>> b/include/openvswitch/ofp-actions.h
>> index 88f573d..53d6b44 100644
>> --- a/include/openvswitch/ofp-actions.h
>> +++ b/include/openvswitch/ofp-actions.h
>> @@ -954,11 +954,11 @@ ofpacts_pull_openflow_instructions(struct ofpbuf 
>> *openflow,
>>                                    const struct vl_mff_map *vl_mff_map,
>>                                    struct ofpbuf *ofpacts);
>> enum ofperr ofpacts_check(struct ofpact[], size_t ofpacts_len,
>> -                          struct flow *, ofp_port_t max_ports,
>> +                          struct match *, ofp_port_t max_ports,
>>                           uint8_t table_id, uint8_t n_tables,
>>                           enum ofputil_protocol *usable_protocols);
>> enum ofperr ofpacts_check_consistency(struct ofpact[], size_t ofpacts_len,
>> -                                      struct flow *, ofp_port_t max_ports,
>> +                                      struct match *, ofp_port_t max_ports,
>>                                       uint8_t table_id, uint8_t n_tables,
>>                                       enum ofputil_protocol 
>> usable_protocols);
>> enum ofperr ofpact_check_output_port(ofp_port_t port, ofp_port_t max_ports);
>> diff --git a/lib/bundle.c b/lib/bundle.c
>> index 70a743b..620318e 100644
>> --- a/lib/bundle.c
>> +++ b/lib/bundle.c
>> @@ -105,13 +105,13 @@ bundle_execute(const struct ofpact_bundle *bundle,
>> 
>> enum ofperr
>> bundle_check(const struct ofpact_bundle *bundle, ofp_port_t max_ports,
>> -             const struct flow *flow)
>> +             const struct match *match)
>> {
>>     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
>>     size_t i;
>> 
>>     if (bundle->dst.field) {
>> -        enum ofperr error = mf_check_dst(&bundle->dst, flow);
>> +        enum ofperr error = mf_check_dst(&bundle->dst, match);
>>         if (error) {
>>             return error;
>>         }
>> diff --git a/lib/bundle.h b/lib/bundle.h
>> index f5ce321..48b9b79 100644
>> --- a/lib/bundle.h
>> +++ b/lib/bundle.h
>> @@ -29,6 +29,7 @@
>> struct ds;
>> struct flow;
>> struct flow_wildcards;
>> +struct match;
>> struct ofpact_bundle;
>> struct ofpbuf;
>> 
>> @@ -43,7 +44,7 @@ ofp_port_t bundle_execute(const struct ofpact_bundle *, 
>> const struct flow *,
>>                         bool (*slave_enabled)(ofp_port_t ofp_port, void 
>> *aux),
>>                         void *aux);
>> enum ofperr bundle_check(const struct ofpact_bundle *, ofp_port_t max_ports,
>> -                         const struct flow *);
>> +                         const struct match *);
>> char *bundle_parse(const char *, struct ofpbuf *ofpacts) 
>> OVS_WARN_UNUSED_RESULT;
>> char *bundle_parse_load(const char *, struct ofpbuf *ofpacts)
>>     OVS_WARN_UNUSED_RESULT;
>> diff --git a/lib/learn.c b/lib/learn.c
>> index ce52c35..1990849 100644
>> --- a/lib/learn.c
>> +++ b/lib/learn.c
>> @@ -35,18 +35,18 @@
>> /* Checks that 'learn' is a valid action on 'flow'.  Returns 0 if it is 
>> valid,
>>  * otherwise an OFPERR_*. */
>> enum ofperr
>> -learn_check(const struct ofpact_learn *learn, const struct flow *flow)
>> +learn_check(const struct ofpact_learn *learn, const struct match *src_match)
>> {
>>     const struct ofpact_learn_spec *spec;
>> -    struct match match;
>> +    struct match dst_match;
>> 
>> -    match_init_catchall(&match);
>> +    match_init_catchall(&dst_match);
>>     OFPACT_LEARN_SPEC_FOR_EACH (spec, learn) {
>>         enum ofperr error;
>> 
>>         /* Check the source. */
>>         if (spec->src_type == NX_LEARN_SRC_FIELD) {
>> -            error = mf_check_src(&spec->src, flow);
>> +            error = mf_check_src(&spec->src, src_match);
>>             if (error) {
>>                 return error;
>>             }
>> @@ -55,18 +55,19 @@ learn_check(const struct ofpact_learn *learn, const 
>> struct flow *flow)
>>         /* Check the destination. */
>>         switch (spec->dst_type) {
>>         case NX_LEARN_DST_MATCH:
>> -            error = mf_check_src(&spec->dst, &match.flow);
>> +            error = mf_check_src(&spec->dst, &dst_match);
>>             if (error) {
>>                 return error;
>>             }
>>             if (spec->src_type & NX_LEARN_SRC_IMMEDIATE) {
>>                 mf_write_subfield_value(&spec->dst,
>> -                                        ofpact_learn_spec_imm(spec), 
>> &match);
>> +                                        ofpact_learn_spec_imm(spec),
>> +                                        &dst_match);
>>             }
>>             break;
>> 
>>         case NX_LEARN_DST_LOAD:
>> -            error = mf_check_dst(&spec->dst, &match.flow);
>> +            error = mf_check_dst(&spec->dst, &dst_match);
>>             if (error) {
>>                 return error;
>>             }
>> diff --git a/lib/learn.h b/lib/learn.h
>> index adbbdf3..9dd41d3 100644
>> --- a/lib/learn.h
>> +++ b/lib/learn.h
>> @@ -23,6 +23,7 @@
>> struct ds;
>> struct flow;
>> struct flow_wildcards;
>> +struct match;
>> struct ofpbuf;
>> struct ofpact_learn;
>> struct ofputil_flow_mod;
>> @@ -33,7 +34,7 @@ struct nx_action_learn;
>>  * See lib/ofp-actions.c for NXAST_LEARN specification.
>>  */
>> 
>> -enum ofperr learn_check(const struct ofpact_learn *, const struct flow *);
>> +enum ofperr learn_check(const struct ofpact_learn *, const struct match *);
>> void learn_execute(const struct ofpact_learn *, const struct flow *,
>>                    struct ofputil_flow_mod *, struct ofpbuf *ofpacts);
>> void learn_mask(const struct ofpact_learn *, struct flow_wildcards *);
>> diff --git a/lib/meta-flow.c b/lib/meta-flow.c
>> index 40704e6..9d635a3 100644
>> --- a/lib/meta-flow.c
>> +++ b/lib/meta-flow.c
>> @@ -379,10 +379,12 @@ mf_is_mask_valid(const struct mf_field *mf, const 
>> union mf_value *mask)
>> }
>> 
>> /* Returns true if 'flow' meets the prerequisites for 'mf', false otherwise.
>> + * If a non-NULL 'mask' is passed, zero-valued matches can also be verified.
>>  * Sets inspected bits in 'wc', if non-NULL. */
>> -bool
>> -mf_are_prereqs_ok(const struct mf_field *mf, const struct flow *flow,
>> -                  struct flow_wildcards *wc)
>> +static bool
>> +mf_are_prereqs_ok__(const struct mf_field *mf, const struct flow *flow,
>> +                    const struct flow_wildcards *mask OVS_UNUSED,
>> +                    struct flow_wildcards *wc)
>> {
>>     switch (mf->prereqs) {
>>     case MFP_NONE:
>> @@ -401,6 +403,7 @@ mf_are_prereqs_ok(const struct mf_field *mf, const 
>> struct flow *flow,
>>     case MFP_IP_ANY:
>>         return is_ip_any(flow);
>>     case MFP_TCP:
>> +        /* Matching !FRAG_LATER is not enforced (mask is not checked). */
>>         return is_tcp(flow, wc) && !(flow->nw_frag & FLOW_NW_FRAG_LATER);
>>     case MFP_UDP:
>>         return is_udp(flow, wc) && !(flow->nw_frag & FLOW_NW_FRAG_LATER);
>> @@ -421,6 +424,23 @@ mf_are_prereqs_ok(const struct mf_field *mf, const 
>> struct flow *flow,
>>     OVS_NOT_REACHED();
>> }
>> 
>> +/* Returns true if 'flow' meets the prerequisites for 'mf', false otherwise.
>> + * Sets inspected bits in 'wc', if non-NULL. */
>> +bool
>> +mf_are_prereqs_ok(const struct mf_field *mf, const struct flow *flow,
>> +                  struct flow_wildcards *wc)
>> +{
>> +    return mf_are_prereqs_ok__(mf, flow, NULL, wc);
>> +}
>> +
>> +/* Returns true if 'match' meets the prerequisites for 'mf', false 
>> otherwise.
>> + */
>> +bool
>> +mf_are_match_prereqs_ok(const struct mf_field *mf, const struct match 
>> *match)
>> +{
>> +    return mf_are_prereqs_ok__(mf, &match->flow, &match->wc, NULL);
>> +}
>> +
>> /* Returns true if 'value' may be a valid value *as part of a masked match*,
>>  * false otherwise.
>>  *
>> @@ -1948,7 +1968,7 @@ mf_set(const struct mf_field *mf,
>> }
>> 
>> static enum ofperr
>> -mf_check__(const struct mf_subfield *sf, const struct flow *flow,
>> +mf_check__(const struct mf_subfield *sf, const struct match *match,
>>            const char *type)
>> {
>>     if (!sf->field) {
>> @@ -1966,7 +1986,7 @@ mf_check__(const struct mf_subfield *sf, const struct 
>> flow *flow,
>>                      "of %s field %s", sf->ofs, sf->n_bits,
>>                      sf->field->n_bits, type, sf->field->name);
>>         return OFPERR_OFPBAC_BAD_SET_LEN;
>> -    } else if (flow && !mf_are_prereqs_ok(sf->field, flow, NULL)) {
>> +    } else if (match && !mf_are_match_prereqs_ok(sf->field, match)) {
>>         VLOG_WARN_RL(&rl, "%s field %s lacks correct prerequisites",
>>                      type, sf->field->name);
>>         return OFPERR_OFPBAC_MATCH_INCONSISTENT;
>> @@ -2053,18 +2073,18 @@ mf_subfield_swap(const struct mf_subfield *a,
>>  * 0 if so, otherwise an OpenFlow error code (e.g. as returned by
>>  * ofp_mkerr()).  */
>> enum ofperr
>> -mf_check_src(const struct mf_subfield *sf, const struct flow *flow)
>> +mf_check_src(const struct mf_subfield *sf, const struct match *match)
>> {
>> -    return mf_check__(sf, flow, "source");
>> +    return mf_check__(sf, match, "source");
>> }
>> 
>> /* Checks whether 'sf' is valid for writing a subfield into 'flow'.  Returns >> 0
>>  * if so, otherwise an OpenFlow error code (e.g. as returned by
>>  * ofp_mkerr()). */
>> enum ofperr
>> -mf_check_dst(const struct mf_subfield *sf, const struct flow *flow)
>> +mf_check_dst(const struct mf_subfield *sf, const struct match *match)
>> {
>> -    int error = mf_check__(sf, flow, "destination");
>> +    int error = mf_check__(sf, match, "destination");
>>     if (!error && !sf->field->writable) {
>>         VLOG_WARN_RL(&rl, "destination field %s is not writable",
>>                      sf->field->name);
>> diff --git a/lib/multipath.c b/lib/multipath.c
>> index 8a1d1fa..e855a88 100644
>> --- a/lib/multipath.c
>> +++ b/lib/multipath.c
>> @@ -35,9 +35,9 @@
>>  * OFPERR_*. */
>> enum ofperr
>> multipath_check(const struct ofpact_multipath *mp,
>> -                const struct flow *flow)
>> +                const struct match *match)
>> {
>> -    return mf_check_dst(&mp->dst, flow);
>> +    return mf_check_dst(&mp->dst, match);
>> }
>> 
>> /* multipath_execute(). */
>> diff --git a/lib/multipath.h b/lib/multipath.h
>> index 6dd3785..4158302 100644
>> --- a/lib/multipath.h
>> +++ b/lib/multipath.h
>> @@ -24,6 +24,7 @@
>> struct ds;
>> struct flow;
>> struct flow_wildcards;
>> +struct match;
>> struct nx_action_multipath;
>> struct ofpact_multipath;
>> struct ofpbuf;
>> @@ -31,7 +32,7 @@ struct ofpbuf;
>> /* NXAST_MULTIPATH helper functions. */
>> 
>> enum ofperr multipath_check(const struct ofpact_multipath *,
>> -                            const struct flow *);
>> +                            const struct match *);
>> 
>> void multipath_execute(const struct ofpact_multipath *, struct flow *,
>>                        struct flow_wildcards *);
>> diff --git a/lib/nx-match.c b/lib/nx-match.c
>> index 91401e2..95516a1 100644
>> --- a/lib/nx-match.c
>> +++ b/lib/nx-match.c
>> @@ -539,7 +539,7 @@ nx_pull_raw(const uint8_t *p, unsigned int match_len, 
>> bool strict,
>>                 *cookie = value.be64;
>>                 *cookie_mask = mask.be64;
>>             }
>> -        } else if (!mf_are_prereqs_ok(field, &match->flow, NULL)) {
>> +        } else if (!mf_are_match_prereqs_ok(field, match)) {
>>             error = OFPERR_OFPBMC_BAD_PREREQ;
>>         } else if (!mf_is_all_wild(field, &match->wc)) {
>>             error = OFPERR_OFPBMC_DUP_FIELD;
>> @@ -1663,16 +1663,17 @@ nxm_format_reg_move(const struct ofpact_reg_move 
>> *move, struct ds *s)
>> 
>> 
>> enum ofperr
>> -nxm_reg_move_check(const struct ofpact_reg_move *move, const struct flow 
>> *flow)
>> +nxm_reg_move_check(const struct ofpact_reg_move *move,
>> +                   const struct match *match)
>> {
>>     enum ofperr error;
>> 
>> -    error = mf_check_src(&move->src, flow);
>> +    error = mf_check_src(&move->src, match);
>>     if (error) {
>>         return error;
>>     }
>> 
>> -    return mf_check_dst(&move->dst, flow);
>> +    return mf_check_dst(&move->dst, match);
>> }
>> 
>> /* nxm_execute_reg_move(). */
>> @@ -1734,16 +1735,16 @@ nxm_format_stack_pop(const struct ofpact_stack *pop, 
>> struct ds *s)
>> 
>> enum ofperr
>> nxm_stack_push_check(const struct ofpact_stack *push,
>> -                     const struct flow *flow)
>> +                     const struct match *match)
>> {
>> -    return mf_check_src(&push->subfield, flow);
>> +    return mf_check_src(&push->subfield, match);
>> }
>> 
>> enum ofperr
>> nxm_stack_pop_check(const struct ofpact_stack *pop,
>> -                    const struct flow *flow)
>> +                    const struct match *match)
>> {
>> -    return mf_check_dst(&pop->subfield, flow);
>> +    return mf_check_dst(&pop->subfield, match);
>> }
>> 
>> /* nxm_execute_stack_push(), nxm_execute_stack_pop().
>> diff --git a/lib/nx-match.h b/lib/nx-match.h
>> index 5dca24a..631ab48 100644
>> --- a/lib/nx-match.h
>> +++ b/lib/nx-match.h
>> @@ -116,7 +116,7 @@ char *nxm_parse_reg_move(struct ofpact_reg_move *, const 
>> char *)
>> void nxm_format_reg_move(const struct ofpact_reg_move *, struct ds *);
>> 
>> enum ofperr nxm_reg_move_check(const struct ofpact_reg_move *,
>> -                               const struct flow *);
>> +                               const struct match *);
>> 
>> void nxm_reg_load(const struct mf_subfield *, uint64_t src_data,
>>                   struct flow *, struct flow_wildcards *);
>> @@ -128,9 +128,9 @@ void nxm_format_stack_push(const struct ofpact_stack *, 
>> struct ds *);
>> void nxm_format_stack_pop(const struct ofpact_stack *, struct ds *);
>> 
>> enum ofperr nxm_stack_push_check(const struct ofpact_stack *,
>> -                                 const  struct flow *);
>> +                                 const  struct match *);
>> enum ofperr nxm_stack_pop_check(const struct ofpact_stack *,
>> -                               const struct flow *);
>> +                                const struct match *);
>> void nx_stack_push(struct ofpbuf *stack, const void *v, uint8_t bytes);
>> void nx_stack_push_bottom(struct ofpbuf *stack, const void *v, uint8_t 
>> bytes);
>> void *nx_stack_pop(struct ofpbuf *stack, uint8_t *bytes);
>> diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
>> index ce80f57..2869e0f 100644
>> --- a/lib/ofp-actions.c
>> +++ b/lib/ofp-actions.c
>> @@ -7065,9 +7065,10 @@ inconsistent_match(enum ofputil_protocol 
>> *usable_protocols)
>>  * without context. */
>> static enum ofperr
>> ofpact_check__(enum ofputil_protocol *usable_protocols, struct ofpact *a,
>> -               struct flow *flow, ofp_port_t max_ports,
>> +               struct match *match, ofp_port_t max_ports,
>>                uint8_t table_id, uint8_t n_tables)
>> {
>> +    struct flow *flow = &match->flow;
>>     const struct ofpact_enqueue *enqueue;
>>     const struct mf_field *mf;
>> 
>> @@ -7089,14 +7090,14 @@ ofpact_check__(enum ofputil_protocol 
>> *usable_protocols, struct ofpact *a,
>>         return 0;
>> 
>>     case OFPACT_OUTPUT_REG:
>> -        return mf_check_src(&ofpact_get_OUTPUT_REG(a)->src, flow);
>> +        return mf_check_src(&ofpact_get_OUTPUT_REG(a)->src, match);
>> 
>>     case OFPACT_OUTPUT_TRUNC:
>>         return ofpact_check_output_port(ofpact_get_OUTPUT_TRUNC(a)->port,
>>                                         max_ports);
>> 
>>     case OFPACT_BUNDLE:
>> -        return bundle_check(ofpact_get_BUNDLE(a), max_ports, flow);
>> +        return bundle_check(ofpact_get_BUNDLE(a), max_ports, match);
>> 
>>     case OFPACT_SET_VLAN_VID:
>>         /* Remember if we saw a vlan tag in the flow to aid translating to
>> @@ -7179,7 +7180,7 @@ ofpact_check__(enum ofputil_protocol 
>> *usable_protocols, struct ofpact *a,
>>         return 0;
>> 
>>     case OFPACT_REG_MOVE:
>> -        return nxm_reg_move_check(ofpact_get_REG_MOVE(a), flow);
>> +        return nxm_reg_move_check(ofpact_get_REG_MOVE(a), match);
>> 
>>     case OFPACT_SET_FIELD:
>>         mf = ofpact_get_SET_FIELD(a)->field;
>> @@ -7202,10 +7203,10 @@ ofpact_check__(enum ofputil_protocol 
>> *usable_protocols, struct ofpact *a,
>>         return 0;
>> 
>>     case OFPACT_STACK_PUSH:
>> -        return nxm_stack_push_check(ofpact_get_STACK_PUSH(a), flow);
>> +        return nxm_stack_push_check(ofpact_get_STACK_PUSH(a), match);
>> 
>>     case OFPACT_STACK_POP:
>> -        return nxm_stack_pop_check(ofpact_get_STACK_POP(a), flow);
>> +        return nxm_stack_pop_check(ofpact_get_STACK_POP(a), match);
>> 
>>     case OFPACT_SET_MPLS_LABEL:
>>     case OFPACT_SET_MPLS_TC:
>> @@ -7229,13 +7230,13 @@ ofpact_check__(enum ofputil_protocol 
>> *usable_protocols, struct ofpact *a,
>>         return 0;
>> 
>>     case OFPACT_LEARN:
>> -        return learn_check(ofpact_get_LEARN(a), flow);
>> +        return learn_check(ofpact_get_LEARN(a), match);
>> 
>>     case OFPACT_CONJUNCTION:
>>         return 0;
>> 
>>     case OFPACT_MULTIPATH:
>> -        return multipath_check(ofpact_get_MULTIPATH(a), flow);
>> +        return multipath_check(ofpact_get_MULTIPATH(a), match);
>> 
>>     case OFPACT_NOTE:
>>     case OFPACT_EXIT:
>> @@ -7262,7 +7263,7 @@ ofpact_check__(enum ofputil_protocol 
>> *usable_protocols, struct ofpact *a,
>>     case OFPACT_CLONE: {
>>         struct ofpact_nest *on = ofpact_get_CLONE(a);
>>         return ofpacts_check(on->actions, ofpact_nest_get_action_len(on),
>> -                             flow, max_ports, table_id, n_tables,
>> +                             match, max_ports, table_id, n_tables,
>>                              usable_protocols);
>>     }
>> 
>> @@ -7280,11 +7281,11 @@ ofpact_check__(enum ofputil_protocol 
>> *usable_protocols, struct ofpact *a,
>>         }
>> 
>>         if (oc->zone_src.field) {
>> -            return mf_check_src(&oc->zone_src, flow);
>> +            return mf_check_src(&oc->zone_src, match);
>>         }
>> 
>>         return ofpacts_check(oc->actions, ofpact_ct_get_action_len(oc),
>> -                             flow, max_ports, table_id, n_tables,
>> +                             match, max_ports, table_id, n_tables,
>>                              usable_protocols);
>>     }
>> 
>> @@ -7312,7 +7313,7 @@ ofpact_check__(enum ofputil_protocol 
>> *usable_protocols, struct ofpact *a,
>>         struct ofpact_nest *on = ofpact_get_WRITE_ACTIONS(a);
>>         enum ofputil_protocol p = *usable_protocols;
>>         return ofpacts_check(on->actions, ofpact_nest_get_action_len(on),
>> -                             flow, max_ports, table_id, n_tables, &p);
>> +                             match, max_ports, table_id, n_tables, &p);
>>     }
>> 
>>     case OFPACT_WRITE_METADATA:
>> @@ -7360,32 +7361,33 @@ ofpact_check__(enum ofputil_protocol 
>> *usable_protocols, struct ofpact *a,
>>  * example of an inconsistency between match and actions is a flow that does
>>  * not match on an MPLS Ethertype but has an action that pops an MPLS label.)
>>  *
>> - * May annotate ofpacts with information gathered from the 'flow'.
>> + * May annotate ofpacts with information gathered from the 'match'.
>>  *
>> - * May temporarily modify 'flow', but restores the changes before 
>> returning. */
>> + * May temporarily modify 'match', but restores the changes before
>> + * returning. */
>> enum ofperr
>> ofpacts_check(struct ofpact ofpacts[], size_t ofpacts_len,
>> -              struct flow *flow, ofp_port_t max_ports,
>> +              struct match *match, ofp_port_t max_ports,
>>               uint8_t table_id, uint8_t n_tables,
>>               enum ofputil_protocol *usable_protocols)
>> {
>>     struct ofpact *a;
>> -    ovs_be16 dl_type = flow->dl_type;
>> -    ovs_be16 vlan_tci = flow->vlan_tci;
>> -    uint8_t nw_proto = flow->nw_proto;
>> +    ovs_be16 dl_type = match->flow.dl_type;
>> +    ovs_be16 vlan_tci = match->flow.vlan_tci;
>> +    uint8_t nw_proto = match->flow.nw_proto;
>>     enum ofperr error = 0;
>> 
>>     OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
>> -        error = ofpact_check__(usable_protocols, a, flow,
>> +        error = ofpact_check__(usable_protocols, a, match,
>>                                max_ports, table_id, n_tables);
>>         if (error) {
>>             break;
>>         }
>>     }
>>     /* Restore fields that may have been modified. */
>> -    flow->dl_type = dl_type;
>> -    flow->vlan_tci = vlan_tci;
>> -    flow->nw_proto = nw_proto;
>> +    match->flow.dl_type = dl_type;
>> +    match->flow.vlan_tci = vlan_tci;
>> +    match->flow.nw_proto = nw_proto;
>>     return error;
>> }
>> 
>> @@ -7393,14 +7395,14 @@ ofpacts_check(struct ofpact ofpacts[], size_t 
>> ofpacts_len,
>>  * OFPERR_OFPBAC_MATCH_INCONSISTENT rather than clearing bits. */
>> enum ofperr
>> ofpacts_check_consistency(struct ofpact ofpacts[], size_t ofpacts_len,
>> -                          struct flow *flow, ofp_port_t max_ports,
>> +                          struct match *match, ofp_port_t max_ports,
>>                           uint8_t table_id, uint8_t n_tables,
>>                           enum ofputil_protocol usable_protocols)
>> {
>>     enum ofputil_protocol p = usable_protocols;
>>     enum ofperr error;
>> 
>> -    error = ofpacts_check(ofpacts, ofpacts_len, flow, max_ports,
>> +    error = ofpacts_check(ofpacts, ofpacts_len, match, max_ports,
>>                           table_id, n_tables, &p);
>>     return (error ? error
>>             : p != usable_protocols ? OFPERR_OFPBAC_MATCH_INCONSISTENT
>> diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
>> index a6b9fcf..7826bc5 100644
>> --- a/lib/ofp-parse.c
>> +++ b/lib/ofp-parse.c
>> @@ -546,7 +546,7 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int 
>> command, char *string,
>>         if (!error) {
>>             enum ofperr err;
>> 
>> -            err = ofpacts_check(ofpacts.data, ofpacts.size, &fm->match.flow,
>> +            err = ofpacts_check(ofpacts.data, ofpacts.size, &fm->match,
>>                                 OFPP_MAX, fm->table_id, 255, 
>> usable_protocols);
>>             if (!err && !*usable_protocols) {
>>                 err = OFPERR_OFPBAC_MATCH_INCONSISTENT;
>> diff --git a/lib/ofp-util.c b/lib/ofp-util.c
>> index 0c9343e..7d40cbb 100644
>> --- a/lib/ofp-util.c
>> +++ b/lib/ofp-util.c
>> @@ -1751,7 +1751,7 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
>>     }
>> 
>>     return ofpacts_check_consistency(fm->ofpacts, fm->ofpacts_len,
>> -                                     &fm->match.flow, max_port,
>> +                                     &fm->match, max_port,
>>                                      fm->table_id, max_table, protocol);
>> }
>> 
>> diff --git a/ofproto/ofproto-dpif-trace.c b/ofproto/ofproto-dpif-trace.c
>> index b01a131..a5cc089 100644
>> --- a/ofproto/ofproto-dpif-trace.c
>> +++ b/ofproto/ofproto-dpif-trace.c
>> @@ -324,7 +324,7 @@ ofproto_unixctl_trace_actions(struct unixctl_conn *conn, 
>> int argc,
>>     struct ofpbuf ofpacts;
>>     struct dp_packet *packet;
>>     struct ds result;
>> -    struct flow flow;
>> +    struct match match;
>>     uint16_t in_port;
>> 
>>     /* Three kinds of error return values! */
>> @@ -354,12 +354,13 @@ ofproto_unixctl_trace_actions(struct unixctl_conn 
>> *conn, int argc,
>>         enforce_consistency = false;
>>     }
>> 
>> -    error = parse_flow_and_packet(argc, argv, &ofproto, &flow, &packet);
>> +    error = parse_flow_and_packet(argc, argv, &ofproto, &match.flow, 
>> &packet);
>>     if (error) {
>>         unixctl_command_reply_error(conn, error);
>>         free(error);
>>         goto exit;
>>     }
>> +    match_wc_init(&match, &match.flow);
> 
> Inside match_wc_init(), this ends up copying the entire flow from the
> current memory into itself - should we avoid that?
> 

I don’t this this matters for the trace, but we could change the match_init_* 
functions skipping copies between identical addresses?

  Jarno

>> 
>>     /* Do the same checks as handle_packet_out() in ofproto.c.
>>      *
>> @@ -371,18 +372,18 @@ ofproto_unixctl_trace_actions(struct unixctl_conn 
>> *conn, int argc,
>>      *
>>      * We skip the "meter" check here because meter is an instruction, not an
>>      * action, and thus cannot appear in ofpacts. */
>> -    in_port = ofp_to_u16(flow.in_port.ofp_port);
>> +    in_port = ofp_to_u16(match.flow.in_port.ofp_port);
>>     if (in_port >= ofproto->up.max_ports && in_port < ofp_to_u16(OFPP_MAX)) {
>>         unixctl_command_reply_error(conn, "invalid in_port");
>>         goto exit;
>>     }
>>     if (enforce_consistency) {
>> -        retval = ofpacts_check_consistency(ofpacts.data, ofpacts.size, 
>> &flow,
>> +        retval = ofpacts_check_consistency(ofpacts.data, ofpacts.size, 
>> &match,
>>                                            u16_to_ofp(ofproto->up.max_ports),
>>                                            0, ofproto->up.n_tables,
>>                                            usable_protocols);
>>     } else {
>> -        retval = ofpacts_check(ofpacts.data, ofpacts.size, &flow,
>> +        retval = ofpacts_check(ofpacts.data, ofpacts.size, &match,
>>                                u16_to_ofp(ofproto->up.max_ports), 0,
>>                                ofproto->up.n_tables, &usable_protocols);
>>     }
>> @@ -398,7 +399,7 @@ ofproto_unixctl_trace_actions(struct unixctl_conn *conn, 
>> int argc,
>>         goto exit;
>>     }
>> 
>> -    ofproto_trace(ofproto, &flow, packet,
>> +    ofproto_trace(ofproto, &match.flow, packet,
>>                   ofpacts.data, ofpacts.size, &result);
>>     unixctl_command_reply(conn, ds_cstr(&result));
>> 
>> diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
>> index ef4b1d9..35ec31d 100644
>> --- a/ofproto/ofproto.c
>> +++ b/ofproto/ofproto.c
>> @@ -3447,6 +3447,7 @@ ofproto_packet_out_init(struct ofproto *ofproto,
>>                         const struct ofputil_packet_out *po)
>> {
>>     enum ofperr error;
>> +    struct match match;
>> 
>>     if (ofp_to_u16(po->in_port) >= ofproto->max_ports
>>         && ofp_to_u16(po->in_port) < ofp_to_u16(OFPP_MAX)) {
>> @@ -3471,8 +3472,8 @@ ofproto_packet_out_init(struct ofproto *ofproto,
>>      * actions aren't in any table.  This is OK as 'table_id' is only used to
>>      * check instructions (e.g., goto-table), which can't appear on the 
>> action
>>      * list of a packet-out. */
>> -    error = ofpacts_check_consistency(po->ofpacts, po->ofpacts_len,
>> -                                      opo->flow,
>> +    match_wc_init(&match, opo->flow);
>> +    error = ofpacts_check_consistency(po->ofpacts, po->ofpacts_len, &match,
>>                                       u16_to_ofp(ofproto->max_ports), 0,
>>                                       ofproto->n_tables,
>>                                       ofconn_get_protocol(ofconn));
>> diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
>> index 77332e0..e317242 100644
>> --- a/utilities/ovs-ofctl.c
>> +++ b/utilities/ovs-ofctl.c
>> @@ -3880,12 +3880,12 @@ ofctl_parse_actions__(const char *version_s, bool 
>> instructions)
>>         if (!error && instructions) {
>>             /* Verify actions, enforce consistency. */
>>             enum ofputil_protocol protocol;
>> -            struct flow flow;
>> +            struct match match;
>> 
>> -            memset(&flow, 0, sizeof flow);
>> +            memset(&match, 0, sizeof match);
>>             protocol = ofputil_protocols_from_ofp_version(version);
>>             error = ofpacts_check_consistency(ofpacts.data, ofpacts.size,
>> -                                              &flow, OFPP_MAX,
>> +                                              &match, OFPP_MAX,
>>                                               table_id ? atoi(table_id) : 0,
>>                                               OFPTT_MAX + 1, protocol);
>>         }
>> --
>> 2.1.4
>> 
>> _______________________________________________
>> dev mailing list
>> [email protected] <mailto:[email protected]>
>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev 
>> <https://mail.openvswitch.org/mailman/listinfo/ovs-dev>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to