/* 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 ofs; unsigned int i; int n; /* Initialize dst->map, counting the number of nonzero elements. */ n = 0; memset(dst->map, 0, sizeof dst->map); for (i = 0; i < FLOW_U32S; i++) { if (src_u32[i]) { dst->map[i / 32] |= 1u << (i % 32); n++; } } /* Initialize dst->values. */ dst->values = miniflow_alloc_values(dst, n); ofs = 0; for (i = 0; i < MINI_N_MAPS; i++) { uint32_t map; for (map = dst->map[i]; map; map = zero_rightmost_1bit(map)) { dst->values[ofs++] = src_u32[raw_ctz(map) + i * 32]; } } }
static void ofputil_format_version_bitmap__(struct ds *msg, uint32_t bitmap, void (*format_version)(struct ds *msg, enum ofp_version)) { while (bitmap) { format_version(msg, raw_ctz(bitmap)); bitmap = zero_rightmost_1bit(bitmap); if (bitmap) { ds_put_cstr(msg, ", "); } } }
/* Returns the set of protocols that are supported on top of the * OpenFlow versions included in 'bitmap'. */ enum ofputil_protocol ofputil_protocols_from_version_bitmap(uint32_t bitmap) { enum ofputil_protocol protocols = 0; for (; bitmap; bitmap = zero_rightmost_1bit(bitmap)) { enum ofp_version version = rightmost_1bit_idx(bitmap); protocols |= ofputil_protocols_from_ofp_version(version); } return protocols; }
/* Returns a bitmap of OpenFlow versions that are supported by at * least one of the 'protocols'. */ uint32_t ofputil_protocols_to_version_bitmap(enum ofputil_protocol protocols) { uint32_t bitmap = 0; for (; protocols; protocols = zero_rightmost_1bit(protocols)) { enum ofputil_protocol protocol = rightmost_1bit(protocols); bitmap |= 1u << ofputil_protocol_to_ofp_version(protocol); } return bitmap; }
/* Perform a bitwise OR of miniflow 'src' flow data with the equivalent * fields in 'dst', storing the result in 'dst'. */ static void flow_union_with_miniflow(struct flow *dst, const struct miniflow *src) { uint32_t *dst_u32 = (uint32_t *) dst; int ofs; int i; ofs = 0; for (i = 0; i < MINI_N_MAPS; i++) { uint32_t map; for (map = src->map[i]; map; map = zero_rightmost_1bit(map)) { dst_u32[raw_ctz(map) + i * 32] |= src->values[ofs++]; } } }
/* Returns true if 'target' satisifies 'match', that is, if each bit for which * 'match' specifies a particular value has the correct value in 'target'. * * This function is equivalent to miniflow_equal_flow_in_minimask(&match->flow, * target, &match->mask) but it is faster because of the invariant that * match->flow.map and match->mask.map are the same. */ bool minimatch_matches_flow(const struct minimatch *match, const struct flow *target) { const uint32_t *target_u32 = (const uint32_t *) target; const uint32_t *flowp = miniflow_get_u32_values(&match->flow); const uint32_t *maskp = miniflow_get_u32_values(&match->mask.masks); uint64_t map; for (map = match->flow.map; map; map = zero_rightmost_1bit(map)) { if ((*flowp++ ^ target_u32[raw_ctz(map)]) & *maskp++) { return false; } } return true; }
/* 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 nonzero uint32_t elements of 'src'. 'n' must be the number * of 1-bits in 'dst->map'. * * This function initializes 'dst->values' (either inline if possible or with * malloc() otherwise) and copies the nonzero uint32_t elements of 'src' 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; int i; dst->values = miniflow_alloc_values(dst, n); ofs = 0; for (i = 0; i < MINI_N_MAPS; i++) { uint32_t map; for (map = dst->map[i]; map; map = zero_rightmost_1bit(map)) { dst->values[ofs++] = src_u32[raw_ctz(map) + i * 32]; } } }
/* Initializes 'dst' as a copy of 'src'. */ void miniflow_expand(const struct miniflow *src, struct flow *dst) { uint32_t *dst_u32 = (uint32_t *) dst; int ofs; int i; memset(dst_u32, 0, sizeof *dst); ofs = 0; for (i = 0; i < MINI_N_MAPS; i++) { uint32_t map; for (map = src->map[i]; map; map = zero_rightmost_1bit(map)) { dst_u32[raw_ctz(map) + i * 32] = src->values[ofs++]; } } }
/* Returns a hash value for the bits of range [start, end) in 'minimatch', * given 'basis'. * * The hash values returned by this function are the same as those returned by * flow_hash_in_minimask_range(), only the form of the arguments differ. */ uint32_t minimatch_hash_range(const struct minimatch *match, uint8_t start, uint8_t end, uint32_t *basis) { const uint32_t *p; uint64_t map = miniflow_get_map_in_range(&match->mask.masks, start, end, &p); const ptrdiff_t df = match->mask.masks.values - match->flow.values; uint32_t hash = *basis; for (; map; map = zero_rightmost_1bit(map)) { if (*p) { hash = mhash_add(hash, *(p - df) & *p); } p++; } *basis = hash; /* Allow continuation from the unfinished value. */ return mhash_finish(hash, (p - match->mask.masks.values) * 4); }
/* Returns true if 'target' satisifies 'match', that is, if each bit for which * 'match' specifies a particular value has the correct value in 'target'. * * This function is equivalent to miniflow_equal_flow_in_minimask(&match->flow, * target, &match->mask) but it is faster because of the invariant that * match->flow.map and match->mask.map are the same. */ bool minimatch_matches_flow(const struct minimatch *match, const struct flow *target) { const uint32_t *target_u32 = (const uint32_t *) target; const uint32_t *flowp = match->flow.values; const uint32_t *maskp = match->mask.masks.values; int i; for (i = 0; i < MINI_N_MAPS; i++) { uint32_t map; for (map = match->flow.map[i]; map; map = zero_rightmost_1bit(map)) { if ((*flowp++ ^ target_u32[raw_ctz(map)]) & *maskp++) { return false; } } target_u32 += 32; } return true; }