On Mon, Jul 23, 2012 at 03:16:32PM +0900, Simon Horman wrote: > 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 complicates nx_match pull and put somewhat. > > This patch takes an approach suggested by Ben Pfaff to separate the > encoding of the match and the adding of padding and, in the case of OXM, > a header. > > Signed-off-by: Simon Horman <ho...@verge.net.au> > > --- > > v7 > * Correct the parse-oxm sub-command of ovs-ofputil > * Separate raw match encoding and header/pad encoding > * Change subject from "nx-match: Take into account leading header when > calculating pad" > > 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 > > Conflicts: > lib/nx-match.c > > wip > --- > lib/nx-match.c | 241 > ++++++++++++++++++++++++++++++++++++++++++++------ > lib/nx-match.h | 17 +++- > lib/ofp-util.c | 30 +++---- > utilities/ovs-ofctl.c | 40 ++++++--- > 4 files changed, 272 insertions(+), 56 deletions(-) > > diff --git a/lib/nx-match.c b/lib/nx-match.c > index 2498b9b..c49ebdb 100644 > --- a/lib/nx-match.c > +++ b/lib/nx-match.c > @@ -91,12 +91,11 @@ 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, > - ovs_be64 *cookie, ovs_be64 *cookie_mask) > +nx_pull_raw(const uint8_t *p, 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; > > assert((cookie != NULL) == (cookie_mask != NULL)); > > @@ -108,14 +107,6 @@ nx_pull_match__(struct ofpbuf *b, unsigned int > match_len, bool strict, > return 0; > } > > - p = ofpbuf_try_pull(b, ROUND_UP(match_len, 8)); > - if (!p) { > - VLOG_DBG_RL(&rl, "nx_match length %u, rounded up to a " > - "multiple of 8, is longer than space in message (max " > - "length %zu)", match_len, b->size); > - return OFPERR_OFPBMC_BAD_LEN; > - } > - > for (; > (header = nx_entry_ok(p, match_len)) != 0; > p += 4 + NXM_LENGTH(header), match_len -= 4 + NXM_LENGTH(header)) { > @@ -198,6 +189,27 @@ nx_pull_match__(struct ofpbuf *b, unsigned int > match_len, bool strict, > return match_len ? OFPERR_OFPBMC_BAD_LEN : 0; > } > > +static enum ofperr > +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) > +{ > + uint8_t *p = NULL; > + > + if (match_len) { > + p = ofpbuf_try_pull(b, ROUND_UP(match_len, 8)); > + if (!p) { > + VLOG_DBG_RL(&rl, "nx_match length %u, rounded up to a " > + "multiple of 8, is longer than space in message (max > " > + "length %zu)", match_len, b->size); > + return OFPERR_OFPBMC_BAD_LEN; > + } > + } > + > + return nx_pull_raw(p, match_len, strict, priority, rule, > + cookie, cookie_mask); > +} > + > /* 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 > @@ -212,8 +224,8 @@ 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); > + 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 > @@ -223,8 +235,68 @@ 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); > + return nx_pull_match__(b, match_len, false, priority, rule, > + cookie, cookie_mask); > +} > + > +static enum ofperr > +oxm_pull_match__(struct ofpbuf *b, bool strict, > + uint16_t priority, struct cls_rule *rule, > + ovs_be64 *cookie, ovs_be64 *cookie_mask) > +{ > + struct ofp11_match_header *omh = b->data; > + uint8_t *p; > + uint16_t match_len; > + > + if (b->size < sizeof *omh) { > + return OFPERR_OFPBMC_BAD_LEN; > + } > + > + match_len = ntohs(omh->length); > + if (match_len < sizeof *omh) { > + return OFPERR_OFPBMC_BAD_LEN; > + } > + > + if (omh->type != htons(OFPMT_OXM)) { > + return OFPERR_OFPBMC_BAD_TYPE; > + } > + > + p = ofpbuf_try_pull(b, ROUND_UP(match_len, 8)); > + if (!p) { > + VLOG_DBG_RL(&rl, "oxm length %u, rounded up to a " > + "multiple of 8, is longer than space in message (max " > + "length %zu)", match_len, b->size); > + return OFPERR_OFPBMC_BAD_LEN; > + } > + > + return nx_pull_raw(p + sizeof *omh, match_len - sizeof *omh, > + strict, priority, rule, cookie, cookie_mask); > +} > + > +/* Parses the oxm formatted match description preceeded by a struct > + * ofp11_match 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 OXM headers. > + * > + * Returns 0 if successful, otherwise an OpenFlow error code. */ > +enum ofperr > +oxm_pull_match(struct ofpbuf *b, uint16_t priority, struct cls_rule *rule, > + ovs_be64 *cookie, ovs_be64 *cookie_mask) > +{ > + return oxm_pull_match__(b, true, priority, rule, cookie, cookie_mask); > +} > + > +/* Behaves the same as oxm_pull_match() with one exception. Skips over > unknown > + * PXM headers instead of failing with an error when they are encountered. */ > +enum ofperr > +oxm_pull_match_loose(struct ofpbuf *b, uint16_t priority, struct cls_rule > *rule, > + ovs_be64 *cookie, ovs_be64 *cookie_mask) > +{ > + return oxm_pull_match__(b, false, priority, rule, cookie, cookie_mask); > }
I wonder if the cookie and cookie_mack parameters should be removed from oxm_pull_match(), oxm_pull_match_loose() and oxm_put_match() (below) as cookie is an NXM match that is not present in OXM. > > /* nx_put_match() and helpers. > @@ -472,10 +544,9 @@ nxm_put_ip(struct ofpbuf *b, const struct cls_rule *cr, > } > > /* Appends to 'b' the nx_match format that expresses 'cr' (except for > - * 'cr->priority', because priority is not part of nx_match), plus enough > - * zero bytes to pad the nx_match out to a multiple of 8. For Flow Mod > - * and Flow Stats Requests messages, a 'cookie' and 'cookie_mask' may be > - * supplied. Otherwise, 'cookie_mask' should be zero. > + * 'cr->priority', because priority is not part of nx_match). > + * For Flow Mod * and Flow Stats Requests messages, a 'cookie' and > + * 'cookie_mask' may be supplied. Otherwise, 'cookie_mask' should be zero. > * > * This function can cause 'b''s data to be reallocated. > * > @@ -483,9 +554,9 @@ nxm_put_ip(struct ofpbuf *b, const struct cls_rule *cr, > * > * If 'cr' is a catch-all rule that matches every packet, then this function > * appends nothing to 'b' and returns 0. */ > -int > -nx_put_match(struct ofpbuf *b, bool oxm, const struct cls_rule *cr, > - ovs_be64 cookie, ovs_be64 cookie_mask) > +static int > +nx_put_raw(struct ofpbuf *b, bool oxm, const struct cls_rule *cr, > + ovs_be64 cookie, ovs_be64 cookie_mask) > { > const flow_wildcards_t wc = cr->wc.wildcards; > const struct flow *flow = &cr->flow; > @@ -592,9 +663,65 @@ 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; > + return match_len; > +} > + > + > +/* Appends to 'b' the nx_match format that expresses 'cr' (except for > + * 'cr->priority', because priority is not part of nx_match), plus enough > + * zero bytes to pad the nx_match out to a multiple of 8. For Flow Mod > + * and Flow Stats Requests messages, a 'cookie' and 'cookie_mask' may be > + * supplied. Otherwise, 'cookie_mask' should be zero. > + * > + * This function can cause 'b''s data to be reallocated. > + * > + * Returns the number of bytes appended to 'b', excluding padding. > + * > + * If 'cr' is a catch-all rule that matches every packet, then this function > + * appends nothing to 'b' and returns 0. */ > +int > +nx_put_match(struct ofpbuf *b, const struct cls_rule *cr, > + ovs_be64 cookie, ovs_be64 cookie_mask) > +{ > + int match_len = nx_put_raw(b, false, cr, cookie, cookie_mask); > + > + ofpbuf_put_zeros(b, ROUND_UP(match_len, 8) - match_len); > + return match_len; > +} > + > + > +/* Appends to 'b' an struct ofp11_match_header followed by the oxm format > that > + * expresses 'cr' (except for 'cr->priority', because priority is not part > + * of nx_match), plus enough zero bytes to pad the data appended out to a > + * multiple of 8. For Flow Mod and Flow Stats Requests messages, a 'cookie' > + * and 'cookie_mask' may be supplied. Otherwise, 'cookie_mask' should be > zero. > + * > + * This function can cause 'b''s data to be reallocated. > + * > + * Returns the number of bytes appended to 'b', excluding the padding. > + * > + * If 'cr' is a catch-all rule that matches every packet, then the function > + * appends a struct ofp11_match_header and padding to 'b' and returns > + * the length of struct ofp11_match_header. */ > +int > +oxm_put_match(struct ofpbuf *b, const struct cls_rule *cr, > + ovs_be64 cookie, ovs_be64 cookie_mask) > +{ > + int match_len; > + struct ofp11_match_header *omh; > + size_t start_len = b->size; > + > + ofpbuf_put_uninit(b, sizeof *omh); > + match_len = nx_put_raw(b, true, cr, cookie, cookie_mask) + sizeof *omh; > ofpbuf_put_zeros(b, ROUND_UP(match_len, 8) - match_len); > + > + omh = (struct ofp11_match_header *)((char *)b->data + start_len); > + omh->type = htons(OFPMT_OXM); > + omh->length = htons(match_len); > + > return match_len; > } > + _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev