[ovs-dev] [prelearning 1/5] packets: Add more utility functions for IPv4 and IPv6 addresses.
Ethan Jackson
ethan at nicira.com
Wed Aug 17 00:41:46 UTC 2011
I would be inclined to implement a "clz" function similar to what
log_2_floor() does in util. We could use it both for log_2_floor()
and ip_count_cidr_bits(). That way we would only have to deal with
the ugly GNUC ifdefing in one place.
Seems fine otherwise.
Ethan
On Tue, Aug 16, 2011 at 16:29, Ben Pfaff <blp at nicira.com> wrote:
> We had these functions scattered around the source tree anyway. packets.h
> is a good place to centralize them.
>
> I do plan to introduce some additional callers.
> ---
> lib/classifier.c | 22 ++---------------
> lib/ofp-util.c | 16 ++----------
> lib/packets.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++-----
> lib/packets.h | 4 +++
> 4 files changed, 69 insertions(+), 38 deletions(-)
>
> diff --git a/lib/classifier.c b/lib/classifier.c
> index d1f9d5d..9c71b85 100644
> --- a/lib/classifier.c
> +++ b/lib/classifier.c
> @@ -421,15 +421,8 @@ format_ip_netmask(struct ds *s, const char *name, ovs_be32 ip,
> ovs_be32 netmask)
> {
> if (netmask) {
> - ds_put_format(s, "%s="IP_FMT, name, IP_ARGS(&ip));
> - if (netmask != htonl(UINT32_MAX)) {
> - if (ip_is_cidr(netmask)) {
> - int wcbits = ofputil_netmask_to_wcbits(netmask);
> - ds_put_format(s, "/%d", 32 - wcbits);
> - } else {
> - ds_put_format(s, "/"IP_FMT, IP_ARGS(&netmask));
> - }
> - }
> + ds_put_format(s, "%s=", name);
> + ip_format_masked(ip, netmask, s);
> ds_put_char(s, ',');
> }
> }
> @@ -441,16 +434,7 @@ format_ipv6_netmask(struct ds *s, const char *name,
> {
> if (!ipv6_mask_is_any(netmask)) {
> ds_put_format(s, "%s=", name);
> - print_ipv6_addr(s, addr);
> - if (!ipv6_mask_is_exact(netmask)) {
> - if (ipv6_is_cidr(netmask)) {
> - int cidr_bits = ipv6_count_cidr_bits(netmask);
> - ds_put_format(s, "/%d", cidr_bits);
> - } else {
> - ds_put_char(s, '/');
> - print_ipv6_addr(s, netmask);
> - }
> - }
> + print_ipv6_masked(s, addr, netmask);
> ds_put_char(s, ',');
> }
> }
> diff --git a/lib/ofp-util.c b/lib/ofp-util.c
> index b0e7405..cdb12e6 100644
> --- a/lib/ofp-util.c
> +++ b/lib/ofp-util.c
> @@ -59,22 +59,12 @@ ofputil_wcbits_to_netmask(int wcbits)
> }
>
> /* Given the IP netmask 'netmask', returns the number of bits of the IP address
> - * that it wildcards. 'netmask' must be a CIDR netmask (see ip_is_cidr()). */
> + * that it wildcards, that is, the number of 0-bits in 'netmask'. 'netmask'
> + * must be a CIDR netmask (see ip_is_cidr()). */
> int
> ofputil_netmask_to_wcbits(ovs_be32 netmask)
> {
> - assert(ip_is_cidr(netmask));
> -#if __GNUC__ >= 4
> - return netmask == htonl(0) ? 32 : __builtin_ctz(ntohl(netmask));
> -#else
> - int wcbits;
> -
> - for (wcbits = 32; netmask; wcbits--) {
> - netmask &= netmask - 1;
> - }
> -
> - return wcbits;
> -#endif
> + return 32 - ip_count_cidr_bits(netmask);
> }
>
> /* A list of the FWW_* and OFPFW_ bits that have the same value, meaning, and
> diff --git a/lib/packets.c b/lib/packets.c
> index e05e3eb..e7c53a8 100644
> --- a/lib/packets.c
> +++ b/lib/packets.c
> @@ -105,6 +105,40 @@ eth_set_vlan_tci(struct ofpbuf *packet, ovs_be16 tci)
> packet->l2 = packet->data;
> }
>
> +/* Given the IP netmask 'netmask', returns the number of bits of the IP address
> + * that it specifies, that is, the number of 1-bits in 'netmask'. 'netmask'
> + * must be a CIDR netmask (see ip_is_cidr()). */
> +int
> +ip_count_cidr_bits(ovs_be32 netmask)
> +{
> + assert(ip_is_cidr(netmask));
> +#if __GNUC__ >= 4
> + return netmask == htonl(0) ? 0 : 32 - __builtin_ctz(ntohl(netmask));
> +#else
> + int one_bits;
> +
> + for (one_bits = 0; netmask; one_bits++) {
> + netmask &= netmask - 1;
> + }
> +
> + return one_bits;
> +#endif
> +}
> +
> +void
> +ip_format_masked(ovs_be32 ip, ovs_be32 mask, struct ds *s)
> +{
> + ds_put_format(s, IP_FMT, IP_ARGS(&ip));
> + if (mask != htonl(UINT32_MAX)) {
> + if (ip_is_cidr(mask)) {
> + ds_put_format(s, "/%d", ip_count_cidr_bits(mask));
> + } else {
> + ds_put_format(s, "/"IP_FMT, IP_ARGS(&mask));
> + }
> + }
> +}
> +
> +
> /* Stores the string representation of the IPv6 address 'addr' into the
> * character array 'addr_str', which must be at least INET6_ADDRSTRLEN
> * bytes long. */
> @@ -117,10 +151,29 @@ format_ipv6_addr(char *addr_str, const struct in6_addr *addr)
> void
> print_ipv6_addr(struct ds *string, const struct in6_addr *addr)
> {
> - char addr_str[INET6_ADDRSTRLEN];
> + char *dst;
> +
> + ds_reserve(string, string->length + INET6_ADDRSTRLEN);
> +
> + dst = string->string + string->length;
> + format_ipv6_addr(dst, addr);
> + string->length += strlen(dst);
> +}
>
> - format_ipv6_addr(addr_str, addr);
> - ds_put_format(string, "%s", addr_str);
> +void
> +print_ipv6_masked(struct ds *s, const struct in6_addr *addr,
> + const struct in6_addr *mask)
> +{
> + print_ipv6_addr(s, addr);
> + if (mask && !ipv6_mask_is_exact(mask)) {
> + if (ipv6_is_cidr(mask)) {
> + int cidr_bits = ipv6_count_cidr_bits(mask);
> + ds_put_format(s, "/%d", cidr_bits);
> + } else {
> + ds_put_char(s, '/');
> + print_ipv6_addr(s, mask);
> + }
> + }
> }
>
> struct in6_addr ipv6_addr_bitand(const struct in6_addr *a,
> @@ -164,9 +217,9 @@ ipv6_create_mask(int mask)
> return netmask;
> }
>
> -/* Given the IPv6 netmask 'netmask', returns the number of bits of the
> - * IPv6 address that it wildcards. 'netmask' must be a CIDR netmask (see
> - * ipv6_is_cidr()). */
> +/* Given the IPv6 netmask 'netmask', returns the number of bits of the IPv6
> + * address that it specifies, that is, the number of 1-bits in 'netmask'.
> + * 'netmask' must be a CIDR netmask (see ipv6_is_cidr()). */
> int
> ipv6_count_cidr_bits(const struct in6_addr *netmask)
> {
> diff --git a/lib/packets.h b/lib/packets.h
> index a389e6a..304cd9d 100644
> --- a/lib/packets.h
> +++ b/lib/packets.h
> @@ -291,6 +291,8 @@ ip_is_cidr(ovs_be32 netmask)
> uint32_t x = ~ntohl(netmask);
> return !(x & (x + 1));
> }
> +int ip_count_cidr_bits(ovs_be32 netmask);
> +void ip_format_masked(ovs_be32 ip, ovs_be32 mask, struct ds *);
>
> #define IP_VER(ip_ihl_ver) ((ip_ihl_ver) >> 4)
> #define IP_IHL(ip_ihl_ver) ((ip_ihl_ver) & 15)
> @@ -423,6 +425,8 @@ static inline bool ipv6_mask_is_exact(const struct in6_addr *mask) {
>
> void format_ipv6_addr(char *addr_str, const struct in6_addr *addr);
> void print_ipv6_addr(struct ds *string, const struct in6_addr *addr);
> +void print_ipv6_masked(struct ds *string, const struct in6_addr *addr,
> + const struct in6_addr *mask);
> struct in6_addr ipv6_addr_bitand(const struct in6_addr *src,
> const struct in6_addr *mask);
> struct in6_addr ipv6_create_mask(int mask);
> --
> 1.7.4.4
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
>
More information about the dev
mailing list