+static inline uint64_t flow_u64_value(const struct flow *flow, size_t index)
+{
+ return ((uint64_t *)flow)[index];
+}
+
+static inline uint64_t *flow_u64_lvalue(struct flow *flow, size_t index)
+{
+ return &((uint64_t *)flow)[index];
+}
+
+static inline size_t
+miniflow_n_values(const struct miniflow *flow)
+{
+ return flowmap_n_1bits(flow->map);
+}
+
+struct flow_for_each_in_maps_aux {
+ const struct flow *flow;
+ struct flowmap_aux map_aux;
+};
+
+static inline bool
+flow_values_get_next_in_maps(struct flow_for_each_in_maps_aux *aux,
+ uint64_t *value)
+{
+ size_t idx;
+
+ if (flowmap_next_index(&aux->map_aux, &idx)) {
+ *value = flow_u64_value(aux->flow, idx);
+ return true;
+ }
+ return false;
+}
+
+/* Iterate through all flow u64 values specified by 'MAPS'. */
+#define FLOW_FOR_EACH_IN_MAPS(VALUE, FLOW, MAPS) \
+ for (struct flow_for_each_in_maps_aux aux__ \
+ = { (FLOW), FLOWMAP_AUX_INITIALIZER(MAPS) }; \
+ flow_values_get_next_in_maps(&aux__, &(VALUE));)
+
+struct mf_for_each_in_map_aux {
+ size_t unit;
+ struct flowmap fmap;
+ struct flowmap map;
+ const uint64_t *values;
+};
+
+static inline bool
+mf_get_next_in_map(struct mf_for_each_in_map_aux *aux,
+ uint64_t *value)
+{
+ map_t *map, *fmap;
+ map_t rm1bit;
+
+ while (OVS_UNLIKELY(!*(map = &aux->map.bits[aux->unit]))) {
+ /* Skip remaining data in the previous unit. */
+ aux->values += count_1bits(aux->fmap.bits[aux->unit]);
+ if (++aux->unit == FLOWMAP_UNITS) {
+ return false;
+ }
+ }
+
+ rm1bit = rightmost_1bit(*map);
+ *map -= rm1bit;
+ fmap = &aux->fmap.bits[aux->unit];
+
+ if (OVS_LIKELY(*fmap & rm1bit)) {
+ map_t trash = *fmap & (rm1bit - 1);
+
+ *fmap -= trash;
+ /* count_1bits() is fast for systems where speed matters (e.g.,
+ * DPDK), so we don't try avoid using it.
+ * Advance 'aux->values' to point to the value for 'rm1bit'. */
+ aux->values += count_1bits(trash);
+
+ *value = *aux->values;
+ } else {
+ *value = 0;
+ }
+ return true;
+}
+
+/* Iterate through miniflow u64 values specified by 'FLOWMAP'. */
+#define MINIFLOW_FOR_EACH_IN_FLOWMAP(VALUE, FLOW, FLOWMAP) \
+ for (struct mf_for_each_in_map_aux aux__ = \
+ { 0, (FLOW)->map, (FLOWMAP), miniflow_get_values(FLOW) }; \
+ mf_get_next_in_map(&aux__, &(VALUE));)
+
+/* This can be used when it is known that 'idx' is set in 'map'. */
+static inline const uint64_t *
+miniflow_values_get__(const uint64_t *values, map_t map, size_t idx)
+{
+ return values + count_1bits(map & ((MAP_1 << idx) - 1));
+}
+
+/* This can be used when it is known that 'u64_idx' is set in
+ * the map of 'mf'. */
+static inline const uint64_t *
+miniflow_get__(const struct miniflow *mf, size_t idx)
+{
+ const uint64_t *values = miniflow_get_values(mf);
+ const map_t *map = mf->map.bits;
+
+ while (idx >= MAP_T_BITS) {
+ idx -= MAP_T_BITS;
+ values += count_1bits(*map++);
+ }
+ return miniflow_values_get__(values, *map, idx);
+}
+
+#define MINIFLOW_IN_MAP(MF, IDX) flowmap_is_set(&(MF)->map, IDX)
+
+/* Get the value of the struct flow 'FIELD' as up to 8 byte wide integer type
+ * 'TYPE' from miniflow 'MF'. */
+#define MINIFLOW_GET_TYPE(MF, TYPE, FIELD) \
+ (MINIFLOW_IN_MAP(MF, FLOW_U64_OFFSET(FIELD)) \
+ ? ((OVS_FORCE const TYPE *)miniflow_get__(MF, FLOW_U64_OFFSET(FIELD))) \
+ [FLOW_U64_OFFREM(FIELD) / sizeof(TYPE)] \
+ : 0)
+
+#define MINIFLOW_GET_U8(FLOW, FIELD) \
+ MINIFLOW_GET_TYPE(FLOW, uint8_t, FIELD)
+#define MINIFLOW_GET_U16(FLOW, FIELD) \
+ MINIFLOW_GET_TYPE(FLOW, uint16_t, FIELD)
+#define MINIFLOW_GET_BE16(FLOW, FIELD) \
+ MINIFLOW_GET_TYPE(FLOW, ovs_be16, FIELD)
+#define MINIFLOW_GET_U32(FLOW, FIELD) \
+ MINIFLOW_GET_TYPE(FLOW, uint32_t, FIELD)
+#define MINIFLOW_GET_BE32(FLOW, FIELD) \
+ MINIFLOW_GET_TYPE(FLOW, ovs_be32, FIELD)
+#define MINIFLOW_GET_U64(FLOW, FIELD) \
+ MINIFLOW_GET_TYPE(FLOW, uint64_t, FIELD)
+#define MINIFLOW_GET_BE64(FLOW, FIELD) \
+ MINIFLOW_GET_TYPE(FLOW, ovs_be64, FIELD)
+
+static inline uint64_t miniflow_get(const struct miniflow *,
+ unsigned int u64_ofs);
+static inline uint32_t miniflow_get_u32(const struct miniflow *,
+ unsigned int u32_ofs);
+static inline ovs_be32 miniflow_get_be32(const struct miniflow *,
+ unsigned int be32_ofs);
+static inline uint16_t miniflow_get_vid(const struct miniflow *);
+static inline uint16_t miniflow_get_tcp_flags(const struct miniflow *);