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 <ho...@verge.net.au> --- v4 * Pad is needed even if match is zero length (what was I thinking?!) v3 * Initial post --- lib/nx-match.c | 32 ++++++++++++++++++++------------ lib/nx-match.h | 9 +++++---- lib/ofp-util.c | 17 +++++++++-------- utilities/ovs-ofctl.c | 7 ++++--- 4 files changed, 38 insertions(+), 27 deletions(-) diff --git a/lib/nx-match.c b/lib/nx-match.c index eb055dd..1c6d5dc 100644 --- a/lib/nx-match.c +++ b/lib/nx-match.c @@ -89,9 +89,14 @@ nx_entry_ok(const void *p, unsigned int match_len) return header; } +static size_t padded_match_len(size_t match_len, size_t hdr_len) +{ + return ROUND_UP(match_len + hdr_len, 8) - hdr_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; @@ -99,7 +104,7 @@ nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict, assert((cookie != NULL) == (cookie_mask != NULL)); - p = ofpbuf_try_pull(b, ROUND_UP(match_len, 8)); + p = ofpbuf_try_pull(b, 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 " @@ -203,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. @@ -485,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 +595,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 = padded_match_len(match_len, hdr_len) - match_len; + ofpbuf_put_zeros(b, pad_len); return match_len; } @@ -725,7 +733,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 +790,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 495178b..1d7fad5 100644 --- a/lib/nx-match.h +++ b/lib/nx-match.h @@ -41,16 +41,17 @@ struct nx_action_reg_move; */ 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 3713c03..ee0cb34 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -1624,8 +1624,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; } @@ -1780,7 +1781,7 @@ ofputil_decode_nxst_flow_request(struct ofputil_flow_stats_request *fsr, enum ofperr error; 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; @@ -1986,7 +1987,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; } @@ -2168,8 +2169,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; } @@ -2278,8 +2279,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; } diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 838ba00..6a65dc1 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -1924,17 +1924,18 @@ do_parse_nxm__(bool oxm) ovs_be64 cookie, cookie_mask; enum ofperr error; int match_len; + size_t hdr_len = oxm ? sizeof(struct ofp11_match_header) : 0; /* 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, hdr_len); /* 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, hdr_len, 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, hdr_len, 0, &rule, &cookie, &cookie_mask); } -- 1.7.10.2.484.gcd07cc5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev