From: Ben Pfaff Date: Thu, 28 Oct 2010 03:15:56 +0000 (-0700) Subject: flow: Add more functions for working with flow_wildcards. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=494e43a517694cff1ca6304f6456ba0edbb924e2;p=openvswitch flow: Add more functions for working with flow_wildcards. These have limited use now but will become more important later. --- diff --git a/lib/flow.c b/lib/flow.c index 82e60eb9..ca745187 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -367,6 +367,8 @@ flow_nw_bits_to_mask(uint32_t wildcards, int shift) return wildcards < 32 ? htonl(~((1u << wildcards) - 1)) : 0; } +/* Initializes 'wc' from 'wildcards', which may be any combination of the + * OFPFW_* and OVSFW_* wildcard bits. */ void flow_wildcards_init(struct flow_wildcards *wc, uint32_t wildcards) { @@ -375,3 +377,59 @@ flow_wildcards_init(struct flow_wildcards *wc, uint32_t wildcards) wc->nw_dst_mask = flow_nw_bits_to_mask(wc->wildcards, OFPFW_NW_DST_SHIFT); } +/* Initializes 'wc' as an exact-match set of wildcards; that is, 'wc' does not + * wildcard any bits or fields. */ +void +flow_wildcards_init_exact(struct flow_wildcards *wc) +{ + flow_wildcards_init(wc, 0); +} + +static int +count_ones(ovs_be32 mask) +{ +#if __GNUC__ >= 4 + return __builtin_popcount(mask); +#else + int bits; + + for (bits = 0; mask; bits++) { + mask &= mask - 1; + } + + return bits; +#endif +} + +static bool +set_nw_mask(struct flow_wildcards *wc, ovs_be32 mask, + ovs_be32 *maskp, int shift) +{ + int wcbits = 32 - count_ones(mask); + if (flow_nw_bits_to_mask(wcbits, 0) == mask) { + wc->wildcards &= ~(0x3f << shift); + wc->wildcards |= wcbits << shift; + *maskp = mask; + return true; + } else { + return false; + } +} + +/* Sets the IP (or ARP) source wildcard mask to CIDR 'mask' (consisting of N + * high-order 1-bit and 32-N low-order 0-bits). Returns true if successful, + * false if 'mask' is not a CIDR mask. */ +bool +flow_wildcards_set_nw_src_mask(struct flow_wildcards *wc, ovs_be32 mask) +{ + return set_nw_mask(wc, mask, &wc->nw_src_mask, OFPFW_NW_SRC_SHIFT); +} + +/* Sets the IP (or ARP) destination wildcard mask to CIDR 'mask' (consisting of + * N high-order 1-bit and 32-N low-order 0-bits). Returns true if successful, + * false if 'mask' is not a CIDR mask. */ +bool +flow_wildcards_set_nw_dst_mask(struct flow_wildcards *wc, ovs_be32 mask) +{ + return set_nw_mask(wc, mask, &wc->nw_dst_mask, OFPFW_NW_DST_SHIFT); +} diff --git a/lib/flow.h b/lib/flow.h index ba376812..7667cb04 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -97,5 +97,9 @@ struct flow_wildcards { ovs_be32 flow_nw_bits_to_mask(uint32_t wildcards, int shift); void flow_wildcards_init(struct flow_wildcards *, uint32_t wildcards); +void flow_wildcards_init_exact(struct flow_wildcards *); + +bool flow_wildcards_set_nw_src_mask(struct flow_wildcards *, ovs_be32); +bool flow_wildcards_set_nw_dst_mask(struct flow_wildcards *, ovs_be32); #endif /* flow.h */