Allow general masking of IPv4 addresses rather than just CIDR masks.
authorBen Pfaff <blp@nicira.com>
Wed, 23 May 2012 05:06:03 +0000 (22:06 -0700)
committerBen Pfaff <blp@nicira.com>
Wed, 13 Jun 2012 04:19:22 +0000 (21:19 -0700)
OF1.1 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>
NEWS
include/openflow/nicira-ext.h
lib/meta-flow.c
lib/ofp-util.c
lib/packets.c
tests/ovs-ofctl.at
utilities/ovs-ofctl.8.in

diff --git a/NEWS b/NEWS
index f5b7ad52d478b2dc8e8aa24d21ffdd53b7e227ff..b5dd6c3eaeee1dcf8ddc363564d808b3104fbb8d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,7 +3,13 @@ post-v1.7.0
     - New FAQ.  Please send updates and additions!
     - ovs-ofctl:
         - "mod-port" command can now control all OpenFlow config flags.
     - New FAQ.  Please send updates and additions!
     - ovs-ofctl:
         - "mod-port" command can now control all OpenFlow config flags.
-    - Added support for arbitrary ethernet masks
+    - OpenFlow:
+      - Allow general bitwise masking for IPv4 source and destination
+        addresses in IPv4 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
+       masked.)
     - Additional protocols are not mirrored and dropped when forward-bpdu is
       false.  For a full list, see the ovs-vswitchd.conf.db man page.
     - Open vSwitch now sends RARP packets in situations where it previously
     - Additional protocols are not mirrored and dropped when forward-bpdu is
       false.  For a full list, see the ovs-vswitchd.conf.db man page.
     - Open vSwitch now sends RARP packets in situations where it previously
index 2280e738af2dcc0fd847e86fbab2f11c2451e72e..9401376a63fefa5b8a5d152f3848a202e8bb5559 100644 (file)
@@ -1461,7 +1461,8 @@ OFP_ASSERT(sizeof(struct nx_action_output_reg) == 24);
  *
  * Format: 32-bit integer in network byte order.
  *
  *
  * Format: 32-bit integer in network byte order.
  *
- * Masking: Only CIDR masks are allowed, that is, masks that consist of N
+ * Masking: Fully maskable, in Open vSwitch 1.8 and later.  In earlier
+ *   versions, only CIDR masks are allowed, that is, masks that consist of N
  *   high-order bits set to 1 and the other 32-N bits set to 0. */
 #define NXM_OF_IP_SRC     NXM_HEADER  (0x0000,  7, 4)
 #define NXM_OF_IP_SRC_W   NXM_HEADER_W(0x0000,  7, 4)
  *   high-order bits set to 1 and the other 32-N bits set to 0. */
 #define NXM_OF_IP_SRC     NXM_HEADER  (0x0000,  7, 4)
 #define NXM_OF_IP_SRC_W   NXM_HEADER_W(0x0000,  7, 4)
@@ -1530,7 +1531,8 @@ OFP_ASSERT(sizeof(struct nx_action_output_reg) == 24);
  *
  * Format: 32-bit integer in network byte order.
  *
  *
  * Format: 32-bit integer in network byte order.
  *
- * Masking: Only CIDR masks are allowed, that is, masks that consist of N
+ * Masking: Fully maskable, in Open vSwitch 1.8 and later.  In earlier
+ *   versions, only CIDR masks are allowed, that is, masks that consist of N
  *   high-order bits set to 1 and the other 32-N bits set to 0. */
 #define NXM_OF_ARP_SPA    NXM_HEADER  (0x0000, 16, 4)
 #define NXM_OF_ARP_SPA_W  NXM_HEADER_W(0x0000, 16, 4)
  *   high-order bits set to 1 and the other 32-N bits set to 0. */
 #define NXM_OF_ARP_SPA    NXM_HEADER  (0x0000, 16, 4)
 #define NXM_OF_ARP_SPA_W  NXM_HEADER_W(0x0000, 16, 4)
