void miniflow_expand(const struct miniflow *, struct flow *);
+static inline uint32_t
+mf_get_next_in_map(uint64_t *fmap, uint64_t rm1bit, const uint32_t **fp,
+ uint32_t *value)
+{
+ *value = 0;
+ if (*fmap & rm1bit) {
+ uint64_t trash = *fmap & (rm1bit - 1);
+
+ if (trash) {
+ *fmap -= trash;
+ *fp += count_1bits(trash);
+ }
+ *value = **fp;
+ }
+ return rm1bit != 0;
+}
+
+/* Iterate through all miniflow u32 values specified by the 'MAP'.
+ * This works as the first statement in a block.*/
+#define MINIFLOW_FOR_EACH_IN_MAP(VALUE, FLOW, MAP) \
+ const uint32_t *fp_ = (FLOW)->values; \
+ uint64_t rm1bit_, fmap_, map_; \
+ for (fmap_ = (FLOW)->map, map_ = (MAP), rm1bit_ = rightmost_1bit(map_); \
+ mf_get_next_in_map(&fmap_, rm1bit_, &fp_, &(VALUE)); \
+ map_ -= rm1bit_, rm1bit_ = rightmost_1bit(map_))
+
/* These accessors use byte offsets, which are assumed to be compile-time
* constants. */
static inline uint8_t miniflow_get_u8(const struct miniflow *,
static inline uint16_t miniflow_get_vid(const struct miniflow *);
static inline uint16_t miniflow_get_tcp_flags(const struct miniflow *);
static inline ovs_be64 miniflow_get_metadata(const struct miniflow *);
+static inline uint8_t miniflow_get_u8(const struct miniflow *, unsigned int ofs);
bool miniflow_equal(const struct miniflow *a, const struct miniflow *b);
bool miniflow_equal_in_minimask(const struct miniflow *a,
uint64_t miniflow_get_map_in_range(const struct miniflow *miniflow,
uint8_t start, uint8_t end,
unsigned int *offset);
+uint32_t miniflow_hash_5tuple(const struct miniflow *flow, uint32_t basis);
\f
/* Compressed flow wildcards. */
&& flow->nw_proto == IPPROTO_ICMPV6);
}
+static inline bool is_stp(const struct flow *flow)
+{
+ return (eth_addr_equals(flow->dl_dst, eth_addr_stp)
+ && flow->dl_type == htons(FLOW_DL_TYPE_NONE));
+}
+
#endif /* flow.h */