+
+ if (eth_type_mpls(flow->dl_type)) {
+ int n;
+
+ b->l2_5_ofs = b->l3_ofs;
+ for (n = 1; n < FLOW_MAX_MPLS_LABELS; n++) {
+ if (flow->mpls_lse[n - 1] & htonl(MPLS_BOS_MASK)) {
+ break;
+ }
+ }
+ while (n > 0) {
+ push_mpls(b, flow->dl_type, flow->mpls_lse[--n]);
+ }
+ }
+}
+\f
+/* Compressed flow. */
+
+static int
+miniflow_n_values(const struct miniflow *flow)
+{
+ return count_1bits(flow->map);
+}
+
+static uint32_t *
+miniflow_alloc_values(struct miniflow *flow, int n)
+{
+ if (n <= MINI_N_INLINE) {
+ return flow->inline_values;
+ } else {
+ COVERAGE_INC(miniflow_malloc);
+ return xmalloc(n * sizeof *flow->values);
+ }
+}
+
+/* Completes an initialization of 'dst' as a miniflow copy of 'src' begun by
+ * the caller. The caller must have already initialized 'dst->map' properly
+ * to indicate the significant uint32_t elements of 'src'. 'n' must be the
+ * number of 1-bits in 'dst->map'.
+ *
+ * Normally the significant elements are the ones that are non-zero. However,
+ * when a miniflow is initialized from a (mini)mask, the values can be zeroes,
+ * so that the flow and mask always have the same maps.
+ *
+ * This function initializes 'dst->values' (either inline if possible or with
+ * malloc() otherwise) and copies the uint32_t elements of 'src' indicated by
+ * 'dst->map' into it. */
+static void
+miniflow_init__(struct miniflow *dst, const struct flow *src, int n)
+{
+ const uint32_t *src_u32 = (const uint32_t *) src;
+ unsigned int ofs;
+ uint64_t map;
+
+ dst->values = miniflow_alloc_values(dst, n);
+ ofs = 0;
+ for (map = dst->map; map; map = zero_rightmost_1bit(map)) {
+ dst->values[ofs++] = src_u32[raw_ctz(map)];
+ }
+}
+
+/* Initializes 'dst' as a copy of 'src'. The caller must eventually free 'dst'
+ * with miniflow_destroy(). */
+void
+miniflow_init(struct miniflow *dst, const struct flow *src)
+{
+ const uint32_t *src_u32 = (const uint32_t *) src;
+ unsigned int i;
+ int n;
+
+ /* Initialize dst->map, counting the number of nonzero elements. */
+ n = 0;
+ dst->map = 0;
+
+ for (i = 0; i < FLOW_U32S; i++) {
+ if (src_u32[i]) {
+ dst->map |= UINT64_C(1) << i;
+ n++;
+ }
+ }
+
+ miniflow_init__(dst, src, n);
+}
+
+/* Initializes 'dst' as a copy of 'src', using 'mask->map' as 'dst''s map. The
+ * caller must eventually free 'dst' with miniflow_destroy(). */
+void
+miniflow_init_with_minimask(struct miniflow *dst, const struct flow *src,
+ const struct minimask *mask)
+{
+ dst->map = mask->masks.map;
+ miniflow_init__(dst, src, miniflow_n_values(dst));
+}
+
+/* Initializes 'dst' as a copy of 'src'. The caller must eventually free 'dst'
+ * with miniflow_destroy(). */
+void
+miniflow_clone(struct miniflow *dst, const struct miniflow *src)
+{
+ int n = miniflow_n_values(src);
+ dst->map = src->map;
+ dst->values = miniflow_alloc_values(dst, n);
+ memcpy(dst->values, src->values, n * sizeof *dst->values);
+}
+
+/* Initializes 'dst' with the data in 'src', destroying 'src'.
+ * The caller must eventually free 'dst' with miniflow_destroy(). */
+void
+miniflow_move(struct miniflow *dst, struct miniflow *src)
+{
+ if (src->values == src->inline_values) {
+ dst->values = dst->inline_values;
+ memcpy(dst->values, src->values,
+ miniflow_n_values(src) * sizeof *dst->values);
+ } else {
+ dst->values = src->values;
+ }
+ dst->map = src->map;
+}
+
+/* Frees any memory owned by 'flow'. Does not free the storage in which 'flow'
+ * itself resides; the caller is responsible for that. */
+void
+miniflow_destroy(struct miniflow *flow)
+{
+ if (flow->values != flow->inline_values) {
+ free(flow->values);
+ }
+}
+
+/* Initializes 'dst' as a copy of 'src'. */
+void
+miniflow_expand(const struct miniflow *src, struct flow *dst)
+{
+ memset(dst, 0, sizeof *dst);
+ flow_union_with_miniflow(dst, src);
+}
+
+/* Returns the uint32_t that would be at byte offset '4 * u32_ofs' if 'flow'
+ * were expanded into a "struct flow". */
+static uint32_t
+miniflow_get(const struct miniflow *flow, unsigned int u32_ofs)
+{
+ return (flow->map & UINT64_C(1) << u32_ofs)
+ ? *(flow->values +
+ count_1bits(flow->map & ((UINT64_C(1) << u32_ofs) - 1)))
+ : 0;
+}
+
+/* Returns true if 'a' and 'b' are the same flow, false otherwise. */
+bool
+miniflow_equal(const struct miniflow *a, const struct miniflow *b)
+{
+ const uint32_t *ap = a->values;
+ const uint32_t *bp = b->values;
+ const uint64_t a_map = a->map;
+ const uint64_t b_map = b->map;
+ uint64_t map;
+
+ if (a_map == b_map) {
+ for (map = a_map; map; map = zero_rightmost_1bit(map)) {
+ if (*ap++ != *bp++) {
+ return false;
+ }
+ }
+ } else {
+ for (map = a_map | b_map; map; map = zero_rightmost_1bit(map)) {
+ uint64_t bit = rightmost_1bit(map);
+ uint64_t a_value = a_map & bit ? *ap++ : 0;
+ uint64_t b_value = b_map & bit ? *bp++ : 0;
+
+ if (a_value != b_value) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* Returns true if 'a' and 'b' are equal at the places where there are 1-bits
+ * in 'mask', false if they differ. */
+bool
+miniflow_equal_in_minimask(const struct miniflow *a, const struct miniflow *b,
+ const struct minimask *mask)
+{
+ const uint32_t *p;
+ uint64_t map;
+
+ p = mask->masks.values;
+
+ for (map = mask->masks.map; map; map = zero_rightmost_1bit(map)) {
+ int ofs = raw_ctz(map);
+
+ if ((miniflow_get(a, ofs) ^ miniflow_get(b, ofs)) & *p) {
+ return false;
+ }
+ p++;
+ }
+
+ return true;
+}
+
+/* Returns true if 'a' and 'b' are equal at the places where there are 1-bits
+ * in 'mask', false if they differ. */
+bool
+miniflow_equal_flow_in_minimask(const struct miniflow *a, const struct flow *b,
+ const struct minimask *mask)
+{
+ const uint32_t *b_u32 = (const uint32_t *) b;
+ const uint32_t *p;
+ uint64_t map;
+
+ p = mask->masks.values;
+
+ for (map = mask->masks.map; map; map = zero_rightmost_1bit(map)) {
+ int ofs = raw_ctz(map);
+
+ if ((miniflow_get(a, ofs) ^ b_u32[ofs]) & *p) {
+ return false;
+ }
+ p++;
+ }
+
+ return true;
+}
+
+/* Returns a hash value for 'flow', given 'basis'. */
+uint32_t
+miniflow_hash(const struct miniflow *flow, uint32_t basis)
+{
+ const uint32_t *p = flow->values;
+ uint32_t hash = basis;
+ uint64_t hash_map = 0;
+ uint64_t map;
+
+ for (map = flow->map; map; map = zero_rightmost_1bit(map)) {
+ if (*p) {
+ hash = mhash_add(hash, *p);
+ hash_map |= rightmost_1bit(map);
+ }
+ p++;
+ }
+ hash = mhash_add(hash, hash_map);
+ hash = mhash_add(hash, hash_map >> 32);
+
+ return mhash_finish(hash, p - flow->values);
+}
+
+/* Returns a hash value for the bits of 'flow' where there are 1-bits in
+ * 'mask', given 'basis'.
+ *
+ * The hash values returned by this function are the same as those returned by
+ * flow_hash_in_minimask(), only the form of the arguments differ. */
+uint32_t
+miniflow_hash_in_minimask(const struct miniflow *flow,
+ const struct minimask *mask, uint32_t basis)
+{
+ const uint32_t *p = mask->masks.values;
+ uint32_t hash = basis;
+ uint32_t flow_u32;
+
+ MINIFLOW_FOR_EACH_IN_MAP(flow_u32, flow, mask->masks.map) {
+ hash = mhash_add(hash, flow_u32 & *p++);
+ }
+
+ return mhash_finish(hash, (p - mask->masks.values) * 4);
+}
+
+/* Returns a hash value for the bits of 'flow' where there are 1-bits in
+ * 'mask', given 'basis'.
+ *
+ * The hash values returned by this function are the same as those returned by
+ * miniflow_hash_in_minimask(), only the form of the arguments differ. */
+uint32_t
+flow_hash_in_minimask(const struct flow *flow, const struct minimask *mask,
+ uint32_t basis)
+{
+ const uint32_t *flow_u32 = (const uint32_t *)flow;
+ const uint32_t *p = mask->masks.values;
+ uint32_t hash;
+ uint64_t map;
+
+ hash = basis;
+ for (map = mask->masks.map; map; map = zero_rightmost_1bit(map)) {
+ hash = mhash_add(hash, flow_u32[raw_ctz(map)] & *p++);
+ }
+
+ return mhash_finish(hash, (p - mask->masks.values) * 4);
+}
+
+/* Returns a hash value for the bits of range [start, end) in 'flow',
+ * where there are 1-bits in 'mask', given 'hash'.
+ *
+ * The hash values returned by this function are the same as those returned by
+ * minimatch_hash_range(), only the form of the arguments differ. */
+uint32_t
+flow_hash_in_minimask_range(const struct flow *flow,
+ const struct minimask *mask,
+ uint8_t start, uint8_t end, uint32_t *basis)
+{
+ const uint32_t *flow_u32 = (const uint32_t *)flow;
+ unsigned int offset;
+ uint64_t map = miniflow_get_map_in_range(&mask->masks, start, end,
+ &offset);
+ const uint32_t *p = mask->masks.values + offset;
+ uint32_t hash = *basis;
+
+ for (; map; map = zero_rightmost_1bit(map)) {
+ hash = mhash_add(hash, flow_u32[raw_ctz(map)] & *p++);
+ }
+
+ *basis = hash; /* Allow continuation from the unfinished value. */
+ return mhash_finish(hash, (p - mask->masks.values) * 4);
+}
+
+\f
+/* Initializes 'dst' as a copy of 'src'. The caller must eventually free 'dst'
+ * with minimask_destroy(). */
+void
+minimask_init(struct minimask *mask, const struct flow_wildcards *wc)
+{
+ miniflow_init(&mask->masks, &wc->masks);
+}
+
+/* Initializes 'dst' as a copy of 'src'. The caller must eventually free 'dst'
+ * with minimask_destroy(). */
+void
+minimask_clone(struct minimask *dst, const struct minimask *src)
+{
+ miniflow_clone(&dst->masks, &src->masks);
+}
+
+/* Initializes 'dst' with the data in 'src', destroying 'src'.
+ * The caller must eventually free 'dst' with minimask_destroy(). */
+void
+minimask_move(struct minimask *dst, struct minimask *src)
+{
+ miniflow_move(&dst->masks, &src->masks);
+}
+
+/* Initializes 'dst_' as the bit-wise "and" of 'a_' and 'b_'.
+ *
+ * The caller must provide room for FLOW_U32S "uint32_t"s in 'storage', for use
+ * by 'dst_'. The caller must *not* free 'dst_' with minimask_destroy(). */
+void
+minimask_combine(struct minimask *dst_,
+ const struct minimask *a_, const struct minimask *b_,
+ uint32_t storage[FLOW_U32S])
+{
+ struct miniflow *dst = &dst_->masks;
+ const struct miniflow *a = &a_->masks;
+ const struct miniflow *b = &b_->masks;
+ uint64_t map;
+ int n = 0;
+
+ dst->values = storage;
+
+ dst->map = 0;
+ for (map = a->map & b->map; map; map = zero_rightmost_1bit(map)) {
+ int ofs = raw_ctz(map);
+ uint32_t mask = miniflow_get(a, ofs) & miniflow_get(b, ofs);
+
+ if (mask) {
+ dst->map |= rightmost_1bit(map);
+ dst->values[n++] = mask;
+ }
+ }
+}
+
+/* Frees any memory owned by 'mask'. Does not free the storage in which 'mask'
+ * itself resides; the caller is responsible for that. */
+void
+minimask_destroy(struct minimask *mask)
+{
+ miniflow_destroy(&mask->masks);
+}
+
+/* Initializes 'dst' as a copy of 'src'. */
+void
+minimask_expand(const struct minimask *mask, struct flow_wildcards *wc)
+{
+ miniflow_expand(&mask->masks, &wc->masks);
+}
+
+/* Returns the uint32_t that would be at byte offset '4 * u32_ofs' if 'mask'
+ * were expanded into a "struct flow_wildcards". */
+uint32_t
+minimask_get(const struct minimask *mask, unsigned int u32_ofs)
+{
+ return miniflow_get(&mask->masks, u32_ofs);
+}
+
+/* Returns true if 'a' and 'b' are the same flow mask, false otherwise. */
+bool
+minimask_equal(const struct minimask *a, const struct minimask *b)
+{
+ return miniflow_equal(&a->masks, &b->masks);
+}
+
+/* Returns a hash value for 'mask', given 'basis'. */
+uint32_t
+minimask_hash(const struct minimask *mask, uint32_t basis)
+{
+ return miniflow_hash(&mask->masks, basis);
+}
+
+/* Returns true if at least one bit is wildcarded in 'a_' but not in 'b_',
+ * false otherwise. */
+bool
+minimask_has_extra(const struct minimask *a_, const struct minimask *b_)
+{
+ const struct miniflow *a = &a_->masks;
+ const struct miniflow *b = &b_->masks;
+ uint64_t map;
+
+ for (map = a->map | b->map; map; map = zero_rightmost_1bit(map)) {
+ int ofs = raw_ctz(map);
+ uint32_t a_u32 = miniflow_get(a, ofs);
+ uint32_t b_u32 = miniflow_get(b, ofs);
+
+ if ((a_u32 & b_u32) != b_u32) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Returns true if 'mask' matches every packet, false if 'mask' fixes any bits
+ * or fields. */
+bool
+minimask_is_catchall(const struct minimask *mask_)
+{
+ const struct miniflow *mask = &mask_->masks;
+ const uint32_t *p = mask->values;
+ uint64_t map;
+
+ for (map = mask->map; map; map = zero_rightmost_1bit(map)) {
+ if (*p++) {
+ return false;
+ }
+ }
+ return true;