nx-match: New function nx_pull_match_loose().
authorEthan Jackson <ethan@nicira.com>
Tue, 3 Jan 2012 21:30:45 +0000 (13:30 -0800)
committerEthan Jackson <ethan@nicira.com>
Tue, 10 Jan 2012 22:30:15 +0000 (14:30 -0800)
Future patches will need the ability to skip over unsupported NXM
headers.

Signed-off-by: Ethan Jackson <ethan@nicira.com>
lib/nx-match.c
lib/nx-match.h
tests/ovs-ofctl.at
utilities/ovs-ofctl.c

index a93a693..eaccce1 100644 (file)
@@ -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);
+}
 \f
 /* nx_put_match() and helpers.
  *
index c7ee0f8..8931d58 100644 (file)
@@ -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);
 
index d89d398..57712c0 100644 (file)
@@ -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])
index 044f74c..ec7eee5 100644 (file)
@@ -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;