index b97af30965e293be045a522aca5a459d8eb64d0b..32707e33f1495b23be4e4126675b41169c702b1d 100644 (file)
@@ -175,7 +175,7 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
     {
         MFF_IPV4_SRC, "ip_src", "nw_src",
         MF_FIELD_SIZES(be32),
     {
         MFF_IPV4_SRC, "ip_src", "nw_src",
         MF_FIELD_SIZES(be32),
-        MFM_CIDR, 0,
+        MFM_FULLY, 0,
         MFS_IPV4,
         MFP_IPV4,
         true,
         MFS_IPV4,
         MFP_IPV4,
         true,
@@ -184,7 +184,7 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
     }, {
         MFF_IPV4_DST, "ip_dst", "nw_dst",
         MF_FIELD_SIZES(be32),
     }, {
         MFF_IPV4_DST, "ip_dst", "nw_dst",
         MF_FIELD_SIZES(be32),
-        MFM_CIDR, 0,
+        MFM_FULLY, 0,
         MFS_IPV4,
         MFP_IPV4,
         true,
         MFS_IPV4,
         MFP_IPV4,
         true,
@@ -281,7 +281,7 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
     }, {
         MFF_ARP_SPA, "arp_spa", NULL,
         MF_FIELD_SIZES(be32),
     }, {
         MFF_ARP_SPA, "arp_spa", NULL,
         MF_FIELD_SIZES(be32),
-        MFM_CIDR, 0,
+        MFM_FULLY, 0,
         MFS_IPV4,
         MFP_ARP,
         false,
         MFS_IPV4,
         MFP_ARP,
         false,
@@ -290,7 +290,7 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
     }, {
         MFF_ARP_TPA, "arp_tpa", NULL,
         MF_FIELD_SIZES(be32),
     }, {
         MFF_ARP_TPA, "arp_tpa", NULL,
         MF_FIELD_SIZES(be32),
-        MFM_CIDR, 0,
+        MFM_FULLY, 0,
         MFS_IPV4,
         MFP_ARP,
         false,
         MFS_IPV4,
         MFP_ARP,
         false,
index 4af7a1ff2b15e43789852f4d2d1504af371d8225..5bd220b6a59286ed74b8c7b9b51e4024f04df992 100644 (file)
@@ -64,8 +64,11 @@ ofputil_wcbits_to_netmask(int wcbits)
 }
 
 /* Given the IP netmask 'netmask', returns the number of bits of the IP address
 }
 
 /* Given the IP netmask 'netmask', returns the number of bits of the IP address
- * that it wildcards, that is, the number of 0-bits in 'netmask'.  'netmask'
- * must be a CIDR netmask (see ip_is_cidr()). */
+ * that it wildcards, that is, the number of 0-bits in 'netmask', a number
+ * between 0 and 32 inclusive.
+ *
+ * If 'netmask' is not a CIDR netmask (see ip_is_cidr()), the return value will
+ * still be in the valid range but isn't otherwise meaningful. */
 int
 ofputil_netmask_to_wcbits(ovs_be32 netmask)
 {
 int
 ofputil_netmask_to_wcbits(ovs_be32 netmask)
 {
@@ -348,11 +351,6 @@ ofputil_cls_rule_from_ofp11_match(const struct ofp11_match *match,
         if (!(wc & OFPFW11_NW_PROTO)) {
             cls_rule_set_nw_proto(rule, match->nw_proto);
         }
         if (!(wc & OFPFW11_NW_PROTO)) {
             cls_rule_set_nw_proto(rule, match->nw_proto);
         }
-
-        if (!ip_is_cidr(~match->nw_src_mask) ||
-            !ip_is_cidr(~match->nw_dst_mask)) {
-            return OFPERR_OFPBMC_BAD_NW_ADDR_MASK;
-        }
         cls_rule_set_nw_src_masked(rule, match->nw_src, ~match->nw_src_mask);
         cls_rule_set_nw_dst_masked(rule, match->nw_dst, ~match->nw_dst_mask);
     }
         cls_rule_set_nw_src_masked(rule, match->nw_src, ~match->nw_src_mask);
         cls_rule_set_nw_dst_masked(rule, match->nw_dst, ~match->nw_dst_mask);
     }
@@ -1497,6 +1495,11 @@ ofputil_usable_protocols(const struct cls_rule *rule)
         return OFPUTIL_P_NXM_ANY;
     }
 
         return OFPUTIL_P_NXM_ANY;
     }
 
