From c08201d6645520f384bbfee3b490b99af8f2c149 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 22 May 2012 22:06:03 -0700 Subject: [PATCH] Allow general masking of IPv4 addresses rather than just CIDR masks. OF1.1 and later make these fields fully maskable so we might as well also. Reviewed-by: Simon Horman Signed-off-by: Ben Pfaff --- 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 f5b7ad52..b5dd6c3e 100644 --- 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. - - 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 2280e738..9401376a 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 b97af309..32707e33 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 4af7a1ff..5bd220b6 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 bbf49344..833074cc 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 740892cb..a2ec7f92 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 085a2c25..4d34bd46 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 -- 2.30.2