aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJarno Rajahalme <jrajahalme@nicira.com>2013-10-23 12:52:57 -0700
committerBen Pfaff <blp@nicira.com>2013-10-23 13:52:24 -0700
commit8621547cc94ad91018ac0b662427a6fa20165a8d (patch)
tree52e4fd6338df1772d17a00ce99448eb99229f8a4
parentdba70df0cba19228f2751ad0c28d75ab422306e2 (diff)
lib/ofp-actions: Enforce action consistency.
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 <jrajahalme@nicira.com> Signed-off-by: Ben Pfaff <blp@nicira.com>
-rw-r--r--lib/ofp-actions.c63
-rw-r--r--lib/ofp-actions.h2
-rw-r--r--lib/ofp-parse.c43
-rw-r--r--lib/ofp-parse.h12
-rw-r--r--lib/ofp-util.h1
-rw-r--r--ofproto/ofproto.c17
-rw-r--r--tests/learn.at2
-rw-r--r--tests/ovs-ofctl.at10
-rw-r--r--utilities/ovs-controller.c2
-rw-r--r--utilities/ovs-ofctl.c27
10 files changed, 138 insertions, 41 deletions
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index ae63d008..cccd6b17 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -1541,7 +1541,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;
@@ -1570,17 +1570,48 @@ 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:
+ if (flow->dl_type != htons(ETH_TYPE_IP)) {
+ goto inconsistent;
+ }
+ return 0;
+
case OFPACT_SET_IP_DSCP:
case OFPACT_SET_IP_ECN:
case OFPACT_SET_IP_TTL:
+ case OFPACT_DEC_TTL:
+ if (!is_ip_any(flow)) {
+ 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:
@@ -1595,16 +1626,25 @@ ofpact_check__(const struct ofpact *a, struct flow *flow, ofp_port_t max_ports,
case OFPACT_STACK_POP:
return nxm_stack_pop_check(ofpact_get_STACK_POP(a), flow);
- case OFPACT_DEC_TTL:
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);
@@ -1621,6 +1661,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:
@@ -1632,7 +1675,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, false);
}
case OFPACT_WRITE_METADATA:
@@ -1658,6 +1701,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
@@ -1667,14 +1716,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 f7e35402..e097468b 100644
--- a/lib/ofp-actions.h
+++ b/lib/ofp-actions.h
@@ -565,7 +565,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 a4b6d2e0..757b9716 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -1152,7 +1152,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,
@@ -1360,10 +1361,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) {
@@ -1393,12 +1405,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;
@@ -1745,9 +1759,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
@@ -1809,7 +1825,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;
@@ -1838,7 +1855,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;
@@ -1870,12 +1887,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 515ccd70..58a3e87d 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 1afdce00..1f778082 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 6d625c2a..402b38d0 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 f99cc3a1..7a4bda5f 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 f4ca4d59..131beaf8 100644
--- a/tests/ovs-ofctl.at
+++ b/tests/ovs-ofctl.at
@@ -213,6 +213,12 @@ OFPT_FLOW_MOD (OF1.2): ADD table:255 actions=sample(probability=12345,collector_
]])
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 (With Tunnel-Parameters)])
AT_DATA([flows.txt], [[
tun_id=0x1234000056780000/0xffff0000ffff0000,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=0x3,tun_ttl=20,tun_flags=key|csum actions=drop
@@ -266,7 +272,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)
]])
@@ -302,7 +308,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 f487d8ce..9596ad4a 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 630591c1..1a1d4236 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);
}