+    /* Only NXM supports non-CIDR IPv4 address masks. */
+    if (!ip_is_cidr(wc->nw_src_mask) || !ip_is_cidr(wc->nw_dst_mask)) {
+        return OFPUTIL_P_NXM_ANY;
+    }
+
     /* Only NXM supports bitwise matching on transport port. */
     if ((wc->tp_src_mask && wc->tp_src_mask != htons(UINT16_MAX)) ||
         (wc->tp_dst_mask && wc->tp_dst_mask != htons(UINT16_MAX))) {
     /* Only NXM supports bitwise matching on transport port. */
     if ((wc->tp_src_mask && wc->tp_src_mask != htons(UINT16_MAX)) ||
         (wc->tp_dst_mask && wc->tp_dst_mask != htons(UINT16_MAX))) {
index bbf4934401b52c75ace8ac51d1f0865828333e94..833074cc5fc863f582929a88916d1de453c79be0 100644 (file)
@@ -246,12 +246,13 @@ eth_addr_bitand(const uint8_t src[ETH_ADDR_LEN],
 }
 
 /* Given the IP netmask 'netmask', returns the number of bits of the IP address
 }
 
 /* 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()). */
+ * that it specifies, that is, the number of 1-bits in 'netmask'.
+ *
+ * If 'netmask' is not a CIDR netmask (see ip_is_cidr()), the return value will
+ * still be in the valid range but isn't otherwise meaningful. */
 int
 ip_count_cidr_bits(ovs_be32 netmask)
 {
 int
 ip_count_cidr_bits(ovs_be32 netmask)
 {
-    assert(ip_is_cidr(netmask));
     return 32 - ctz(ntohl(netmask));
 }
 
     return 32 - ctz(ntohl(netmask));
 }
 
index 740892cb8c229f4ec61a51810437b5446e717985..a2ec7f92b69b481668535d698241d5b0ec2256e2 100644 (file)
@@ -274,12 +274,14 @@ NXM_NX_IP_TTL(80)
 # IP source
 NXM_OF_ETH_TYPE(0800) NXM_OF_IP_SRC(ac100014)
 NXM_OF_ETH_TYPE(0800) NXM_OF_IP_SRC_W(C0a80000/FFFF0000)
 # IP source
 NXM_OF_ETH_TYPE(0800) NXM_OF_IP_SRC(ac100014)
 NXM_OF_ETH_TYPE(0800) NXM_OF_IP_SRC_W(C0a80000/FFFF0000)
+NXM_OF_ETH_TYPE(0800) NXM_OF_IP_SRC_W(C0a80000/5a5a5a5a)
 NXM_OF_ETH_TYPE(0806) NXM_OF_IP_SRC(ac100014)
 NXM_OF_IP_SRC_W(C0D80000/FFFF0000)
 
 # IP destination
 NXM_OF_ETH_TYPE(0800) NXM_OF_IP_DST(ac100014)
 NXM_OF_ETH_TYPE(0800) NXM_OF_IP_DST_W(C0a88012/FFFF0000)
 NXM_OF_ETH_TYPE(0806) NXM_OF_IP_SRC(ac100014)
 NXM_OF_IP_SRC_W(C0D80000/FFFF0000)
 
 # IP destination
 NXM_OF_ETH_TYPE(0800) NXM_OF_IP_DST(ac100014)
 NXM_OF_ETH_TYPE(0800) NXM_OF_IP_DST_W(C0a88012/FFFF0000)
+NXM_OF_ETH_TYPE(0800) NXM_OF_IP_DST_W(C0a80000/5a5a5a5a)
 NXM_OF_IP_DST(ac100014)
 NXM_OF_ETH_TYPE(0806) NXM_OF_IP_DST_W(C0D80000/FFFF0000)
 
 NXM_OF_IP_DST(ac100014)
 NXM_OF_ETH_TYPE(0806) NXM_OF_IP_DST_W(C0D80000/FFFF0000)
 
@@ -323,12 +325,14 @@ NXM_OF_ETH_TYPE(0806) NXM_OF_ARP_OP(0001) NXM_OF_ARP_OP(0001)
 # ARP source protocol address
 NXM_OF_ETH_TYPE(0806) NXM_OF_ARP_SPA(ac100014)
 NXM_OF_ETH_TYPE(0806) NXM_OF_ARP_SPA_W(C0a81234/FFFFFF00)
 # ARP source protocol address
 NXM_OF_ETH_TYPE(0806) NXM_OF_ARP_SPA(ac100014)
 NXM_OF_ETH_TYPE(0806) NXM_OF_ARP_SPA_W(C0a81234/FFFFFF00)
+NXM_OF_ETH_TYPE(0806) NXM_OF_ARP_SPA_W(C0a81234/aaaaaa00)
 NXM_OF_ETH_TYPE(0800) NXM_OF_ARP_SPA(ac100014)
 NXM_OF_ARP_SPA_W(C0D8fedc/FFFF0000)
 
 # ARP destination protocol address
 NXM_OF_ETH_TYPE(0806) NXM_OF_ARP_TPA(ac100014)
 NXM_OF_ETH_TYPE(0806) NXM_OF_ARP_TPA_W(C0a812fe/FFFFFF00)
 NXM_OF_ETH_TYPE(0800) NXM_OF_ARP_SPA(ac100014)
 NXM_OF_ARP_SPA_W(C0D8fedc/FFFF0000)
 
 # ARP destination protocol address
 NXM_OF_ETH_TYPE(0806) NXM_OF_ARP_TPA(ac100014)
 NXM_OF_ETH_TYPE(0806) NXM_OF_ARP_TPA_W(C0a812fe/FFFFFF00)
+NXM_OF_ETH_TYPE(0806) NXM_OF_ARP_TPA_W(C0a81234/77777777)
 NXM_OF_ETH_TYPE(0800) NXM_OF_ARP_TPA(ac100014)
 NXM_OF_ARP_TPA_W(C0D80000/FFFF0000)
 
 NXM_OF_ETH_TYPE(0800) NXM_OF_ARP_TPA(ac100014)
 NXM_OF_ARP_TPA_W(C0D80000/FFFF0000)
 
@@ -474,12 +478,14 @@ nx_pull_match() returned error OFPBMC_BAD_PREREQ
 # IP source
 NXM_OF_ETH_TYPE(0800), NXM_OF_IP_SRC(ac100014)
 NXM_OF_ETH_TYPE(0800), NXM_OF_IP_SRC_W(c0a80000/ffff0000)
 # IP source
 NXM_OF_ETH_TYPE(0800), NXM_OF_IP_SRC(ac100014)
 NXM_OF_ETH_TYPE(0800), NXM_OF_IP_SRC_W(c0a80000/ffff0000)
+NXM_OF_ETH_TYPE(0800), NXM_OF_IP_SRC_W(40080000/5a5a5a5a)
 nx_pull_match() returned error OFPBMC_BAD_PREREQ
 nx_pull_match() returned error OFPBMC_BAD_PREREQ
 
 # IP destination
 NXM_OF_ETH_TYPE(0800), NXM_OF_IP_DST(ac100014)
 NXM_OF_ETH_TYPE(0800), NXM_OF_IP_DST_W(c0a80000/ffff0000)
 nx_pull_match() returned error OFPBMC_BAD_PREREQ
 nx_pull_match() returned error OFPBMC_BAD_PREREQ
 
 # IP destination
 NXM_OF_ETH_TYPE(0800), NXM_OF_IP_DST(ac100014)
 NXM_OF_ETH_TYPE(0800), NXM_OF_IP_DST_W(c0a80000/ffff0000)
+NXM_OF_ETH_TYPE(0800), NXM_OF_IP_DST_W(40080000/5a5a5a5a)
 nx_pull_match() returned error OFPBMC_BAD_PREREQ
 nx_pull_match() returned error OFPBMC_BAD_PREREQ
 
 nx_pull_match() returned error OFPBMC_BAD_PREREQ
 nx_pull_match() returned error OFPBMC_BAD_PREREQ
 
@@ -523,12 +529,14 @@ nx_pull_match() returned error OFPBMC_DUP_FIELD
 # ARP source protocol address
 NXM_OF_ETH_TYPE(0806), NXM_OF_ARP_SPA(ac100014)
 NXM_OF_ETH_TYPE(0806), NXM_OF_ARP_SPA_W(c0a81200/ffffff00)
 # ARP source protocol address
 NXM_OF_ETH_TYPE(0806), NXM_OF_ARP_SPA(ac100014)
 NXM_OF_ETH_TYPE(0806), NXM_OF_ARP_SPA_W(c0a81200/ffffff00)
+NXM_OF_ETH_TYPE(0806), NXM_OF_ARP_SPA_W(80a80200/aaaaaa00)
 nx_pull_match() returned error OFPBMC_BAD_PREREQ
 nx_pull_match() returned error OFPBMC_BAD_PREREQ
 
 # ARP destination protocol address
 NXM_OF_ETH_TYPE(0806), NXM_OF_ARP_TPA(ac100014)
 NXM_OF_ETH_TYPE(0806), NXM_OF_ARP_TPA_W(c0a81200/ffffff00)
 nx_pull_match() returned error OFPBMC_BAD_PREREQ
 nx_pull_match() returned error OFPBMC_BAD_PREREQ
 
 # ARP destination protocol address
 NXM_OF_ETH_TYPE(0806), NXM_OF_ARP_TPA(ac100014)
 NXM_OF_ETH_TYPE(0806), NXM_OF_ARP_TPA_W(c0a81200/ffffff00)
+NXM_OF_ETH_TYPE(0806), NXM_OF_ARP_TPA_W(40201234/77777777)
 nx_pull_match() returned error OFPBMC_BAD_PREREQ
 nx_pull_match() returned error OFPBMC_BAD_PREREQ
 
 nx_pull_match() returned error OFPBMC_BAD_PREREQ
 nx_pull_match() returned error OFPBMC_BAD_PREREQ
 
@@ -765,8 +773,9 @@ dnl Try invalid TOS:
 0000 00 00 0800 00 00 c0a88000000000ff 00000000ffffffff 0000 0000 dnl
 00000000 00 000000 0000000000000000ffffffffffffffff
 
 0000 00 00 0800 00 00 c0a88000000000ff 00000000ffffffff 0000 0000 dnl
 00000000 00 000000 0000000000000000ffffffffffffffff
 
-dnl Try non-CIDR nw_src_mask:
-# bad ofp11_match: OFPBMC_BAD_NW_ADDR_MASK
+# ip,nw_src=128.160.128.0/165.165.165.165
+# 44: c0 -> 80
+# 45: a8 -> a0
 0000 0058 00000000 000003f7 dnl
 000000000000ffffffffffff 000000000000ffffffffffff dnl
 0000 00 00 0800 00 00 c0a880005a5a5a5a 00000000ffffffff 0000 0000 dnl
 0000 0058 00000000 000003f7 dnl
 000000000000ffffffffffff 000000000000ffffffffffff dnl
 0000 00 00 0800 00 00 c0a880005a5a5a5a 00000000ffffffff 0000 0000 dnl
@@ -778,8 +787,9 @@ dnl Try non-CIDR nw_src_mask:
 0000 00 00 0800 00 00 00000000ffffffff c0a88000000000ff 0000 0000 dnl
 00000000 00 000000 0000000000000000ffffffffffffffff
 
 0000 00 00 0800 00 00 00000000ffffffff c0a88000000000ff 0000 0000 dnl
 00000000 00 000000 0000000000000000ffffffffffffffff
 
-dnl Try non-CIDR nw_dst_mask:
-# bad ofp11_match: OFPBMC_BAD_NW_ADDR_MASK
+# ip,nw_dst=128.160.128.0/165.165.165.165
+# 52: c0 -> 80
+# 53: a8 -> a0
 0000 0058 00000000 000003f7 dnl
 000000000000ffffffffffff 000000000000ffffffffffff dnl
 0000 00 00 0800 00 00 00000000ffffffff c0a880005a5a5a5a 0000 0000 dnl
 0000 0058 00000000 000003f7 dnl
 000000000000ffffffffffff 000000000000ffffffffffff dnl
 0000 00 00 0800 00 00 00000000ffffffff c0a880005a5a5a5a 0000 0000 dnl
index 085a2c2583a1a43de3f4c0fd7a420879b495155c..4d34bd461d005eb73cd5ae791506deeab0d6f198 100644 (file)
@@ -418,7 +418,9 @@ which may be specified as an IP address or host name
 \fInetmask\fR allows restricting a match to an IPv4 address prefix.
 The netmask may be specified as a dotted quad
 (e.g. \fB192.168.1.0/255.255.255.0\fR) or as a CIDR block
 \fInetmask\fR allows restricting a match to an IPv4 address prefix.
 The netmask may be specified as a dotted quad
 (e.g. \fB192.168.1.0/255.255.255.0\fR) or as a CIDR block
-(e.g. \fB192.168.1.0/24\fR).
+(e.g. \fB192.168.1.0/24\fR).  Open vSwitch 1.8 and later support
+arbitrary dotted quad masks; earlier versions support only CIDR masks,
+that is, the dotted quads that are equivalent to some CIDR block.
 .IP
 When \fBdl_type=0x0806\fR or \fBarp\fR is specified, matches the
 \fBar_spa\fR or \fBar_tpa\fR field, respectively, in ARP packets for
 .IP
 When \fBdl_type=0x0806\fR or \fBarp\fR is specified, matches the
 \fBar_spa\fR or \fBar_tpa\fR field, respectively, in ARP packets for