Future patches will need the ability to skip over unsupported NXM
headers.
Signed-off-by: Ethan Jackson <[email protected]>
---
lib/nx-match.c | 59 ++++++++++++++++++++++++++++++++++---------------
lib/nx-match.h | 3 ++
tests/ovs-ofctl.at | 17 +++++++++++++-
utilities/ovs-ofctl.c | 14 +++++++++--
4 files changed, 71 insertions(+), 22 deletions(-)
diff --git a/lib/nx-match.c b/lib/nx-match.c
index a93a693..eaccce1 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -96,18 +96,10 @@ nx_entry_ok(const void *p, unsigned int match_len)
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;
@@ -126,14 +118,19 @@ nx_pull_match(struct ofpbuf *b, unsigned int match_len,
uint16_t priority,
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)) {
@@ -190,13 +187,39 @@ nx_pull_match(struct ofpbuf *b, unsigned int match_len,
uint16_t priority,
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);
+}
/* nx_put_match() and helpers.
*
diff --git a/lib/nx-match.h b/lib/nx-match.h
index c7ee0f8..8931d58 100644
--- a/lib/nx-match.h
+++ b/lib/nx-match.h
@@ -36,6 +36,9 @@ struct nx_action_reg_move;
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);
diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
index d89d398..57712c0 100644
--- a/tests/ovs-ofctl.at
+++ b/tests/ovs-ofctl.at
@@ -370,7 +370,7 @@ NXM_NX_REG0_W(a0e0d050/f0f0f0f0)
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
@@ -565,6 +565,21 @@ nx_pull_match() returned error 44010101 (type
OFPET_BAD_REQUEST, code NXBRC_NXM_
])
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])
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index 044f74c..ec7eee5 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -55,7 +55,9 @@
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
@@ -1539,8 +1541,14 @@ do_parse_nx_match(int argc OVS_UNUSED, char *argv[]
OVS_UNUSED)
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;
--
1.7.7.1
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev