+ 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
+ * 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. */
+enum ofperr
+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. */
+enum ofperr
+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);
+}
+
+static enum ofperr
+oxm_pull_match__(struct ofpbuf *b, bool strict,
+ uint16_t priority, struct cls_rule *rule)
+{
+ 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, NULL, NULL);
+}
+
+/* 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'.
+ *
+ * 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)
+{
+ return oxm_pull_match__(b, true, priority, rule);
+}
+
+/* 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)
+{
+ return oxm_pull_match__(b, false, priority, rule);