+ return nx_pull_raw(p, match_len, strict, match, cookie, cookie_mask);
+}
+
+/* Parses the nx_match formatted match description in 'b' with length
+ * 'match_len'. Stores the results in 'match'. If 'cookie' and 'cookie_mask'
+ * are valid pointers, then stores the cookie and mask in them if 'b' contains
+ * a "NXM_NX_COOKIE*" match. Otherwise, stores 0 in both.
+ *
+ * Fails with an error upon encountering an unknown NXM header.
+ *
+ * Returns 0 if successful, otherwise an OpenFlow error code. */
+enum ofperr
+nx_pull_match(struct ofpbuf *b, unsigned int match_len, struct match *match,
+ ovs_be64 *cookie, ovs_be64 *cookie_mask)
+{
+ return nx_pull_match__(b, match_len, true, match, cookie, cookie_mask);
+}
+
+/* Behaves the same as nx_pull_match(), but skips over unknown NXM headers,
+ * instead of failing with an error. */
+enum ofperr
+nx_pull_match_loose(struct ofpbuf *b, unsigned int match_len,
+ struct match *match,
+ ovs_be64 *cookie, ovs_be64 *cookie_mask)
+{
+ return nx_pull_match__(b, match_len, false, match, cookie, cookie_mask);
+}
+
+static enum ofperr
+oxm_pull_match__(struct ofpbuf *b, bool strict, struct match *match)
+{
+ 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 %"PRIuSIZE")", match_len, b->size);
+ return OFPERR_OFPBMC_BAD_LEN;
+ }
+
+ return nx_pull_raw(p + sizeof *omh, match_len - sizeof *omh,
+ strict, match, NULL, NULL);
+}
+
+/* Parses the oxm formatted match description preceded by a struct
+ * ofp11_match_header in 'b'. Stores the result in 'match'.
+ *
+ * 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, struct match *match)
+{
+ return oxm_pull_match__(b, true, match);
+}
+
+/* Behaves the same as oxm_pull_match() with one exception. Skips over unknown
+ * OXM headers instead of failing with an error when they are encountered. */
+enum ofperr
+oxm_pull_match_loose(struct ofpbuf *b, struct match *match)
+{
+ return oxm_pull_match__(b, false, match);