aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Pfaff <blp@nicira.com>2012-05-22 22:49:31 -0700
committerBen Pfaff <blp@nicira.com>2012-06-12 21:19:25 -0700
commitff0b06eef1d7044df8220ccbed718a6fae55fc10 (patch)
treef83e6f68d2c89a392711b51309586e3708e6ef0a
parentc08201d6645520f384bbfee3b490b99af8f2c149 (diff)
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 <horms@verge.net.au> Signed-off-by: Ben Pfaff <blp@nicira.com>
-rw-r--r--NEWS4
-rw-r--r--include/openflow/nicira-ext.h6
-rw-r--r--lib/meta-flow.c25
-rw-r--r--lib/meta-flow.h1
-rw-r--r--lib/packets.c7
-rw-r--r--tests/ovs-ofctl.at18
-rw-r--r--utilities/ovs-ofctl.8.in6
7 files changed, 42 insertions, 25 deletions
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