From 102ce76655b4f99f7e3697011ca983c617a9f5ee Mon Sep 17 00:00:00 2001 From: Ethan Jackson Date: Tue, 3 Jan 2012 13:30:45 -0800 Subject: [PATCH] nx-match: New function nx_pull_match_loose(). Future patches will need the ability to skip over unsupported NXM headers. Signed-off-by: Ethan Jackson --- 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 a93a6939b..eaccce12f 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 c7ee0f8d2..8931d58a2 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 d89d3981b..57712c063 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 # 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 044f74cca..ec7eee505 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; -- 2.43.0