From: Ben Pfaff Date: Wed, 23 May 2012 05:49:31 +0000 (-0700) Subject: Allow general masking of IPv6 addresses rather than just CIDR masks. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ff0b06eef1d7044df8220ccbed718a6fae55fc10;p=openvswitch Allow general masking of IPv6 addresses rather than just CIDR masks. OF1.2 and later make these fields fully maskable so we might as well also. Reviewed-by: Simon Horman Signed-off-by: Ben Pfaff --- diff --git a/NEWS b/NEWS index b5dd6c3e..28e3cf04 100644 --- a/NEWS +++ b/NEWS @@ -4,8 +4,8 @@ post-v1.7.0 - ovs-ofctl: - "mod-port" command can now control all OpenFlow config flags. - OpenFlow: - - Allow general bitwise masking for IPv4 source and destination - addresses in IPv4 and ARP packets. (Previously, only CIDR masks + - Allow general bitwise masking for IPv4 and IPv6 addresses in + IPv4, IPv6, and ARP packets. (Previously, only CIDR masks were allowed.) - Allow support for arbitrary Ethernet masks. (Previously, only the multicast bit in the destination address could be individually diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h index 9401376a..2f46311f 100644 --- a/include/openflow/nicira-ext.h +++ b/include/openflow/nicira-ext.h @@ -1608,7 +1608,8 @@ OFP_ASSERT(sizeof(struct nx_action_output_reg) == 24); * * Format: 128-bit IPv6 address. * - * Masking: Only CIDR masks are allowed, that is, masks that consist of N + * Masking: Fully maskable, in Open vSwitch 1.8 and later. In previous + * versions, only CIDR masks are allowed, that is, masks that consist of N * high-order bits set to 1 and the other 128-N bits set to 0. */ #define NXM_NX_IPV6_SRC NXM_HEADER (0x0001, 19, 16) #define NXM_NX_IPV6_SRC_W NXM_HEADER_W(0x0001, 19, 16) @@ -1636,7 +1637,8 @@ OFP_ASSERT(sizeof(struct nx_action_output_reg) == 24); * * Format: 128-bit IPv6 address. * - * Masking: Only CIDR masks are allowed, that is, masks that consist of N + * Masking: Fully maskable, in Open vSwitch 1.8 and later. In previous + * versions, only CIDR masks are allowed, that is, masks that consist of N * high-order bits set to 1 and the other 128-N bits set to 0. */ #define NXM_NX_ND_TARGET NXM_HEADER (0x0001, 23, 16) #define NXM_NX_ND_TARGET_W NXM_HEADER_W (0x0001, 23, 16) diff --git a/lib/meta-flow.c b/lib/meta-flow.c index 32707e33..b3a4bffa 100644 --- a/lib/meta-flow.c +++ b/lib/meta-flow.c @@ -195,7 +195,7 @@ static const struct mf_field mf_fields[MFF_N_IDS] = { { MFF_IPV6_SRC, "ipv6_src", NULL, MF_FIELD_SIZES(ipv6), - MFM_CIDR, 0, + MFM_FULLY, 0, MFS_IPV6, MFP_IPV6, true, @@ -204,7 +204,7 @@ static const struct mf_field mf_fields[MFF_N_IDS] = { }, { MFF_IPV6_DST, "ipv6_dst", NULL, MF_FIELD_SIZES(ipv6), - MFM_CIDR, 0, + MFM_FULLY, 0, MFS_IPV6, MFP_IPV6, true, @@ -407,7 +407,7 @@ static const struct mf_field mf_fields[MFF_N_IDS] = { { MFF_ND_TARGET, "nd_target", NULL, MF_FIELD_SIZES(ipv6), - MFM_CIDR, 0, + MFM_FULLY, 0, MFS_IPV6, MFP_ND, false, @@ -814,11 +814,6 @@ mf_is_mask_valid(const struct mf_field *mf, const union mf_value *mask) case MFM_FULLY: return true; - - case MFM_CIDR: - return (mf->n_bytes == 4 - ? ip_is_cidr(mask->be32) - : ipv6_is_cidr(&mask->ipv6)); } NOT_REACHED(); @@ -2091,12 +2086,14 @@ mf_from_ipv6_string(const struct mf_field *mf, const char *s, netmask = strtok_r(NULL, "/", &save_ptr); if (netmask) { - int prefix = atoi(netmask); - if (prefix <= 0 || prefix > 128) { - free(str); - return xasprintf("%s: prefix bits not between 1 and 128", s); - } else { - *mask = ipv6_create_mask(prefix); + if (inet_pton(AF_INET6, netmask, mask) != 1) { + int prefix = atoi(netmask); + if (prefix <= 0 || prefix > 128) { + free(str); + return xasprintf("%s: prefix bits not between 1 and 128", s); + } else { + *mask = ipv6_create_mask(prefix); + } } } else { *mask = in6addr_exact; diff --git a/lib/meta-flow.h b/lib/meta-flow.h index 29e3fa79..ffde5cc3 100644 --- a/lib/meta-flow.h +++ b/lib/meta-flow.h @@ -144,7 +144,6 @@ enum mf_prereqs { enum mf_maskable { MFM_NONE, /* No sub-field masking. */ MFM_FULLY, /* Every bit is individually maskable. */ - MFM_CIDR /* Contiguous low-order bits may be masked. */ }; /* How to format or parse a field's value. */ diff --git a/lib/packets.c b/lib/packets.c index 833074cc..57291674 100644 --- a/lib/packets.c +++ b/lib/packets.c @@ -350,7 +350,10 @@ ipv6_create_mask(int mask) /* 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()). */ + * 'netmask' must be a CIDR netmask (see ipv6_is_cidr()). + * + * If 'netmask' is not a CIDR netmask (see ipv6_is_cidr()), the return value + * will still be in the valid range but isn't otherwise meaningful. */ int ipv6_count_cidr_bits(const struct in6_addr *netmask) { @@ -358,8 +361,6 @@ ipv6_count_cidr_bits(const struct in6_addr *netmask) 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; diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at index a2ec7f92..a4fa7e46 100644 --- a/tests/ovs-ofctl.at +++ b/tests/ovs-ofctl.at @@ -350,14 +350,21 @@ NXM_NX_ARP_THA(0002e30f80a4) NXM_OF_ETH_TYPE(86dd) NXM_NX_IPV6_SRC(20010db83c4d00010002000300040005) NXM_OF_ETH_TYPE(0800) NXM_NX_IPV6_SRC(20010db83c4d00010002000300040005) NXM_OF_ETH_TYPE(86dd) NXM_NX_IPV6_SRC_W(20010db83c4d00010000000000000000/ffffffffffffffff0000000000000000) +NXM_OF_ETH_TYPE(86dd) NXM_NX_IPV6_SRC_W(20010db83c4d00010000000000000000/5a5a5a5a5a5a5a5a0000000000000000) NXM_OF_ETH_TYPE(0800) NXM_NX_IPV6_SRC_W(20010db83c4d00010000000000000000/ffffffffffffffff0000000000000000) # IPv6 destination NXM_OF_ETH_TYPE(86dd) NXM_NX_IPV6_DST(20010db83c4d00010002000300040005) NXM_OF_ETH_TYPE(0800) NXM_NX_IPV6_DST(20010db83c4d00010002000300040005) -NXM_OF_ETH_TYPE(86dd) NXM_NX_IPV6_DST_W(20010db83c4d00010000000000000000/ffffffffffffffff0000000000000000) +NXM_OF_ETH_TYPE(86dd) NXM_NX_IPV6_DST_W(20010db83c4d00010000000000000000/77777777777777777777777777777777) NXM_OF_ETH_TYPE(0800) NXM_NX_IPV6_DST_W(20010db83c4d00010000000000000000/ffffffffffffffff0000000000000000) +# ND target address +NXM_OF_ETH_TYPE(86dd) NXM_OF_IP_PROTO(3a) NXM_NX_ICMPV6_TYPE(87) NXM_NX_ND_TARGET(20010db83c4d00010002000300040005) +NXM_OF_ETH_TYPE(86dd) NXM_OF_IP_PROTO(3a) NXM_NX_ICMPV6_TYPE(88) NXM_NX_ND_TARGET(20010db83c4d00010002000300040005) +NXM_OF_ETH_TYPE(86dd) NXM_OF_IP_PROTO(3a) NXM_NX_ICMPV6_TYPE(87) NXM_NX_ND_TARGET_W(20010db83c4d00010002000300040005/0123456789abcdeffedcba9876543210) +NXM_OF_ETH_TYPE(86dd) NXM_OF_IP_PROTO(3a) NXM_NX_ICMPV6_TYPE(88) NXM_NX_ND_TARGET_W(20010db83c4d00010002000300040005/fedcba98765432100123456789abcdef) + # ND source hardware address NXM_OF_ETH_TYPE(86dd) NXM_OF_IP_PROTO(3a) NXM_NX_ICMPV6_TYPE(87) NXM_NX_ND_TARGET(20010db83c4d00010002000300040005) NXM_NX_ND_SLL(0002e30f80a4) NXM_OF_ETH_TYPE(86dd) NXM_OF_IP_PROTO(3a) NXM_NX_ICMPV6_TYPE(88) NXM_NX_ND_TARGET(20010db83c4d00010002000300040005) NXM_NX_ND_SLL(0002e30f80a4) @@ -554,14 +561,21 @@ nx_pull_match() returned error OFPBMC_BAD_PREREQ NXM_OF_ETH_TYPE(86dd), NXM_NX_IPV6_SRC(20010db83c4d00010002000300040005) nx_pull_match() returned error OFPBMC_BAD_PREREQ NXM_OF_ETH_TYPE(86dd), NXM_NX_IPV6_SRC_W(20010db83c4d00010000000000000000/ffffffffffffffff0000000000000000) +NXM_OF_ETH_TYPE(86dd), NXM_NX_IPV6_SRC_W(00000818184800000000000000000000/5a5a5a5a5a5a5a5a0000000000000000) nx_pull_match() returned error OFPBMC_BAD_PREREQ # IPv6 destination NXM_OF_ETH_TYPE(86dd), NXM_NX_IPV6_DST(20010db83c4d00010002000300040005) nx_pull_match() returned error OFPBMC_BAD_PREREQ -NXM_OF_ETH_TYPE(86dd), NXM_NX_IPV6_DST_W(20010db83c4d00010000000000000000/ffffffffffffffff0000000000000000) +NXM_OF_ETH_TYPE(86dd), NXM_NX_IPV6_DST_W(20010530344500010000000000000000/77777777777777777777777777777777) nx_pull_match() returned error OFPBMC_BAD_PREREQ +# ND target address +NXM_OF_ETH_TYPE(86dd), NXM_OF_IP_PROTO(3a), NXM_NX_ICMPV6_TYPE(87), NXM_NX_ND_TARGET(20010db83c4d00010002000300040005) +NXM_OF_ETH_TYPE(86dd), NXM_OF_IP_PROTO(3a), NXM_NX_ICMPV6_TYPE(88), NXM_NX_ND_TARGET(20010db83c4d00010002000300040005) +NXM_OF_ETH_TYPE(86dd), NXM_OF_IP_PROTO(3a), NXM_NX_ICMPV6_TYPE(87), NXM_NX_ND_TARGET_W(00010520080900010000000000040000/0123456789abcdeffedcba9876543210) +NXM_OF_ETH_TYPE(86dd), NXM_OF_IP_PROTO(3a), NXM_NX_ICMPV6_TYPE(88), NXM_NX_ND_TARGET_W(20000898344400000002000300000005/fedcba98765432100123456789abcdef) + # ND source hardware address NXM_OF_ETH_TYPE(86dd), NXM_OF_IP_PROTO(3a), NXM_NX_ICMPV6_TYPE(87), NXM_NX_ND_TARGET(20010db83c4d00010002000300040005), NXM_NX_ND_SLL(0002e30f80a4) nx_pull_match() returned error OFPBMC_BAD_PREREQ diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in index 4d34bd46..9c4ea0c2 100644 --- a/utilities/ovs-ofctl.8.in +++ b/utilities/ovs-ofctl.8.in @@ -676,7 +676,11 @@ which may be specified as defined in RFC 2373. The preferred format is address. A single instance of \fB::\fR may be used to indicate multiple groups of 16-bits of zeros. The optional \fInetmask\fR allows restricting a match to an IPv6 address prefix. A netmask is specified -as a CIDR block (e.g. \fB2001:db8:3c4d:1::/64\fR). +as an IPv6 address (e.g. \fB2001:db8:3c4d:1::/ffff:ffff:ffff:ffff::\fR) +or a CIDR block (e.g. \fB2001:db8:3c4d:1::/64\fR). Open vSwitch 1.8 +and later support arbitrary masks; earlier versions support only CIDR +masks, that is, CIDR block and IPv6 addresses that are equivalent to +CIDR blocks. . .IP \fBipv6_label=\fIlabel\fR When \fBdl_type\fR is 0x86dd (possibly via shorthand, e.g., \fBipv6\fR