This may be used by both ofputil_decode_flow_mod() and ofputil_decode_packet_in()
Signed-off-by: Simon Horman <ho...@verge.net.au> --- v7 * Make use of oxm_pull_match() Change subject from "ofp-util: Add ofputil_ofp12_decode_match()" to "ofp-util: Add ofputil_pull_ofp12_match()" v6 * No change v5 * Add padded_match_len parameter to ofputil_pull_ofp12_match() and __ofputil_pull_ofp11_match(). This will be used when decoding messages that need to know the match length. * Read mach_length from omh after the length of buf has been verified, else an over-run may occur. v4 * No change v3 * Do not pull ofpbuf_pull() in the case of a STANDARD match. This simplifies things a little. v2 * No change --- lib/ofp-util.c | 54 +++++++++++++++++++++++++++++++++++++++++++++--------- lib/ofp-util.h | 6 ++++++ 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/lib/ofp-util.c b/lib/ofp-util.c index c88488d..9064e6b 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -265,31 +265,67 @@ ofputil_cls_rule_to_ofp10_match(const struct cls_rule *rule, memset(match->pad2, '\0', sizeof match->pad2); } -enum ofperr -ofputil_pull_ofp11_match(struct ofpbuf *buf, unsigned int priority, - struct cls_rule *rule) +static enum ofperr +__ofputil_pull_ofp11_match(struct ofpbuf *buf, unsigned int priority, + struct cls_rule *rule, ovs_be64 *cookie, + ovs_be64 *cookie_mask, uint16_t *padded_match_len, + uint8_t max_version) { - struct ofp11_match_header *omh; - struct ofp11_match *om; + struct ofp11_match_header *omh = buf->data; + uint16_t match_len; - if (buf->size < sizeof(struct ofp11_match_header)) { + if (buf->size < sizeof *omh) { return OFPERR_OFPBMC_BAD_LEN; } - omh = buf->data; + match_len = ntohs(omh->length); + switch (ntohs(omh->type)) { - case OFPMT_STANDARD: - if (omh->length != htons(sizeof *om) || buf->size < sizeof *om) { + case OFPMT_STANDARD: { + struct ofp11_match *om; + + if (match_len != sizeof *om || buf->size < sizeof *om) { return OFPERR_OFPBMC_BAD_LEN; } om = ofpbuf_pull(buf, sizeof *om); + if (padded_match_len) { + *padded_match_len = match_len; + } return ofputil_cls_rule_from_ofp11_match(om, priority, rule); + } + + case OFPMT_OXM: + if (max_version < OFP12_VERSION) { + return OFPERR_OFPBMC_BAD_TYPE; + } + if (padded_match_len) { + *padded_match_len = ROUND_UP(match_len, 8); + } + return oxm_pull_match(buf, priority, rule, cookie, cookie_mask); default: return OFPERR_OFPBMC_BAD_TYPE; } } +enum ofperr +ofputil_pull_ofp11_match(struct ofpbuf *buf, unsigned int priority, + struct cls_rule *rule) +{ + return __ofputil_pull_ofp11_match(buf, priority, rule, NULL, NULL, + NULL, OFP11_VERSION); +} + +enum ofperr +ofputil_pull_ofp12_match(struct ofpbuf *buf, unsigned int priority, + struct cls_rule *rule, ovs_be64 *cookie, + ovs_be64 *cookie_mask, uint16_t *padded_match_len) +{ + return __ofputil_pull_ofp11_match(buf, priority, rule, cookie, + cookie_mask, padded_match_len, + OFP12_VERSION); +} + /* Converts the ofp11_match in 'match' into a cls_rule in 'rule', with the * given 'priority'. Returns 0 if successful, otherwise an OFPERR_* value. */ enum ofperr diff --git a/lib/ofp-util.h b/lib/ofp-util.h index c87d648..cce5d41 100644 --- a/lib/ofp-util.h +++ b/lib/ofp-util.h @@ -125,6 +125,12 @@ enum ofperr ofputil_cls_rule_from_ofp11_match(const struct ofp11_match *, void ofputil_cls_rule_to_ofp11_match(const struct cls_rule *, struct ofp11_match *); +/* Work with ofp12_match. */ +enum ofperr ofputil_pull_ofp12_match(struct ofpbuf *, unsigned int priority, + struct cls_rule *, ovs_be64 *cookie, + ovs_be64 *cookie_mask, + uint16_t *padded_match_len); + /* dl_type translation between OpenFlow and 'struct flow' format. */ ovs_be16 ofputil_dl_type_to_openflow(ovs_be16 flow_dl_type); ovs_be16 ofputil_dl_type_from_openflow(ovs_be16 ofp_dl_type); -- 1.7.10.2.484.gcd07cc5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev