X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fpackets.c;h=05148fe0f3c9a9e670a0eb71f4282bdb100a5dda;hb=130f6e5faa6190ca00000ebcb627e2d4ca3d4b37;hp=2dc82fe12e0d138cf821218fd7633cbfa24f58a4;hpb=093ca5b366899cb187ac0fb70b9308eeb8f452eb;p=openvswitch diff --git a/lib/packets.c b/lib/packets.c index 2dc82fe1..05148fe0 100644 --- a/lib/packets.c +++ b/lib/packets.c @@ -16,10 +16,16 @@ #include #include "packets.h" +#include +#include #include #include +#include "byte-order.h" +#include "dynamic-string.h" #include "ofpbuf.h" +const struct in6_addr in6addr_exact = IN6ADDR_EXACT_INIT; + /* Parses 's' as a 16-digit hexadecimal number representing a datapath ID. On * success stores the dpid into '*dpidp' and returns true, on failure stores 0 * into '*dpidp' and returns false. @@ -83,3 +89,117 @@ compose_benign_packet(struct ofpbuf *b, const char *tag, uint16_t snap_type, memcpy(llc_snap->snap.snap_org, "\x00\x23\x20", 3); llc_snap->snap.snap_type = htons(snap_type); } + +/* Stores the string representation of the IPv6 address 'addr' into the + * character array 'addr_str', which must be at least INET6_ADDRSTRLEN + * bytes long. */ +void +format_ipv6_addr(char *addr_str, const struct in6_addr *addr) +{ + inet_ntop(AF_INET6, addr, addr_str, INET6_ADDRSTRLEN); +} + +void +print_ipv6_addr(struct ds *string, const struct in6_addr *addr) +{ + char addr_str[INET6_ADDRSTRLEN]; + + format_ipv6_addr(addr_str, addr); + ds_put_format(string, "%s", addr_str); +} + +struct in6_addr ipv6_addr_bitand(const struct in6_addr *a, + const struct in6_addr *b) +{ + int i; + struct in6_addr dst; + +#ifdef s6_addr32 + for (i=0; i<4; i++) { + dst.s6_addr32[i] = a->s6_addr32[i] & b->s6_addr32[i]; + } +#else + for (i=0; i<16; i++) { + dst.s6_addr[i] = a->s6_addr[i] & b->s6_addr[i]; + } +#endif + + return dst; +} + +/* Returns an in6_addr consisting of 'mask' high-order 1-bits and 128-N + * low-order 0-bits. */ +struct in6_addr +ipv6_create_mask(int mask) +{ + struct in6_addr netmask; + uint8_t *netmaskp = &netmask.s6_addr[0]; + + memset(&netmask, 0, sizeof netmask); + while (mask > 8) { + *netmaskp = 0xff; + netmaskp++; + mask -= 8; + } + + if (mask) { + *netmaskp = 0xff << (8 - 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()). */ +int +ipv6_count_cidr_bits(const struct in6_addr *netmask) +{ + int i; + int count = 0; + const uint8_t *netmaskp = &netmask->s6_addr[0]; + + assert(ipv6_is_cidr(netmask)); + + for (i=0; i<16; i++) { + if (netmaskp[i] == 0xff) { + count += 8; + } else { + uint8_t nm; + + for(nm = netmaskp[i]; nm; nm <<= 1) { + count++; + } + break; + } + + } + + return count; +} + + +/* Returns true if 'netmask' is a CIDR netmask, that is, if it consists of N + * high-order 1-bits and 128-N low-order 0-bits. */ +bool +ipv6_is_cidr(const struct in6_addr *netmask) +{ + const uint8_t *netmaskp = &netmask->s6_addr[0]; + int i; + + for (i=0; i<16; i++) { + if (netmaskp[i] != 0xff) { + uint8_t x = ~netmaskp[i]; + if (x & (x + 1)) { + return false; + } + while (++i < 16) { + if (netmaskp[i]) { + return false; + } + } + } + } + + return true; +}