[ovs-dev] [of1.1 rollup 06/20] Allow general masking of IPv4 addresses rather than just CIDR masks.

Ben Pfaff blp at nicira.com
Tue Jun 12 07:32:10 UTC 2012


OF1.1 and later make these fields fully maskable so we might as well also.

Signed-off-by: Ben Pfaff <blp at nicira.com>
---
 NEWS                          |    8 +++++++-
 include/openflow/nicira-ext.h |    6 ++++--
 lib/meta-flow.c               |    8 ++++----
 lib/ofp-util.c                |   17 ++++++++++-------
 lib/packets.c                 |    7 ++++---
 tests/ovs-ofctl.at            |   18 ++++++++++++++----
 utilities/ovs-ofctl.8.in      |    4 +++-
 7 files changed, 46 insertions(+), 22 deletions(-)

diff --git a/NEWS b/NEWS
index 8cd38dd..24ba8fc 100644
--- a/NEWS
+++ b/NEWS
@@ -2,7 +2,13 @@ post-v1.7.0
 ------------------------
     - 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
diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h
index 2280e73..9401376 100644
--- a/include/openflow/nicira-ext.h
+++ b/include/openflow/nicira-ext.h
@@ -1461,7 +1461,8 @@ OFP_ASSERT(sizeof(struct nx_action_output_reg) == 24);
  *
  * 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)
@@ -1530,7 +1531,8 @@ OFP_ASSERT(sizeof(struct nx_action_output_reg) == 24);
  *
  * 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)
diff --git a/lib/meta-flow.c b/lib/meta-flow.c
index b97af30..32707e3 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
@@ -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),
-        MFM_CIDR, 0,
+        MFM_FULLY, 0,
         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),
-        MFM_CIDR, 0,
+        MFM_FULLY, 0,
         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),
-        MFM_CIDR, 0,
+        MFM_FULLY, 0,
         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),
-        MFM_CIDR, 0,
+        MFM_FULLY, 0,
         MFS_IPV4,
         MFP_ARP,
         false,
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 4af7a1f..5bd220b 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -64,8 +64,11 @@ ofputil_wcbits_to_netmask(int wcbits)
 }
 
 /* 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)
 {
@@ -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 (!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);
     }
@@ -1497,6 +1495,11 @@ ofputil_usable_protocols(const struct cls_rule *rule)
         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))) {
diff --git a/lib/packets.c b/lib/packets.c
index bbf4934..833074c 100644
--- a/lib/packets.c
+++ b/lib/packets.c
@@ -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
- * 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)
 {
-    assert(ip_is_cidr(netmask));
     return 32 - ctz(ntohl(netmask));
 }
 
diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
index 740892c..a2ec7f9 100644
--- a/tests/ovs-ofctl.at
+++ b/tests/ovs-ofctl.at
@@ -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)
+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(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)
 
@@ -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)
+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(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)
 
@@ -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)
+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)
+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
 
@@ -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)
+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)
+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
 
@@ -765,8 +773,9 @@ dnl Try invalid TOS:
 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
@@ -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
 
-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
diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in
index 085a2c2..4d34bd4 100644
--- a/utilities/ovs-ofctl.8.in
+++ b/utilities/ovs-ofctl.8.in
@@ -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
-(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
-- 
1.7.2.5




More information about the dev mailing list