+/* miniflow_push_* macros allow filling in a miniflow data values in order.
+ * Assertions are needed only when the layout of the struct flow is modified.
+ * 'ofs' is a compile-time constant, which allows most of the code be optimized
+ * away. Some GCC versions gave warnigns on ALWAYS_INLINE, so these are
+ * defined as macros. */
+
+#if (FLOW_WC_SEQ != 26)
+#define MINIFLOW_ASSERT(X) ovs_assert(X)
+#else
+#define MINIFLOW_ASSERT(X)
+#endif
+
+#define miniflow_push_uint32_(MF, OFS, VALUE) \
+{ \
+ MINIFLOW_ASSERT(MF.data < MF.end && (OFS) % 4 == 0 \
+ && !(MF.map & (UINT64_MAX << (OFS) / 4))); \
+ *MF.data++ = VALUE; \
+ MF.map |= UINT64_C(1) << (OFS) / 4; \
+}
+
+#define miniflow_push_be32_(MF, OFS, VALUE) \
+ miniflow_push_uint32_(MF, OFS, (OVS_FORCE uint32_t)(VALUE))
+
+#define miniflow_push_uint16_(MF, OFS, VALUE) \
+{ \
+ MINIFLOW_ASSERT(MF.data < MF.end && \
+ (((OFS) % 4 == 0 && !(MF.map & (UINT64_MAX << (OFS) / 4))) \
+ || ((OFS) % 4 == 2 && MF.map & (UINT64_C(1) << (OFS) / 4) \
+ && !(MF.map & (UINT64_MAX << ((OFS) / 4 + 1)))))); \
+ \
+ if ((OFS) % 4 == 0) { \
+ *(uint16_t *)MF.data = VALUE; \
+ MF.map |= UINT64_C(1) << (OFS) / 4; \
+ } else if ((OFS) % 4 == 2) { \
+ *((uint16_t *)MF.data + 1) = VALUE; \
+ MF.data++; \
+ } \
+}
+
+#define miniflow_push_be16_(MF, OFS, VALUE) \
+ miniflow_push_uint16_(MF, OFS, (OVS_FORCE uint16_t)VALUE);
+
+/* Data at 'valuep' may be unaligned. */
+#define miniflow_push_words_(MF, OFS, VALUEP, N_WORDS) \
+{ \
+ int ofs32 = (OFS) / 4; \
+ \
+ MINIFLOW_ASSERT(MF.data + (N_WORDS) <= MF.end && (OFS) % 4 == 0 \
+ && !(MF.map & (UINT64_MAX << ofs32))); \
+ \
+ memcpy(MF.data, (VALUEP), (N_WORDS) * sizeof *MF.data); \
+ MF.data += (N_WORDS); \
+ MF.map |= ((UINT64_MAX >> (64 - (N_WORDS))) << ofs32); \
+}
+
+#define miniflow_push_uint32(MF, FIELD, VALUE) \
+ miniflow_push_uint32_(MF, offsetof(struct flow, FIELD), VALUE)
+
+#define miniflow_push_be32(MF, FIELD, VALUE) \
+ miniflow_push_be32_(MF, offsetof(struct flow, FIELD), VALUE)
+
+#define miniflow_push_uint32_check(MF, FIELD, VALUE) \
+ { if (OVS_LIKELY(VALUE)) { \
+ miniflow_push_uint32_(MF, offsetof(struct flow, FIELD), VALUE); \
+ } \
+ }
+
+#define miniflow_push_be32_check(MF, FIELD, VALUE) \
+ { if (OVS_LIKELY(VALUE)) { \
+ miniflow_push_be32_(MF, offsetof(struct flow, FIELD), VALUE); \
+ } \
+ }
+
+#define miniflow_push_uint16(MF, FIELD, VALUE) \
+ miniflow_push_uint16_(MF, offsetof(struct flow, FIELD), VALUE)
+
+#define miniflow_push_be16(MF, FIELD, VALUE) \
+ miniflow_push_be16_(MF, offsetof(struct flow, FIELD), VALUE)
+
+#define miniflow_push_words(MF, FIELD, VALUEP, N_WORDS) \
+ miniflow_push_words_(MF, offsetof(struct flow, FIELD), VALUEP, N_WORDS)
+
+/* Pulls the MPLS headers at '*datap' and returns the count of them. */
+static inline int
+parse_mpls(void **datap, size_t *sizep)
+{
+ const struct mpls_hdr *mh;
+ int count = 0;
+
+ while ((mh = data_try_pull(datap, sizep, sizeof *mh))) {
+ count++;
+ if (mh->mpls_lse.lo & htons(1 << MPLS_BOS_SHIFT)) {