[ovs-dev] [PATCH 12/21] lib: Check match and action prerequisities with 'match'.

Jarno Rajahalme jarno at ovn.org
Fri Feb 24 00:19:19 UTC 2017


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 <jarno at ovn.org>
---
 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 *,
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);
 
     /* 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



More information about the dev mailing list