OpenFlow 1.1+ specs encourage switches to verify action consistency
at flow setup time.  Implement this for OpenFlow 1.1+ only to not
break any current OF 1.0 based use.

Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com>
---
 lib/ofp-actions.c          |   61 ++++++++++++++++++++++++++++++++++++++++----
 lib/ofp-actions.h          |    2 +-
 lib/ofp-parse.c            |   43 ++++++++++++++++++++++---------
 lib/ofp-parse.h            |   12 ++++++---
 lib/ofp-util.h             |    1 +
 ofproto/ofproto.c          |   17 +++++++-----
 tests/learn.at             |    2 ++
 tests/ovs-ofctl.at         |   10 ++++++--
 utilities/ovs-controller.c |    2 +-
 utilities/ovs-ofctl.c      |   27 +++++++++++++-------
 10 files changed, 137 insertions(+), 40 deletions(-)

diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index 777677a..f02ba4d 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -1521,7 +1521,7 @@ exit:
 /* May modify flow->dl_type, caller must restore it. */
 static enum ofperr
 ofpact_check__(const struct ofpact *a, struct flow *flow, ofp_port_t max_ports,
-               uint8_t table_id)
+               uint8_t table_id, bool enforce_consistency)
 {
     const struct ofpact_enqueue *enqueue;
 
@@ -1550,15 +1550,40 @@ ofpact_check__(const struct ofpact *a, struct flow 
*flow, ofp_port_t max_ports,
 
     case OFPACT_SET_VLAN_VID:
     case OFPACT_SET_VLAN_PCP:
+        return 0;
+
     case OFPACT_STRIP_VLAN:
+        if (!(flow->vlan_tci & htons(VLAN_CFI))) {
+            goto inconsistent;
+        }
+        return 0;
+
     case OFPACT_PUSH_VLAN:
+        if (flow->vlan_tci & htons(VLAN_CFI)) {
+            /* Multiple VLAN headers not supported. */
+            return OFPERR_OFPBAC_BAD_TAG;
+        }
+        return 0;
+
     case OFPACT_SET_ETH_SRC:
     case OFPACT_SET_ETH_DST:
+        return 0;
+
     case OFPACT_SET_IPV4_SRC:
     case OFPACT_SET_IPV4_DST:
     case OFPACT_SET_IPV4_DSCP:
+        if (flow->dl_type != htons(ETH_TYPE_IP)) {
+            goto inconsistent;
+        }
+        return 0;
+
     case OFPACT_SET_L4_SRC_PORT:
     case OFPACT_SET_L4_DST_PORT:
+        if (!is_ip_any(flow) ||
+            (flow->nw_proto != IPPROTO_TCP && flow->nw_proto != IPPROTO_UDP
+             && flow->nw_proto != IPPROTO_SCTP)) {
+            goto inconsistent;
+        }
         return 0;
 
     case OFPACT_REG_MOVE:
@@ -1574,15 +1599,30 @@ ofpact_check__(const struct ofpact *a, struct flow 
*flow, ofp_port_t max_ports,
         return nxm_stack_pop_check(ofpact_get_STACK_POP(a), flow);
 
     case OFPACT_DEC_TTL:
+        if (!is_ip_any(flow)) {
+            goto inconsistent;
+        }
+        return 0;
+
     case OFPACT_SET_MPLS_TTL:
     case OFPACT_DEC_MPLS_TTL:
+        if (!eth_type_mpls(flow->dl_type)) {
+            goto inconsistent;
+        }
+        return 0;
+
     case OFPACT_SET_TUNNEL:
     case OFPACT_SET_QUEUE:
     case OFPACT_POP_QUEUE:
-    case OFPACT_FIN_TIMEOUT:
     case OFPACT_RESUBMIT:
         return 0;
 
+    case OFPACT_FIN_TIMEOUT:
+        if (flow->nw_proto != IPPROTO_TCP) {
+            goto inconsistent;
+        }
+        return 0;
+
     case OFPACT_LEARN:
         return learn_check(ofpact_get_LEARN(a), flow);
 
@@ -1599,6 +1639,9 @@ ofpact_check__(const struct ofpact *a, struct flow *flow, 
ofp_port_t max_ports,
 
     case OFPACT_POP_MPLS:
         flow->dl_type = ofpact_get_POP_MPLS(a)->ethertype;
+        if (!eth_type_mpls(flow->dl_type)) {
+            goto inconsistent;
+        }
         return 0;
 
     case OFPACT_SAMPLE:
@@ -1610,7 +1653,7 @@ ofpact_check__(const struct ofpact *a, struct flow *flow, 
ofp_port_t max_ports,
     case OFPACT_WRITE_ACTIONS: {
         struct ofpact_nest *on = ofpact_get_WRITE_ACTIONS(a);
         return ofpacts_check(on->actions, ofpact_nest_get_action_len(on),
-                             flow, max_ports, table_id);
+                             flow, max_ports, table_id, enforce_consistency);
     }
 
     case OFPACT_WRITE_METADATA:
@@ -1636,6 +1679,12 @@ ofpact_check__(const struct ofpact *a, struct flow 
*flow, ofp_port_t max_ports,
     default:
         NOT_REACHED();
     }
+
+ inconsistent:
+    if (enforce_consistency) {
+        return OFPERR_OFPBAC_MATCH_INCONSISTENT;
+    }
+    return 0;
 }
 
 /* Checks that the 'ofpacts_len' bytes of actions in 'ofpacts' are
@@ -1645,14 +1694,16 @@ ofpact_check__(const struct ofpact *a, struct flow 
*flow, ofp_port_t max_ports,
  * May temporarily modify 'flow', but restores the changes before returning. */
 enum ofperr
 ofpacts_check(const struct ofpact ofpacts[], size_t ofpacts_len,
-              struct flow *flow, ofp_port_t max_ports, uint8_t table_id)
+              struct flow *flow, ofp_port_t max_ports, uint8_t table_id,
+              bool enforce_consistency)
 {
     const struct ofpact *a;
     ovs_be16 dl_type = flow->dl_type;
     enum ofperr error = 0;
 
     OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
-        error = ofpact_check__(a, flow, max_ports, table_id);
+        error = ofpact_check__(a, flow, max_ports, table_id,
+                               enforce_consistency);
         if (error) {
             break;
         }
diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h
index d6aabf9..199acdf 100644
--- a/lib/ofp-actions.h
+++ b/lib/ofp-actions.h
@@ -547,7 +547,7 @@ enum ofperr ofpacts_pull_openflow11_instructions(struct 
ofpbuf *openflow,
                                                  struct ofpbuf *ofpacts);
 enum ofperr ofpacts_check(const struct ofpact[], size_t ofpacts_len,
                           struct flow *, ofp_port_t max_ports,
-                          uint8_t table_id);
+                          uint8_t table_id, bool enforce_consistency);
 enum ofperr ofpacts_verify(const struct ofpact ofpacts[], size_t ofpacts_len);
 
 /* Converting ofpacts to OpenFlow. */
diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index 17bd7e2..f8fa9eb 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -1131,7 +1131,8 @@ parse_field(const struct mf_field *mf, const char *s, 
struct match *match,
 
 static char * WARN_UNUSED_RESULT
 parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string,
-                enum ofputil_protocol *usable_protocols)
+                enum ofputil_protocol *usable_protocols,
+                bool enforce_consistency)
 {
     enum {
         F_OUT_PORT = 1 << 0,
@@ -1339,10 +1340,21 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int 
command, char *string,
             enum ofperr err;
 
             err = ofpacts_check(ofpacts.data, ofpacts.size, &fm->match.flow,
-                                OFPP_MAX, 0);
+                                OFPP_MAX, 0, true);
             if (err) {
-                error = xasprintf("actions are invalid with specified match "
-                                  "(%s)", ofperr_to_string(err));
+                if (!enforce_consistency &&
+                    err == OFPERR_OFPBAC_MATCH_INCONSISTENT) {
+                    /* Allow inconsistent actions to be used with OF 1.0. */
+                    *usable_protocols &= OFPUTIL_P_OF10_ANY;
+                    /* Try again, allowing for inconsistency.
+                     * XXX: As a side effect, logging may be duplicated. */
+                    err = ofpacts_check(ofpacts.data, ofpacts.size,
+                                        &fm->match.flow, OFPP_MAX, 0, false);
+                }
+                if (err) {
+                    error = xasprintf("actions are invalid with specified 
match "
+                                      "(%s)", ofperr_to_string(err));
+                }
             }
         }
         if (error) {
@@ -1372,12 +1384,14 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int 
command, char *string,
  * error.  The caller is responsible for freeing the returned string. */
 char * WARN_UNUSED_RESULT
 parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
-              enum ofputil_protocol *usable_protocols)
+              enum ofputil_protocol *usable_protocols,
+              bool enforce_consistency)
 {
     char *string = xstrdup(str_);
     char *error;
 
-    error = parse_ofp_str__(fm, command, string, usable_protocols);
+    error = parse_ofp_str__(fm, command, string, usable_protocols,
+                            enforce_consistency);
     if (error) {
         fm->ofpacts = NULL;
         fm->ofpacts_len = 0;
@@ -1724,9 +1738,11 @@ parse_ofpacts(const char *s_, struct ofpbuf *ofpacts,
 char * WARN_UNUSED_RESULT
 parse_ofp_flow_mod_str(struct ofputil_flow_mod *fm, const char *string,
                        uint16_t command,
-                       enum ofputil_protocol *usable_protocols)
+                       enum ofputil_protocol *usable_protocols,
+                       bool enforce_consistency)
 {
-    char *error = parse_ofp_str(fm, command, string, usable_protocols);
+    char *error = parse_ofp_str(fm, command, string, usable_protocols,
+                                enforce_consistency);
     if (!error) {
         /* Normalize a copy of the match.  This ensures that non-normalized
          * flows get logged but doesn't affect what gets sent to the switch, so
@@ -1788,7 +1804,8 @@ parse_ofp_table_mod(struct ofputil_table_mod *tm, const 
char *table_id,
 char * WARN_UNUSED_RESULT
 parse_ofp_flow_mod_file(const char *file_name, uint16_t command,
                         struct ofputil_flow_mod **fms, size_t *n_fms,
-                        enum ofputil_protocol *usable_protocols)
+                        enum ofputil_protocol *usable_protocols,
+                        bool enforce_consistency)
 {
     size_t allocated_fms;
     int line_number;
@@ -1817,7 +1834,7 @@ parse_ofp_flow_mod_file(const char *file_name, uint16_t 
command,
             *fms = x2nrealloc(*fms, &allocated_fms, sizeof **fms);
         }
         error = parse_ofp_flow_mod_str(&(*fms)[*n_fms], ds_cstr(&s), command,
-                                       &usable);
+                                       &usable, enforce_consistency);
         if (error) {
             size_t i;
 
@@ -1849,12 +1866,14 @@ parse_ofp_flow_mod_file(const char *file_name, uint16_t 
command,
 char * WARN_UNUSED_RESULT
 parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *fsr,
                                  bool aggregate, const char *string,
-                                 enum ofputil_protocol *usable_protocols)
+                                 enum ofputil_protocol *usable_protocols,
+                                 bool enforce_consistency)
 {
     struct ofputil_flow_mod fm;
     char *error;
 
-    error = parse_ofp_str(&fm, -1, string, usable_protocols);
+    error = parse_ofp_str(&fm, -1, string, usable_protocols,
+                          enforce_consistency);
     if (error) {
         return error;
     }
diff --git a/lib/ofp-parse.h b/lib/ofp-parse.h
index 515ccd7..58a3e87 100644
--- a/lib/ofp-parse.h
+++ b/lib/ofp-parse.h
@@ -36,12 +36,14 @@ struct simap;
 enum ofputil_protocol;
 
 char *parse_ofp_str(struct ofputil_flow_mod *, int command, const char *str_,
-                    enum ofputil_protocol *usable_protocols)
+                    enum ofputil_protocol *usable_protocols,
+                    bool enforce_consistency)
     WARN_UNUSED_RESULT;
 
 char *parse_ofp_flow_mod_str(struct ofputil_flow_mod *, const char *string,
                              uint16_t command,
-                             enum ofputil_protocol *usable_protocols)
+                             enum ofputil_protocol *usable_protocols,
+                             bool enforce_consistency)
     WARN_UNUSED_RESULT;
 
 char *parse_ofp_table_mod(struct ofputil_table_mod *,
@@ -51,12 +53,14 @@ char *parse_ofp_table_mod(struct ofputil_table_mod *,
 
 char *parse_ofp_flow_mod_file(const char *file_name, uint16_t command,
                               struct ofputil_flow_mod **fms, size_t *n_fms,
-                              enum ofputil_protocol *usable_protocols)
+                              enum ofputil_protocol *usable_protocols,
+                              bool enforce_consistency)
     WARN_UNUSED_RESULT;
 
 char *parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *,
                                        bool aggregate, const char *string,
-                                       enum ofputil_protocol *usable_protocols)
+                                       enum ofputil_protocol *usable_protocols,
+                                       bool enforce_consistency)
     WARN_UNUSED_RESULT;
 
 char *parse_ofpacts(const char *, struct ofpbuf *ofpacts,
diff --git a/lib/ofp-util.h b/lib/ofp-util.h
index 7355559..44e60d8 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
@@ -89,6 +89,7 @@ enum ofputil_protocol {
     OFPUTIL_P_OF10_NXM_TID = 1 << 3,
 #define OFPUTIL_P_OF10_STD_ANY (OFPUTIL_P_OF10_STD | OFPUTIL_P_OF10_STD_TID)
 #define OFPUTIL_P_OF10_NXM_ANY (OFPUTIL_P_OF10_NXM | OFPUTIL_P_OF10_NXM_TID)
+#define OFPUTIL_P_OF10_ANY (OFPUTIL_P_OF10_STD_ANY | OFPUTIL_P_OF10_NXM_ANY)
 
     /* OpenFlow 1.1 protocol.
      *
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 6d625c2..402b38d 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -2823,13 +2823,15 @@ reject_slave_controller(struct ofconn *ofconn)
 static enum ofperr
 ofproto_check_ofpacts(struct ofproto *ofproto,
                       const struct ofpact ofpacts[], size_t ofpacts_len,
-                      struct flow *flow, uint8_t table_id)
+                      struct flow *flow, uint8_t table_id,
+                      bool enforce_consistency)
 {
     enum ofperr error;
     uint32_t mid;
 
     error = ofpacts_check(ofpacts, ofpacts_len, flow,
-                          u16_to_ofp(ofproto->max_ports), table_id);
+                          u16_to_ofp(ofproto->max_ports), table_id,
+                          enforce_consistency);
     if (error) {
         return error;
     }
@@ -2887,7 +2889,8 @@ handle_packet_out(struct ofconn *ofconn, const struct 
ofp_header *oh)
     /* Verify actions against packet, then send packet if successful. */
     in_port_.ofp_port = po.in_port;
     flow_extract(payload, 0, 0, NULL, &in_port_, &flow);
-    error = ofproto_check_ofpacts(p, po.ofpacts, po.ofpacts_len, &flow, 0);
+    error = ofproto_check_ofpacts(p, po.ofpacts, po.ofpacts_len, &flow, 0,
+                                  oh->version > OFP10_VERSION);
     if (!error) {
         error = p->ofproto_class->packet_out(p, payload, &flow,
                                              po.ofpacts, po.ofpacts_len);
@@ -3937,7 +3940,8 @@ add_flow(struct ofproto *ofproto, struct ofconn *ofconn,
 
     /* Verify actions. */
     error = ofproto_check_ofpacts(ofproto, fm->ofpacts, fm->ofpacts_len,
-                                  &fm->match.flow, table_id);
+                                  &fm->match.flow, table_id,
+                                  request && request->version > OFP10_VERSION);
     if (error) {
         cls_rule_destroy(&cr);
         return error;
@@ -4059,9 +4063,10 @@ modify_flows__(struct ofproto *ofproto, struct ofconn 
*ofconn,
             continue;
         }
 
-        /* Verify actions. */
+        /* Verify actions, enforce consistency check on OF1.1+. */
         error = ofpacts_check(fm->ofpacts, fm->ofpacts_len, &fm->match.flow,
-                              u16_to_ofp(ofproto->max_ports), rule->table_id);
+                              u16_to_ofp(ofproto->max_ports), rule->table_id,
+                              request && request->version > OFP10_VERSION);
         if (error) {
             return error;
         }
diff --git a/tests/learn.at b/tests/learn.at
index f99cc3a..7a4bda5 100644
--- a/tests/learn.at
+++ b/tests/learn.at
@@ -75,12 +75,14 @@ AT_CHECK([[ovs-ofctl parse-flow 
'actions=learn(load:5->NXM_OF_IP_DST[])']],
   [1], [], [stderr])
 AT_CHECK([sed -e 's/.*|meta_flow|WARN|//' < stderr], [0],
   [[destination field ip_dst lacks correct prerequisites
+destination field ip_dst lacks correct prerequisites
 ovs-ofctl: actions are invalid with specified match (OFPBAC_MATCH_INCONSISTENT)
 ]], [[]])
 AT_CHECK([[ovs-ofctl parse-flow 
'actions=learn(load:NXM_OF_IP_DST[]->NXM_NX_REG1[])']],
   [1], [], [stderr])
 AT_CHECK([sed -e 's/.*|meta_flow|WARN|//' < stderr], [0],
   [[source field ip_dst lacks correct prerequisites
+source field ip_dst lacks correct prerequisites
 ovs-ofctl: actions are invalid with specified match (OFPBAC_MATCH_INCONSISTENT)
 ]])
 AT_CLEANUP
diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
index cbd6aec..a49213e 100644
--- a/tests/ovs-ofctl.at
+++ b/tests/ovs-ofctl.at
@@ -139,6 +139,12 @@ OFPT_FLOW_MOD: ADD 
actions=sample(probability=12345,collector_set_id=23456,obs_d
 ]])
 AT_CLEANUP
 
+AT_SETUP([ovs-ofctl action inconsistency (OpenFlow 1.1)])
+AT_CHECK([ovs-ofctl --protocols OpenFlow11 add-flow br0 'ip 
actions=mod_tp_dst:1234'
+], [1], [stdout], [ovs-ofctl: actions are invalid with specified match 
(OFPBAC_MATCH_INCONSISTENT)
+])
+AT_CLEANUP
+
 AT_SETUP([ovs-ofctl parse-flows (OpenFlow 1.2)])
 AT_DATA([flows.txt], [[
 # comment
@@ -229,7 +235,7 @@ 
actions=output:1,bundle_load(eth_src,0,hrw,ofport,NXM_NX_REG0[16..31],slaves:1),
 actions=resubmit:1,resubmit(2),resubmit(,3),resubmit(2,3)
 
send_flow_rem,actions=output:1,output:NXM_NX_REG0[],output:2,output:NXM_NX_REG1[16..31],output:3
 check_overlap,actions=output:1,exit,output:2
-actions=fin_timeout(idle_timeout=5,hard_timeout=15)
+tcp,actions=fin_timeout(idle_timeout=5,hard_timeout=15)
 actions=controller(max_len=123,reason=invalid_ttl,id=555)
 
actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
@@ -265,7 +271,7 @@ NXT_FLOW_MOD: ADD table:255 
actions=output:1,bundle_load(eth_src,0,hrw,ofport,NX
 NXT_FLOW_MOD: ADD table:255 
actions=resubmit:1,resubmit:2,resubmit(,3),resubmit(2,3)
 NXT_FLOW_MOD: ADD table:255 send_flow_rem 
actions=output:1,output:NXM_NX_REG0[],output:2,output:NXM_NX_REG1[16..31],output:3
 NXT_FLOW_MOD: ADD table:255 check_overlap actions=output:1,exit,output:2
-NXT_FLOW_MOD: ADD table:255 actions=fin_timeout(idle_timeout=5,hard_timeout=15)
+NXT_FLOW_MOD: ADD table:255 tcp 
actions=fin_timeout(idle_timeout=5,hard_timeout=15)
 NXT_FLOW_MOD: ADD table:255 
actions=controller(reason=invalid_ttl,max_len=123,id=555)
 NXT_FLOW_MOD: ADD table:255 
actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
diff --git a/utilities/ovs-controller.c b/utilities/ovs-controller.c
index f487d8c..9596ad4 100644
--- a/utilities/ovs-controller.c
+++ b/utilities/ovs-controller.c
@@ -332,7 +332,7 @@ parse_options(int argc, char *argv[])
         case OPT_WITH_FLOWS:
             error = parse_ofp_flow_mod_file(optarg, OFPFC_ADD, &default_flows,
                                             &n_default_flows,
-                                            &usable_protocols);
+                                            &usable_protocols, false);
             if (error) {
                 ovs_fatal(0, "%s", error);
             }
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index 630591c..1a1d423 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -889,7 +889,9 @@ prepare_dump_flows(int argc, char *argv[], bool aggregate,
 
     error = parse_ofp_flow_stats_request_str(&fsr, aggregate,
                                              argc > 2 ? argv[2] : "",
-                                             &usable_protocols);
+                                             &usable_protocols,
+                                             !(allowed_protocols
+                                               & OFPUTIL_P_OF10_ANY));
     if (error) {
         ovs_fatal(0, "%s", error);
     }
@@ -1111,7 +1113,8 @@ ofctl_flow_mod_file(int argc OVS_UNUSED, char *argv[], 
uint16_t command)
     char *error;
 
     error = parse_ofp_flow_mod_file(argv[2], command, &fms, &n_fms,
-                                    &usable_protocols);
+                                    &usable_protocols,
+                                    !(allowed_protocols & OFPUTIL_P_OF10_ANY));
     if (error) {
         ovs_fatal(0, "%s", error);
     }
@@ -1130,7 +1133,9 @@ ofctl_flow_mod(int argc, char *argv[], uint16_t command)
         enum ofputil_protocol usable_protocols;
 
         error = parse_ofp_flow_mod_str(&fm, argc > 2 ? argv[2] : "", command,
-                                       &usable_protocols);
+                                       &usable_protocols,
+                                       !(allowed_protocols
+                                         & OFPUTIL_P_OF10_ANY));
         if (error) {
             ovs_fatal(0, "%s", error);
         }
@@ -2205,7 +2210,8 @@ read_flows_from_file(const char *filename, struct 
classifier *cls, int index)
         char *error;
         enum ofputil_protocol usable;
 
-        error = parse_ofp_str(&fm, OFPFC_ADD, ds_cstr(&s), &usable);
+        error = parse_ofp_str(&fm, OFPFC_ADD, ds_cstr(&s), &usable,
+                              !(allowed_protocols & OFPUTIL_P_OF10_ANY));
         if (error) {
             ovs_fatal(0, "%s:%d: %s", filename, line_number, error);
         }
@@ -2624,7 +2630,8 @@ ofctl_parse_flow(int argc OVS_UNUSED, char *argv[])
     struct ofputil_flow_mod fm;
     char *error;
 
-    error = parse_ofp_flow_mod_str(&fm, argv[1], OFPFC_ADD, &usable_protocols);
+    error = parse_ofp_flow_mod_str(&fm, argv[1], OFPFC_ADD, &usable_protocols,
+                                   !(allowed_protocols & OFPUTIL_P_OF10_ANY));
     if (error) {
         ovs_fatal(0, "%s", error);
     }
@@ -2642,7 +2649,8 @@ ofctl_parse_flows(int argc OVS_UNUSED, char *argv[])
     char *error;
 
     error = parse_ofp_flow_mod_file(argv[1], OFPFC_ADD, &fms, &n_fms,
-                                    &usable_protocols);
+                                    &usable_protocols,
+                                    !(allowed_protocols & OFPUTIL_P_OF10_ANY));
     if (error) {
         ovs_fatal(0, "%s", error);
     }
@@ -3042,11 +3050,11 @@ ofctl_parse_ofp11_instructions(int argc OVS_UNUSED, 
char *argv[] OVS_UNUSED)
         error = ofpacts_pull_openflow11_instructions(&of11_in, OFP11_VERSION,
                                                      of11_in.size, &ofpacts);
         if (!error) {
-            /* Verify actions. */
+            /* Verify actions, enforce consistency. */
             struct flow flow;
             memset(&flow, 0, sizeof flow);
             error = ofpacts_check(ofpacts.data, ofpacts.size, &flow, OFPP_MAX,
-                                  table_id ? atoi(table_id) : 0);
+                                  table_id ? atoi(table_id) : 0, true);
         }
         if (error) {
             printf("bad OF1.1 instructions: %s\n\n", ofperr_get_name(error));
@@ -3144,7 +3152,8 @@ ofctl_check_vlan(int argc OVS_UNUSED, char *argv[])
     string_s = match_to_string(&match, OFP_DEFAULT_PRIORITY);
     printf("%s -> ", string_s);
     fflush(stdout);
-    error_s = parse_ofp_str(&fm, -1, string_s, &usable_protocols);
+    error_s = parse_ofp_str(&fm, -1, string_s, &usable_protocols,
+                            !(allowed_protocols & OFPUTIL_P_OF10_ANY));
     if (error_s) {
         ovs_fatal(0, "%s", error_s);
     }
-- 
1.7.10.4

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to