return header;
}
-/* Parses the nx_match formatted match description in 'b' with length
- * 'match_len'. The results are stored in 'rule', which is initialized
- * with 'priority'. If 'cookie' and 'cookie_mask' contain valid
- * pointers, then the cookie and mask will be stored in them if a
- * "NXM_NX_COOKIE*" match is defined. Otherwise, 0 is stored in both.
- *
- * Returns 0 if successful, otherwise an OpenFlow error code.
- */
-int
-nx_pull_match(struct ofpbuf *b, unsigned int match_len, uint16_t priority,
- struct cls_rule *rule,
- ovs_be64 *cookie, ovs_be64 *cookie_mask)
+static int
+nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict,
+ uint16_t priority, struct cls_rule *rule,
+ ovs_be64 *cookie, ovs_be64 *cookie_mask)
{
uint32_t header;
uint8_t *p;
if (cookie) {
*cookie = *cookie_mask = htonll(0);
}
- while ((header = nx_entry_ok(p, match_len)) != 0) {
- unsigned length = NXM_LENGTH(header);
+ for (;
+ (header = nx_entry_ok(p, match_len)) != 0;
+ p += 4 + NXM_LENGTH(header), match_len -= 4 + NXM_LENGTH(header)) {
const struct mf_field *mf;
int error;
mf = mf_from_nxm_header(header);
if (!mf) {
- error = NXM_BAD_TYPE;
+ if (strict) {
+ error = NXM_BAD_TYPE;
+ } else {
+ continue;
+ }
} else if (!mf_are_prereqs_ok(mf, &rule->flow)) {
error = NXM_BAD_PREREQ;
} else if (!mf_is_all_wild(mf, &rule->wc)) {
return error;
}
-
- p += 4 + length;
- match_len -= 4 + length;
}
return match_len ? NXM_INVALID : 0;
}
+
+/* Parses the nx_match formatted match description in 'b' with length
+ * 'match_len'. The results are stored in 'rule', which is initialized with
+ * 'priority'. If 'cookie' and 'cookie_mask' contain valid pointers, then the
+ * cookie and mask will be stored in them if a "NXM_NX_COOKIE*" match is
+ * defined. Otherwise, 0 is stored in both.
+ *
+ * Fails with an error when encountering unknown NXM headers.
+ *
+ * Returns 0 if successful, otherwise an OpenFlow error code. */
+int
+nx_pull_match(struct ofpbuf *b, unsigned int match_len,
+ uint16_t priority, struct cls_rule *rule,
+ ovs_be64 *cookie, ovs_be64 *cookie_mask)
+{
+ return nx_pull_match__(b, match_len, true, priority, rule, cookie,
+ cookie_mask);
+}
+
+/* Behaves the same as nx_pull_match() with one exception. Skips over unknown
+ * NXM headers instead of failing with an error when they are encountered. */
+int
+nx_pull_match_loose(struct ofpbuf *b, unsigned int match_len,
+ uint16_t priority, struct cls_rule *rule,
+ ovs_be64 *cookie, ovs_be64 *cookie_mask)
+{
+ return nx_pull_match__(b, match_len, false, priority, rule, cookie,
+ cookie_mask);
+}
\f
/* nx_put_match() and helpers.
*
int nx_pull_match(struct ofpbuf *, unsigned int match_len, uint16_t priority,
struct cls_rule *, ovs_be64 *cookie, ovs_be64 *cookie_mask);
+int nx_pull_match_loose(struct ofpbuf *, unsigned int match_len,
+ uint16_t priority, struct cls_rule *,
+ ovs_be64 *cookie, ovs_be64 *cookie_mask);
int nx_put_match(struct ofpbuf *, const struct cls_rule *,
ovs_be64 cookie, ovs_be64 cookie_mask);
00011e04(12345678)
00011f08(12345678/12345678)
])
-AT_CHECK([ovs-ofctl parse-nx-match < nx-match.txt], [0], [dnl
+AT_CHECK([ovs-ofctl --strict parse-nx-match < nx-match.txt], [0], [dnl
<any>
# in port
])
AT_CLEANUP
+AT_SETUP([ovs-ofctl parse-nx-match loose])
+AT_KEYWORDS([nx-match])
+AT_DATA([nx-match.txt], [dnl
+NXM_OF_IN_PORT(0001), 01020304(1111/2222), NXM_OF_ETH_TYPE(0800)
+])
+
+AT_CHECK([ovs-ofctl --strict parse-nx-match < nx-match.txt], [0], [dnl
+nx_pull_match() returned error 44010101 (type OFPET_BAD_REQUEST, code NXBRC_NXM_BAD_TYPE)
+])
+
+AT_CHECK([ovs-ofctl parse-nx-match < nx-match.txt], [0], [dnl
+NXM_OF_IN_PORT(0001), NXM_OF_ETH_TYPE(0800)
+])
+AT_CLEANUP
+
dnl Check that "-F openflow10" rejects a flow_mod with a tun_id, since
dnl OpenFlow 1.0 doesn't support tunnels.
AT_SETUP([ovs-ofctl -F option and tun_id])
VLOG_DEFINE_THIS_MODULE(ofctl);
-/* --strict: Use strict matching for flow mod commands? */
+/* --strict: Use strict matching for flow mod commands? Additionally governs
+ * use of nx_pull_match() instead of nx_pull_match_loose() in parse-nx-match.
+ */
static bool strict;
/* --readd: If ture, on replace-flows, re-add even flows that have not changed
match_len = nx_match_from_string(ds_cstr(&in), &nx_match);
/* Convert nx_match to cls_rule. */
- error = nx_pull_match(&nx_match, match_len, 0, &rule,
- &cookie, &cookie_mask);
+ if (strict) {
+ error = nx_pull_match(&nx_match, match_len, 0, &rule,
+ &cookie, &cookie_mask);
+ } else {
+ error = nx_pull_match_loose(&nx_match, match_len, 0, &rule,
+ &cookie, &cookie_mask);
+ }
+
if (!error) {
char *out;