On 28 February 2017 at 17:17, Jarno Rajahalme <[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.

> 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?

>
>      /* 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]
> 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