[ovs-dev] [PATCH] nx-match: Take into account leading header when calculating pad

Simon Horman horms at verge.net.au
Fri Jul 20 01:29:36 UTC 2012


In the case of Open Flow 1.2, which is currently the only
time that OXM is be used, there is a 4 byte header before
the match which needs to be taken into account when calculating
the pad length.

This is not entirely pretty, but it does seem to be correct.

Signed-off-by: Simon Horman <horms at verge.net.au>

---

v7
* Correct the parse-oxm sub-command of ovs-ofputil
  Rebase onto upstream master branch

v6
* No change

v5
* Move nx_padded_match_len into nx-match.h as it will
  be used by code outside of nx-match.c added by subsequent patches.

v4
* Pad is needed even if match is zero length
  (what was I thinking?!)

v3
* Initial post

fix
---
 lib/nx-match.c        | 29 ++++++++++++++++-------------
 lib/nx-match.h        | 14 ++++++++++----
 lib/ofp-util.c        | 21 +++++++++++----------
 utilities/ovs-ofctl.c |  7 ++++---
 4 files changed, 41 insertions(+), 30 deletions(-)

diff --git a/lib/nx-match.c b/lib/nx-match.c
index 0f67692..9fdfaa4 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -91,8 +91,8 @@ nx_entry_ok(const void *p, unsigned int match_len)
 }
 
 static enum ofperr
-nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict,
-                uint16_t priority, struct cls_rule *rule,
+nx_pull_match__(struct ofpbuf *b, unsigned int match_len, size_t hdr_len,
+                bool strict, uint16_t priority, struct cls_rule *rule,
                 ovs_be64 *cookie, ovs_be64 *cookie_mask)
 {
     uint32_t header;
@@ -104,11 +104,11 @@ nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict,
     if (cookie) {
         *cookie = *cookie_mask = htonll(0);
     }
-    if (!match_len) {
+    if (!nx_padded_match_len(match_len, hdr_len)) {
         return 0;
     }
 
-    p = ofpbuf_try_pull(b, ROUND_UP(match_len, 8));
+    p = ofpbuf_try_pull(b, nx_padded_match_len(match_len, hdr_len));
     if (!p) {
         VLOG_DBG_RL(&rl, "nx_match length %u, rounded up to a "
                     "multiple of 8, is longer than space in message (max "
@@ -208,23 +208,23 @@ nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict,
  *
  * Returns 0 if successful, otherwise an OpenFlow error code. */
 enum ofperr
-nx_pull_match(struct ofpbuf *b, unsigned int match_len,
+nx_pull_match(struct ofpbuf *b, unsigned int match_len, size_t hdr_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);
+    return nx_pull_match__(b, match_len, hdr_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. */
 enum ofperr
-nx_pull_match_loose(struct ofpbuf *b, unsigned int match_len,
+nx_pull_match_loose(struct ofpbuf *b, unsigned int match_len, size_t hdr_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);
+    return nx_pull_match__(b, match_len, hdr_len, false, priority, rule,
+                           cookie, cookie_mask);
 }
 
 /* nx_put_match() and helpers.
@@ -490,6 +490,7 @@ nx_put_match(struct ofpbuf *b, bool oxm, const struct cls_rule *cr,
     const flow_wildcards_t wc = cr->wc.wildcards;
     const struct flow *flow = &cr->flow;
     const size_t start_len = b->size;
+    size_t pad_len, hdr_len;
     int match_len;
     int i;
 
@@ -589,7 +590,9 @@ nx_put_match(struct ofpbuf *b, bool oxm, const struct cls_rule *cr,
     nxm_put_64m(b, NXM_NX_COOKIE, cookie, cookie_mask);
 
     match_len = b->size - start_len;
-    ofpbuf_put_zeros(b, ROUND_UP(match_len, 8) - match_len);
+    hdr_len = oxm ? sizeof(struct ofp11_match_header) : 0;
+    pad_len = nx_padded_match_len(match_len, hdr_len) - match_len;
+    ofpbuf_put_zeros(b, pad_len);
     return match_len;
 }
 
@@ -725,7 +728,7 @@ parse_nxm_field_name(const char *name, int name_len)
 /* nx_match_from_string(). */
 
 int
-nx_match_from_string(const char *s, struct ofpbuf *b)
+nx_match_from_string(const char *s, struct ofpbuf *b, size_t hdr_len)
 {
     const char *full_s = s;
     const size_t start_len = b->size;
@@ -782,7 +785,7 @@ nx_match_from_string(const char *s, struct ofpbuf *b)
     }
 
     match_len = b->size - start_len;
-    ofpbuf_put_zeros(b, ROUND_UP(match_len, 8) - match_len);
+    ofpbuf_put_zeros(b, ROUND_UP(match_len + hdr_len, 8) - match_len - hdr_len);
     return match_len;
 }
 
diff --git a/lib/nx-match.h b/lib/nx-match.h
index 161733f..1048d5c 100644
--- a/lib/nx-match.h
+++ b/lib/nx-match.h
@@ -40,17 +40,23 @@ struct nx_action_reg_move;
  * See include/openflow/nicira-ext.h for NXM specification.
  */
 
+static inline size_t nx_padded_match_len(size_t match_len, size_t hdr_len)
+{
+    return ROUND_UP(match_len + hdr_len, 8) - hdr_len;
+}
+
 enum ofperr nx_pull_match(struct ofpbuf *, unsigned int match_len,
-                          uint16_t priority, struct cls_rule *,
+                          size_t hdr_len, uint16_t priority, struct cls_rule *,
                           ovs_be64 *cookie, ovs_be64 *cookie_mask);
 enum ofperr nx_pull_match_loose(struct ofpbuf *, unsigned int match_len,
-                                uint16_t priority, struct cls_rule *,
-                                ovs_be64 *cookie, ovs_be64 *cookie_mask);
+                                size_t hdr_len, uint16_t priority,
+                                struct cls_rule *, ovs_be64 *cookie,
+                                ovs_be64 *cookie_mask);
 int nx_put_match(struct ofpbuf *, bool oxm, const struct cls_rule *,
                  ovs_be64 cookie, ovs_be64 cookie_mask);
 
 char *nx_match_to_string(const uint8_t *, unsigned int match_len);
-int nx_match_from_string(const char *, struct ofpbuf *);
+int nx_match_from_string(const char *, struct ofpbuf *, size_t hdr_len);
 
 void nxm_parse_reg_move(struct ofpact_reg_move *, const char *);
 void nxm_parse_reg_load(struct ofpact_reg_load *, const char *);
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index faa0687..dcca64c 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -1731,8 +1731,9 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
 
         /* Dissect the message. */
         nfm = ofpbuf_pull(&b, sizeof *nfm);
-        error = nx_pull_match(&b, ntohs(nfm->match_len), ntohs(nfm->priority),
-                              &fm->cr, &fm->cookie, &fm->cookie_mask);
+        error = nx_pull_match(&b, ntohs(nfm->match_len), 0,
+                              ntohs(nfm->priority), &fm->cr,
+                              &fm->cookie, &fm->cookie_mask);
         if (error) {
             return error;
         }
@@ -1893,7 +1894,7 @@ ofputil_decode_nxst_flow_request(struct ofputil_flow_stats_request *fsr,
     ofpbuf_use_const(&b, oh, ntohs(oh->length));
 
     nfsr = ofpbuf_pull(&b, sizeof *nfsr);
-    error = nx_pull_match(&b, ntohs(nfsr->match_len), 0, &fsr->match,
+    error = nx_pull_match(&b, ntohs(nfsr->match_len), 0, 0, &fsr->match,
                           &fsr->cookie, &fsr->cookie_mask);
     if (error) {
         return error;
@@ -2104,7 +2105,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs,
                          "claims invalid length %zu", match_len, length);
             return EINVAL;
         }
-        if (nx_pull_match(msg, match_len, ntohs(nfs->priority), &fs->rule,
+        if (nx_pull_match(msg, match_len, 0, ntohs(nfs->priority), &fs->rule,
                           NULL, NULL)) {
             return EINVAL;
         }
@@ -2285,8 +2286,8 @@ ofputil_decode_flow_removed(struct ofputil_flow_removed *fr,
         ofpbuf_use_const(&b, oh, ntohs(oh->length));
 
         nfr = ofpbuf_pull(&b, sizeof *nfr);
-        error = nx_pull_match(&b, ntohs(nfr->match_len), ntohs(nfr->priority),
-                              &fr->rule, NULL, NULL);
+        error = nx_pull_match(&b, ntohs(nfr->match_len), 0,
+                              ntohs(nfr->priority), &fr->rule, NULL, NULL);
         if (error) {
             return error;
         }
@@ -2395,8 +2396,8 @@ ofputil_decode_packet_in(struct ofputil_packet_in *pin,
         ofpbuf_use_const(&b, oh, ntohs(oh->length));
 
         npi = ofpbuf_pull(&b, sizeof *npi);
-        error = nx_pull_match_loose(&b, ntohs(npi->match_len), 0, &rule, NULL,
-                                    NULL);
+        error = nx_pull_match_loose(&b, ntohs(npi->match_len), 0, 0,
+                                    &rule, NULL, NULL);
         if (error) {
             return error;
         }
@@ -3170,7 +3171,7 @@ ofputil_decode_flow_monitor_request(struct ofputil_flow_monitor_request *rq,
     rq->out_port = ntohs(nfmr->out_port);
     rq->table_id = nfmr->table_id;
 
-    return nx_pull_match(msg, ntohs(nfmr->match_len), OFP_DEFAULT_PRIORITY,
+    return nx_pull_match(msg, ntohs(nfmr->match_len), 0, OFP_DEFAULT_PRIORITY,
                          &rq->match, NULL, NULL);
 }
 
@@ -3277,7 +3278,7 @@ ofputil_decode_flow_update(struct ofputil_flow_update *update,
         update->table_id = nfuf->table_id;
         update->cookie = nfuf->cookie;
 
-        error = nx_pull_match(msg, match_len, ntohs(nfuf->priority),
+        error = nx_pull_match(msg, match_len, 0, ntohs(nfuf->priority),
                               update->match, NULL, NULL);
         if (error) {
             return error;
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index 39c3dae..b1d4f0c 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -2180,17 +2180,18 @@ ofctl_parse_nxm__(bool oxm)
 
         /* Convert string to nx_match. */
         ofpbuf_init(&nx_match, 0);
-        match_len = nx_match_from_string(ds_cstr(&in), &nx_match);
+        match_len = nx_match_from_string(ds_cstr(&in), &nx_match, 0);
 
         /* Convert nx_match to cls_rule. */
         if (strict) {
-            error = nx_pull_match(&nx_match, match_len, 0, &rule,
+            error = nx_pull_match(&nx_match, match_len, 0, 0, &rule,
                                   &cookie, &cookie_mask);
         } else {
-            error = nx_pull_match_loose(&nx_match, match_len, 0, &rule,
+            error = nx_pull_match_loose(&nx_match, match_len, 0, 0, &rule,
                                         &cookie, &cookie_mask);
         }
 
+
         if (!error) {
             char *out;
 
-- 
1.7.10.2.484.gcd07cc5




More information about the dev mailing list