2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-22 01:51:26 +00:00

Add support for bitwise matching on TCP and UDP ports.

Bug #8827.
Signed-off-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
Ben Pfaff 2012-01-27 17:16:05 -08:00
parent 8e7082b095
commit 73f3356323
12 changed files with 263 additions and 119 deletions

3
NEWS
View File

@ -8,6 +8,9 @@ post-v1.5.0
documented in vswitchd/INTERNALS).
- Load balancing can be disabled by setting the bond-rebalance-interval
to zero.
- OpenFlow:
- Added support for bitwise matching on TCP and UDP ports.
See ovs-ofctl(8) for more information.
- Logging to console and file will have UTC timestamp as a default for all
the daemons. An example of the default format is 2012-01-27T16:35:17Z.
ovs-appctl can be used to change the default format as before.

View File

@ -1398,9 +1398,12 @@ OFP_ASSERT(sizeof(struct nx_action_output_reg) == 24);
*
* Format: 16-bit integer in network byte order.
*
* Masking: Not maskable. */
* Masking: Fully maskable, in Open vSwitch 1.6 and later. Not maskable, in
* earlier versions. */
#define NXM_OF_TCP_SRC NXM_HEADER (0x0000, 9, 2)
#define NXM_OF_TCP_SRC_W NXM_HEADER_W(0x0000, 9, 2)
#define NXM_OF_TCP_DST NXM_HEADER (0x0000, 10, 2)
#define NXM_OF_TCP_DST_W NXM_HEADER_W(0x0000, 10, 2)
/* The source or destination port in the UDP header.
*
@ -1410,9 +1413,12 @@ OFP_ASSERT(sizeof(struct nx_action_output_reg) == 24);
*
* Format: 16-bit integer in network byte order.
*
* Masking: Not maskable. */
* Masking: Fully maskable, in Open vSwitch 1.6 and later. Not maskable, in
* earlier versions. */
#define NXM_OF_UDP_SRC NXM_HEADER (0x0000, 11, 2)
#define NXM_OF_UDP_SRC_W NXM_HEADER_W(0x0000, 11, 2)
#define NXM_OF_UDP_DST NXM_HEADER (0x0000, 12, 2)
#define NXM_OF_UDP_DST_W NXM_HEADER_W(0x0000, 12, 2)
/* The type or code in the ICMP header.
*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2010, 2011 Nicira Networks.
* Copyright (c) 2009, 2010, 2011, 2012 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -252,15 +252,27 @@ cls_rule_set_dl_vlan_pcp(struct cls_rule *rule, uint8_t dl_vlan_pcp)
void
cls_rule_set_tp_src(struct cls_rule *rule, ovs_be16 tp_src)
{
rule->wc.wildcards &= ~FWW_TP_SRC;
rule->flow.tp_src = tp_src;
cls_rule_set_tp_src_masked(rule, tp_src, htons(UINT16_MAX));
}
void
cls_rule_set_tp_src_masked(struct cls_rule *rule, ovs_be16 port, ovs_be16 mask)
{
rule->flow.tp_src = port & mask;
rule->wc.tp_src_mask = mask;
}
void
cls_rule_set_tp_dst(struct cls_rule *rule, ovs_be16 tp_dst)
{
rule->wc.wildcards &= ~FWW_TP_DST;
rule->flow.tp_dst = tp_dst;
cls_rule_set_tp_dst_masked(rule, tp_dst, htons(UINT16_MAX));
}
void
cls_rule_set_tp_dst_masked(struct cls_rule *rule, ovs_be16 port, ovs_be16 mask)
{
rule->flow.tp_dst = port & mask;
rule->wc.tp_dst_mask = mask;
}
void
@ -340,15 +352,13 @@ cls_rule_set_nw_frag_masked(struct cls_rule *rule,
void
cls_rule_set_icmp_type(struct cls_rule *rule, uint8_t icmp_type)
{
rule->wc.wildcards &= ~FWW_TP_SRC;
rule->flow.tp_src = htons(icmp_type);
cls_rule_set_tp_src(rule, htons(icmp_type));
}
void
cls_rule_set_icmp_code(struct cls_rule *rule, uint8_t icmp_code)
{
rule->wc.wildcards &= ~FWW_TP_DST;
rule->flow.tp_dst = htons(icmp_code);
cls_rule_set_tp_dst(rule, htons(icmp_code));
}
void
@ -452,6 +462,23 @@ format_ipv6_netmask(struct ds *s, const char *name,
}
}
static void
format_be16_masked(struct ds *s, const char *name,
ovs_be16 value, ovs_be16 mask)
{
if (mask != htons(0)) {
ds_put_format(s, "%s=", name);
if (mask == htons(UINT16_MAX)) {
ds_put_format(s, "%"PRIu16, ntohs(value));
} else {
ds_put_format(s, "0x%"PRIx16"/0x%"PRIx16,
ntohs(value), ntohs(mask));
}
ds_put_char(s, ',');
}
}
void
cls_rule_format(const struct cls_rule *rule, struct ds *s)
{
@ -464,7 +491,7 @@ cls_rule_format(const struct cls_rule *rule, struct ds *s)
int i;
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 8);
if (rule->priority != OFP_DEFAULT_PRIORITY) {
ds_put_format(s, "priority=%d,", rule->priority);
@ -637,19 +664,11 @@ cls_rule_format(const struct cls_rule *rule, struct ds *s)
break;
}
if (f->nw_proto == IPPROTO_ICMP) {
if (!(w & FWW_TP_SRC)) {
ds_put_format(s, "icmp_type=%"PRIu16",", ntohs(f->tp_src));
}
if (!(w & FWW_TP_DST)) {
ds_put_format(s, "icmp_code=%"PRIu16",", ntohs(f->tp_dst));
}
format_be16_masked(s, "icmp_type", f->tp_src, wc->tp_src_mask);
format_be16_masked(s, "icmp_code", f->tp_dst, wc->tp_dst_mask);
} else if (f->nw_proto == IPPROTO_ICMPV6) {
if (!(w & FWW_TP_SRC)) {
ds_put_format(s, "icmp_type=%"PRIu16",", ntohs(f->tp_src));
}
if (!(w & FWW_TP_DST)) {
ds_put_format(s, "icmp_code=%"PRIu16",", ntohs(f->tp_dst));
}
format_be16_masked(s, "icmp_type", f->tp_src, wc->tp_src_mask);
format_be16_masked(s, "icmp_code", f->tp_dst, wc->tp_dst_mask);
if (!(w & FWW_ND_TARGET)) {
ds_put_cstr(s, "nd_target=");
print_ipv6_addr(s, &f->nd_target);
@ -664,12 +683,8 @@ cls_rule_format(const struct cls_rule *rule, struct ds *s)
ETH_ADDR_ARGS(f->arp_tha));
}
} else {
if (!(w & FWW_TP_SRC)) {
ds_put_format(s, "tp_src=%"PRIu16",", ntohs(f->tp_src));
}
if (!(w & FWW_TP_DST)) {
ds_put_format(s, "tp_dst=%"PRIu16",", ntohs(f->tp_dst));
}
format_be16_masked(s, "tp_src", f->tp_src, wc->tp_src_mask);
format_be16_masked(s, "tp_dst", f->tp_dst, wc->tp_dst_mask);
}
if (s->length > start_len && ds_last(s) == ',') {
@ -1149,7 +1164,7 @@ flow_equal_except(const struct flow *a, const struct flow *b,
const flow_wildcards_t wc = wildcards->wildcards;
int i;
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 8);
for (i = 0; i < FLOW_N_REGS; i++) {
if ((a->regs[i] ^ b->regs[i]) & wildcards->reg_masks[i]) {
@ -1163,8 +1178,8 @@ flow_equal_except(const struct flow *a, const struct flow *b,
&& (wc & FWW_IN_PORT || a->in_port == b->in_port)
&& !((a->vlan_tci ^ b->vlan_tci) & wildcards->vlan_tci_mask)
&& (wc & FWW_DL_TYPE || a->dl_type == b->dl_type)
&& (wc & FWW_TP_SRC || a->tp_src == b->tp_src)
&& (wc & FWW_TP_DST || a->tp_dst == b->tp_dst)
&& !((a->tp_src ^ b->tp_src) & wildcards->tp_src_mask)
&& !((a->tp_dst ^ b->tp_dst) & wildcards->tp_dst_mask)
&& (wc & FWW_DL_SRC || eth_addr_equals(a->dl_src, b->dl_src))
&& (wc & FWW_DL_DST
|| (!((a->dl_dst[0] ^ b->dl_dst[0]) & 0xfe)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2010, 2011 Nicira Networks.
* Copyright (c) 2009, 2010, 2011, 2012 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -110,7 +110,11 @@ void cls_rule_set_dl_vlan(struct cls_rule *, ovs_be16);
void cls_rule_set_any_pcp(struct cls_rule *);
void cls_rule_set_dl_vlan_pcp(struct cls_rule *, uint8_t);
void cls_rule_set_tp_src(struct cls_rule *, ovs_be16);
void cls_rule_set_tp_src_masked(struct cls_rule *,
ovs_be16 port, ovs_be16 mask);
void cls_rule_set_tp_dst(struct cls_rule *, ovs_be16);
void cls_rule_set_tp_dst_masked(struct cls_rule *,
ovs_be16 port, ovs_be16 mask);
void cls_rule_set_nw_proto(struct cls_rule *, uint8_t);
void cls_rule_set_nw_src(struct cls_rule *, ovs_be32);
void cls_rule_set_nw_src_masked(struct cls_rule *, ovs_be32 ip, ovs_be32 mask);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
* Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -444,7 +444,7 @@ flow_zero_wildcards(struct flow *flow, const struct flow_wildcards *wildcards)
const flow_wildcards_t wc = wildcards->wildcards;
int i;
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 8);
for (i = 0; i < FLOW_N_REGS; i++) {
flow->regs[i] &= wildcards->reg_masks[i];
@ -459,12 +459,8 @@ flow_zero_wildcards(struct flow *flow, const struct flow_wildcards *wildcards)
if (wc & FWW_DL_TYPE) {
flow->dl_type = htons(0);
}
if (wc & FWW_TP_SRC) {
flow->tp_src = htons(0);
}
if (wc & FWW_TP_DST) {
flow->tp_dst = htons(0);
}
flow->tp_src &= wildcards->tp_src_mask;
flow->tp_dst &= wildcards->tp_dst_mask;
if (wc & FWW_DL_SRC) {
memset(flow->dl_src, 0, sizeof flow->dl_src);
}
@ -598,7 +594,7 @@ flow_print(FILE *stream, const struct flow *flow)
void
flow_wildcards_init_catchall(struct flow_wildcards *wc)
{
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 8);
wc->wildcards = FWW_ALL;
wc->tun_id_mask = htonll(0);
@ -609,6 +605,8 @@ flow_wildcards_init_catchall(struct flow_wildcards *wc)
memset(wc->reg_masks, 0, sizeof wc->reg_masks);
wc->vlan_tci_mask = htons(0);
wc->nw_frag_mask = 0;
wc->tp_src_mask = htons(0);
wc->tp_dst_mask = htons(0);
memset(wc->zeros, 0, sizeof wc->zeros);
}
@ -617,7 +615,7 @@ flow_wildcards_init_catchall(struct flow_wildcards *wc)
void
flow_wildcards_init_exact(struct flow_wildcards *wc)
{
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 8);
wc->wildcards = 0;
wc->tun_id_mask = htonll(UINT64_MAX);
@ -628,6 +626,8 @@ flow_wildcards_init_exact(struct flow_wildcards *wc)
memset(wc->reg_masks, 0xff, sizeof wc->reg_masks);
wc->vlan_tci_mask = htons(UINT16_MAX);
wc->nw_frag_mask = UINT8_MAX;
wc->tp_src_mask = htons(UINT16_MAX);
wc->tp_dst_mask = htons(UINT16_MAX);
memset(wc->zeros, 0, sizeof wc->zeros);
}
@ -638,12 +638,14 @@ flow_wildcards_is_exact(const struct flow_wildcards *wc)
{
int i;
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 8);
if (wc->wildcards
|| wc->tun_id_mask != htonll(UINT64_MAX)
|| wc->nw_src_mask != htonl(UINT32_MAX)
|| wc->nw_dst_mask != htonl(UINT32_MAX)
|| wc->tp_src_mask != htons(UINT16_MAX)
|| wc->tp_dst_mask != htons(UINT16_MAX)
|| wc->vlan_tci_mask != htons(UINT16_MAX)
|| !ipv6_mask_is_exact(&wc->ipv6_src_mask)
|| !ipv6_mask_is_exact(&wc->ipv6_dst_mask)
@ -667,12 +669,14 @@ flow_wildcards_is_catchall(const struct flow_wildcards *wc)
{
int i;
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 8);
if (wc->wildcards != FWW_ALL
|| wc->tun_id_mask != htonll(0)
|| wc->nw_src_mask != htonl(0)
|| wc->nw_dst_mask != htonl(0)
|| wc->tp_src_mask != htons(0)
|| wc->tp_dst_mask != htons(0)
|| wc->vlan_tci_mask != htons(0)
|| !ipv6_mask_is_any(&wc->ipv6_src_mask)
|| !ipv6_mask_is_any(&wc->ipv6_dst_mask)
@ -699,7 +703,7 @@ flow_wildcards_combine(struct flow_wildcards *dst,
{
int i;
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 8);
dst->wildcards = src1->wildcards | src2->wildcards;
dst->tun_id_mask = src1->tun_id_mask & src2->tun_id_mask;
@ -713,6 +717,8 @@ flow_wildcards_combine(struct flow_wildcards *dst,
dst->reg_masks[i] = src1->reg_masks[i] & src2->reg_masks[i];
}
dst->vlan_tci_mask = src1->vlan_tci_mask & src2->vlan_tci_mask;
dst->tp_src_mask = src1->tp_src_mask & src2->tp_src_mask;
dst->tp_dst_mask = src1->tp_dst_mask & src2->tp_dst_mask;
}
/* Returns a hash of the wildcards in 'wc'. */
@ -734,7 +740,7 @@ flow_wildcards_equal(const struct flow_wildcards *a,
{
int i;
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 8);
if (a->wildcards != b->wildcards
|| a->tun_id_mask != b->tun_id_mask
@ -742,7 +748,9 @@ flow_wildcards_equal(const struct flow_wildcards *a,
|| a->nw_dst_mask != b->nw_dst_mask
|| a->vlan_tci_mask != b->vlan_tci_mask
|| !ipv6_addr_equals(&a->ipv6_src_mask, &b->ipv6_src_mask)
|| !ipv6_addr_equals(&a->ipv6_dst_mask, &b->ipv6_dst_mask)) {
|| !ipv6_addr_equals(&a->ipv6_dst_mask, &b->ipv6_dst_mask)
|| a->tp_src_mask != b->tp_src_mask
|| a->tp_dst_mask != b->tp_dst_mask) {
return false;
}
@ -764,7 +772,7 @@ flow_wildcards_has_extra(const struct flow_wildcards *a,
int i;
struct in6_addr ipv6_masked;
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 8);
for (i = 0; i < FLOW_N_REGS; i++) {
if ((a->reg_masks[i] & b->reg_masks[i]) != b->reg_masks[i]) {
@ -786,7 +794,9 @@ flow_wildcards_has_extra(const struct flow_wildcards *a,
|| (a->tun_id_mask & b->tun_id_mask) != b->tun_id_mask
|| (a->nw_src_mask & b->nw_src_mask) != b->nw_src_mask
|| (a->nw_dst_mask & b->nw_dst_mask) != b->nw_dst_mask
|| (a->vlan_tci_mask & b->vlan_tci_mask) != b->vlan_tci_mask);
|| (a->vlan_tci_mask & b->vlan_tci_mask) != b->vlan_tci_mask
|| (a->tp_src_mask & b->tp_src_mask) != b->tp_src_mask
|| (a->tp_dst_mask & b->tp_dst_mask) != b->tp_dst_mask);
}
/* Sets the wildcard mask for register 'idx' in 'wc' to 'mask'.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
* Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -35,7 +35,7 @@ struct ofpbuf;
/* This sequence number should be incremented whenever anything involving flows
* or the wildcarding of flows changes. This will cause build assertion
* failures in places which likely need to be updated. */
#define FLOW_WC_SEQ 7
#define FLOW_WC_SEQ 8
#define FLOW_N_REGS 5
BUILD_ASSERT_DECL(FLOW_N_REGS <= NXM_NX_MAX_REGS);
@ -100,7 +100,7 @@ BUILD_ASSERT_DECL(sizeof(((struct flow *)0)->nw_frag) == 1);
BUILD_ASSERT_DECL(sizeof(struct flow) == FLOW_SIG_SIZE + FLOW_PAD_SIZE);
/* Remember to update FLOW_WC_SEQ when changing 'struct flow'. */
BUILD_ASSERT_DECL(FLOW_SIG_SIZE == 130 && FLOW_WC_SEQ == 7);
BUILD_ASSERT_DECL(FLOW_SIG_SIZE == 130 && FLOW_WC_SEQ == 8);
void flow_extract(struct ofpbuf *, uint32_t priority, ovs_be64 tun_id,
uint16_t in_port, struct flow *);
@ -152,22 +152,20 @@ typedef unsigned int OVS_BITWISE flow_wildcards_t;
/* excluding the multicast bit */
#define FWW_DL_TYPE ((OVS_FORCE flow_wildcards_t) (1 << 4))
#define FWW_NW_PROTO ((OVS_FORCE flow_wildcards_t) (1 << 5))
#define FWW_TP_SRC ((OVS_FORCE flow_wildcards_t) (1 << 6))
#define FWW_TP_DST ((OVS_FORCE flow_wildcards_t) (1 << 7))
/* No corresponding OFPFW_* bits. */
#define FWW_ETH_MCAST ((OVS_FORCE flow_wildcards_t) (1 << 1))
/* multicast bit only */
#define FWW_NW_DSCP ((OVS_FORCE flow_wildcards_t) (1 << 6))
#define FWW_NW_ECN ((OVS_FORCE flow_wildcards_t) (1 << 7))
#define FWW_ARP_SHA ((OVS_FORCE flow_wildcards_t) (1 << 8))
#define FWW_ARP_THA ((OVS_FORCE flow_wildcards_t) (1 << 9))
#define FWW_ND_TARGET ((OVS_FORCE flow_wildcards_t) (1 << 10))
#define FWW_IPV6_LABEL ((OVS_FORCE flow_wildcards_t) (1 << 11))
#define FWW_NW_TTL ((OVS_FORCE flow_wildcards_t) (1 << 12))
#define FWW_NW_DSCP ((OVS_FORCE flow_wildcards_t) (1 << 13))
#define FWW_NW_ECN ((OVS_FORCE flow_wildcards_t) (1 << 14))
#define FWW_ALL ((OVS_FORCE flow_wildcards_t) (((1 << 15)) - 1))
#define FWW_ALL ((OVS_FORCE flow_wildcards_t) (((1 << 13)) - 1))
/* Remember to update FLOW_WC_SEQ when adding or removing FWW_*. */
BUILD_ASSERT_DECL(FWW_ALL == ((1 << 15) - 1) && FLOW_WC_SEQ == 7);
BUILD_ASSERT_DECL(FWW_ALL == ((1 << 13) - 1) && FLOW_WC_SEQ == 8);
/* Information on wildcards for a flow, as a supplement to "struct flow".
*
@ -182,12 +180,14 @@ struct flow_wildcards {
struct in6_addr ipv6_src_mask; /* 1-bit in each signficant ipv6_src bit. */
struct in6_addr ipv6_dst_mask; /* 1-bit in each signficant ipv6_dst bit. */
ovs_be16 vlan_tci_mask; /* 1-bit in each significant vlan_tci bit. */
ovs_be16 tp_src_mask; /* 1-bit in each significant tp_src bit. */
ovs_be16 tp_dst_mask; /* 1-bit in each significant tp_dst bit. */
uint8_t nw_frag_mask; /* 1-bit in each significant nw_frag bit. */
uint8_t zeros[5]; /* Padding field set to zero. */
uint8_t zeros[1]; /* Padding field set to zero. */
};
/* Remember to update FLOW_WC_SEQ when updating struct flow_wildcards. */
BUILD_ASSERT_DECL(sizeof(struct flow_wildcards) == 80 && FLOW_WC_SEQ == 7);
BUILD_ASSERT_DECL(sizeof(struct flow_wildcards) == 80 && FLOW_WC_SEQ == 8);
void flow_wildcards_init_catchall(struct flow_wildcards *);
void flow_wildcards_init_exact(struct flow_wildcards *);

View File

@ -290,7 +290,7 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
{
MFF_TCP_SRC, "tcp_src", "tp_src",
MF_FIELD_SIZES(be16),
MFM_NONE, FWW_TP_SRC,
MFM_FULLY, 0,
MFS_DECIMAL,
MFP_TCP,
true,
@ -298,7 +298,7 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
}, {
MFF_TCP_DST, "tcp_dst", "tp_dst",
MF_FIELD_SIZES(be16),
MFM_NONE, FWW_TP_DST,
MFM_FULLY, 0,
MFS_DECIMAL,
MFP_TCP,
true,
@ -308,7 +308,7 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
{
MFF_UDP_SRC, "udp_src", NULL,
MF_FIELD_SIZES(be16),
MFM_NONE, FWW_TP_SRC,
MFM_FULLY, 0,
MFS_DECIMAL,
MFP_UDP,
true,
@ -316,7 +316,7 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
}, {
MFF_UDP_DST, "udp_dst", NULL,
MF_FIELD_SIZES(be16),
MFM_NONE, FWW_TP_DST,
MFM_FULLY, 0,
MFS_DECIMAL,
MFP_UDP,
true,
@ -326,7 +326,7 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
{
MFF_ICMPV4_TYPE, "icmp_type", NULL,
MF_FIELD_SIZES(u8),
MFM_NONE, FWW_TP_SRC,
MFM_NONE, 0,
MFS_DECIMAL,
MFP_ICMPV4,
false,
@ -334,7 +334,7 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
}, {
MFF_ICMPV4_CODE, "icmp_code", NULL,
MF_FIELD_SIZES(u8),
MFM_NONE, FWW_TP_DST,
MFM_NONE, 0,
MFS_DECIMAL,
MFP_ICMPV4,
false,
@ -344,7 +344,7 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
{
MFF_ICMPV6_TYPE, "icmpv6_type", NULL,
MF_FIELD_SIZES(u8),
MFM_NONE, FWW_TP_SRC,
MFM_NONE, 0,
MFS_DECIMAL,
MFP_ICMPV6,
false,
@ -352,7 +352,7 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
}, {
MFF_ICMPV6_CODE, "icmpv6_code", NULL,
MF_FIELD_SIZES(u8),
MFM_NONE, FWW_TP_DST,
MFM_NONE, 0,
MFS_DECIMAL,
MFP_ICMPV6,
false,
@ -509,14 +509,6 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
case MFF_ARP_OP:
case MFF_ARP_SHA:
case MFF_ARP_THA:
case MFF_TCP_SRC:
case MFF_TCP_DST:
case MFF_UDP_SRC:
case MFF_UDP_DST:
case MFF_ICMPV4_TYPE:
case MFF_ICMPV4_CODE:
case MFF_ICMPV6_TYPE:
case MFF_ICMPV6_CODE:
case MFF_ND_TARGET:
case MFF_ND_SLL:
case MFF_ND_TLL:
@ -575,6 +567,17 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
case MFF_ARP_TPA:
return !wc->nw_dst_mask;
case MFF_TCP_SRC:
case MFF_UDP_SRC:
case MFF_ICMPV4_TYPE:
case MFF_ICMPV6_TYPE:
return !wc->tp_src_mask;
case MFF_TCP_DST:
case MFF_UDP_DST:
case MFF_ICMPV4_CODE:
case MFF_ICMPV6_CODE:
return !wc->tp_dst_mask;
case MFF_N_IDS:
default:
NOT_REACHED();
@ -603,14 +606,6 @@ mf_get_mask(const struct mf_field *mf, const struct flow_wildcards *wc,
case MFF_ARP_OP:
case MFF_ARP_SHA:
case MFF_ARP_THA:
case MFF_TCP_SRC:
case MFF_TCP_DST:
case MFF_UDP_SRC:
case MFF_UDP_DST:
case MFF_ICMPV4_TYPE:
case MFF_ICMPV4_CODE:
case MFF_ICMPV6_TYPE:
case MFF_ICMPV6_CODE:
case MFF_ND_TARGET:
case MFF_ND_SLL:
case MFF_ND_TLL:
@ -683,6 +678,24 @@ mf_get_mask(const struct mf_field *mf, const struct flow_wildcards *wc,
mask->be32 = wc->nw_dst_mask;
break;
case MFF_TCP_SRC:
case MFF_UDP_SRC:
mask->be16 = wc->tp_src_mask;
break;
case MFF_TCP_DST:
case MFF_UDP_DST:
mask->be16 = wc->tp_dst_mask;
break;
case MFF_ICMPV4_TYPE:
case MFF_ICMPV6_TYPE:
mask->u8 = ntohs(wc->tp_src_mask);
break;
case MFF_ICMPV4_CODE:
case MFF_ICMPV6_CODE:
mask->u8 = ntohs(wc->tp_dst_mask);
break;
case MFF_N_IDS:
default:
NOT_REACHED();
@ -1485,7 +1498,7 @@ mf_set_wild(const struct mf_field *mf, struct cls_rule *rule)
case MFF_UDP_SRC:
case MFF_ICMPV4_TYPE:
case MFF_ICMPV6_TYPE:
rule->wc.wildcards |= FWW_TP_SRC;
rule->wc.tp_src_mask = htons(0);
rule->flow.tp_src = htons(0);
break;
@ -1493,7 +1506,7 @@ mf_set_wild(const struct mf_field *mf, struct cls_rule *rule)
case MFF_UDP_DST:
case MFF_ICMPV4_CODE:
case MFF_ICMPV6_CODE:
rule->wc.wildcards |= FWW_TP_DST;
rule->wc.tp_dst_mask = htons(0);
rule->flow.tp_dst = htons(0);
break;
@ -1546,10 +1559,6 @@ mf_set(const struct mf_field *mf,
case MFF_ARP_OP:
case MFF_ARP_SHA:
case MFF_ARP_THA:
case MFF_TCP_SRC:
case MFF_TCP_DST:
case MFF_UDP_SRC:
case MFF_UDP_DST:
case MFF_ICMPV4_TYPE:
case MFF_ICMPV4_CODE:
case MFF_ICMPV6_TYPE:
@ -1623,6 +1632,16 @@ mf_set(const struct mf_field *mf,
cls_rule_set_nw_dst_masked(rule, value->be32, mask->be32);
break;
case MFF_TCP_SRC:
case MFF_UDP_SRC:
cls_rule_set_tp_src_masked(rule, value->be16, mask->be16);
break;
case MFF_TCP_DST:
case MFF_UDP_DST:
cls_rule_set_tp_dst_masked(rule, value->be16, mask->be16);
break;
case MFF_N_IDS:
default:
NOT_REACHED();

View File

@ -433,24 +433,16 @@ nxm_put_ip(struct ofpbuf *b, const struct cls_rule *cr,
nxm_put_8(b, NXM_OF_IP_PROTO, flow->nw_proto);
if (flow->nw_proto == IPPROTO_TCP) {
if (!(wc & FWW_TP_SRC)) {
nxm_put_16(b, NXM_OF_TCP_SRC, flow->tp_src);
}
if (!(wc & FWW_TP_DST)) {
nxm_put_16(b, NXM_OF_TCP_DST, flow->tp_dst);
}
nxm_put_16m(b, NXM_OF_TCP_SRC, flow->tp_src, cr->wc.tp_src_mask);
nxm_put_16m(b, NXM_OF_TCP_DST, flow->tp_dst, cr->wc.tp_dst_mask);
} else if (flow->nw_proto == IPPROTO_UDP) {
if (!(wc & FWW_TP_SRC)) {
nxm_put_16(b, NXM_OF_UDP_SRC, flow->tp_src);
}
if (!(wc & FWW_TP_DST)) {
nxm_put_16(b, NXM_OF_UDP_DST, flow->tp_dst);
}
nxm_put_16m(b, NXM_OF_UDP_SRC, flow->tp_src, cr->wc.tp_src_mask);
nxm_put_16m(b, NXM_OF_UDP_DST, flow->tp_dst, cr->wc.tp_dst_mask);
} else if (flow->nw_proto == icmp_proto) {
if (!(wc & FWW_TP_SRC)) {
if (cr->wc.tp_src_mask) {
nxm_put_8(b, icmp_type, ntohs(flow->tp_src));
}
if (!(wc & FWW_TP_DST)) {
if (cr->wc.tp_dst_mask) {
nxm_put_8(b, icmp_code, ntohs(flow->tp_dst));
}
}
@ -479,7 +471,7 @@ nx_put_match(struct ofpbuf *b, const struct cls_rule *cr,
int match_len;
int i;
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 8);
/* Metadata. */
if (!(wc & FWW_IN_PORT)) {

View File

@ -78,9 +78,7 @@ ofputil_netmask_to_wcbits(ovs_be32 netmask)
WC_INVARIANT_BIT(DL_SRC) \
WC_INVARIANT_BIT(DL_DST) \
WC_INVARIANT_BIT(DL_TYPE) \
WC_INVARIANT_BIT(NW_PROTO) \
WC_INVARIANT_BIT(TP_SRC) \
WC_INVARIANT_BIT(TP_DST)
WC_INVARIANT_BIT(NW_PROTO)
/* Verify that all of the invariant bits (as defined on WC_INVARIANT_LIST)
* actually have the same names and values. */
@ -102,7 +100,7 @@ static const flow_wildcards_t WC_INVARIANTS = 0
void
ofputil_wildcard_from_openflow(uint32_t ofpfw, struct flow_wildcards *wc)
{
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 8);
/* Initialize most of rule->wc. */
flow_wildcards_init_catchall(wc);
@ -121,6 +119,13 @@ ofputil_wildcard_from_openflow(uint32_t ofpfw, struct flow_wildcards *wc)
wc->nw_src_mask = ofputil_wcbits_to_netmask(ofpfw >> OFPFW_NW_SRC_SHIFT);
wc->nw_dst_mask = ofputil_wcbits_to_netmask(ofpfw >> OFPFW_NW_DST_SHIFT);
if (!(ofpfw & OFPFW_TP_SRC)) {
wc->tp_src_mask = htons(UINT16_MAX);
}
if (!(ofpfw & OFPFW_TP_DST)) {
wc->tp_dst_mask = htons(UINT16_MAX);
}
if (ofpfw & OFPFW_DL_DST) {
/* OpenFlow 1.0 OFPFW_DL_DST covers the whole Ethernet destination, but
* Open vSwitch breaks the Ethernet destination into bits as FWW_DL_DST
@ -200,6 +205,12 @@ ofputil_cls_rule_to_match(const struct cls_rule *rule, struct ofp_match *match)
if (wc->wildcards & FWW_NW_DSCP) {
ofpfw |= OFPFW_NW_TOS;
}
if (!wc->tp_src_mask) {
ofpfw |= OFPFW_TP_SRC;
}
if (!wc->tp_dst_mask) {
ofpfw |= OFPFW_TP_DST;
}
/* Translate VLANs. */
match->dl_vlan = htons(0);
@ -905,7 +916,7 @@ ofputil_min_flow_format(const struct cls_rule *rule)
{
const struct flow_wildcards *wc = &rule->wc;
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 8);
/* Only NXM supports separately wildcards the Ethernet multicast bit. */
if (!(wc->wildcards & FWW_DL_DST) != !(wc->wildcards & FWW_ETH_MCAST)) {
@ -953,6 +964,12 @@ ofputil_min_flow_format(const struct cls_rule *rule)
return NXFF_NXM;
}
/* 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))) {
return NXFF_NXM;
}
/* Other formats can express this rule. */
return NXFF_OPENFLOW10;
}
@ -2735,7 +2752,7 @@ ofputil_normalize_rule(struct cls_rule *rule, enum nx_flow_format flow_format)
wc.nw_src_mask = wc.nw_dst_mask = htonl(0);
}
if (!(may_match & MAY_TP_ADDR)) {
wc.wildcards |= FWW_TP_SRC | FWW_TP_DST;
wc.tp_src_mask = wc.tp_dst_mask = htons(0);
}
if (!(may_match & MAY_NW_PROTO)) {
wc.wildcards |= FWW_NW_PROTO;

View File

@ -10,7 +10,7 @@ tcp,nw_src=192.168.0.3,tp_dst=80 actions=set_queue:37,output:1
udp,nw_src=192.168.0.3,tp_dst=53 actions=pop_queue,output:1
cookie=0x123456789abcdef hard_timeout=10 priority=60000 actions=controller
actions=note:41.42.43,note:00.01.02.03.04.05.06.07,note
tun_id=0x1234,cookie=0x5678,actions=flood
tcp,tp_src=0x1230/0xfff0,tun_id=0x1234,cookie=0x5678,actions=flood
actions=set_tunnel:0x1234,set_tunnel64:0x9876,set_tunnel:0x123456789
actions=multipath(eth_src, 50, hrw, 12, 0, NXM_NX_REG0[0..3]),multipath(symmetric_l4, 1024, iter_hash, 5000, 5050, NXM_NX_REG0[0..12])
table=1,actions=drop
@ -40,7 +40,7 @@ OFPT_FLOW_MOD: ADD udp,nw_src=192.168.0.3,tp_dst=53 actions=pop_queue,output:1
OFPT_FLOW_MOD: ADD priority=60000 cookie:0x123456789abcdef hard:10 actions=CONTROLLER:65535
OFPT_FLOW_MOD: ADD actions=note:41.42.43.00.00.00,note:00.01.02.03.04.05.06.07.00.00.00.00.00.00,note:00.00.00.00.00.00
NXT_SET_FLOW_FORMAT: format=nxm
NXT_FLOW_MOD: ADD tun_id=0x1234 cookie:0x5678 actions=FLOOD
NXT_FLOW_MOD: ADD tcp,tun_id=0x1234,tp_src=0x1230/0xfff0 cookie:0x5678 actions=FLOOD
NXT_FLOW_MOD: ADD actions=set_tunnel:0x1234,set_tunnel64:0x9876,set_tunnel64:0x123456789
NXT_FLOW_MOD: ADD actions=multipath(eth_src,50,hrw,12,0,NXM_NX_REG0[0..3]),multipath(symmetric_l4,1024,iter_hash,5000,5050,NXM_NX_REG0[0..12])
NXT_FLOW_MOD_TABLE_ID: enable
@ -243,18 +243,22 @@ NXM_OF_ETH_TYPE(0806) NXM_OF_IP_DST_W(C0D80000/FFFF0000)
# TCP source port
NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(06) NXM_OF_TCP_SRC(4231)
NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(06) NXM_OF_TCP_SRC_W(5050/F0F0)
NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(07) NXM_OF_TCP_SRC(4231)
# TCP destination port
NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(06) NXM_OF_TCP_DST(4231)
NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(06) NXM_OF_TCP_DST_W(FDE0/FFF0)
NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(07) NXM_OF_TCP_DST(4231)
# UDP source port
NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(11) NXM_OF_UDP_SRC(8732)
NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(11) NXM_OF_UDP_SRC_W(0132/01FF)
NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(06) NXM_OF_UDP_SRC(7823)
# UDP destination port
NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(11) NXM_OF_UDP_DST(1782)
NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(11) NXM_OF_UDP_DST_W(5005/F00F)
NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(02) NXM_OF_UDP_DST(1293)
# ICMP type
@ -436,18 +440,22 @@ nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
# TCP source port
NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(06), NXM_OF_TCP_SRC(4231)
NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(06), NXM_OF_TCP_SRC_W(5050/f0f0)
nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
# TCP destination port
NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(06), NXM_OF_TCP_DST(4231)
NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(06), NXM_OF_TCP_DST_W(fde0/fff0)
nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
# UDP source port
NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(11), NXM_OF_UDP_SRC(8732)
NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(11), NXM_OF_UDP_SRC_W(0132/01ff)
nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
# UDP destination port
NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(11), NXM_OF_UDP_DST(1782)
NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(11), NXM_OF_UDP_DST_W(5005/f00f)
nx_pull_match() returned error NXBRC_NXM_BAD_PREREQ
# ICMP type

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2010, 2011 Nicira Networks.
* Copyright (c) 2009, 2010, 2011, 2012 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -50,8 +50,8 @@
CLS_FIELD(FWW_IN_PORT, in_port, IN_PORT) \
CLS_FIELD(0, vlan_tci, VLAN_TCI) \
CLS_FIELD(FWW_DL_TYPE, dl_type, DL_TYPE) \
CLS_FIELD(FWW_TP_SRC, tp_src, TP_SRC) \
CLS_FIELD(FWW_TP_DST, tp_dst, TP_DST) \
CLS_FIELD(0, tp_src, TP_SRC) \
CLS_FIELD(0, tp_dst, TP_DST) \
CLS_FIELD(FWW_DL_SRC, dl_src, DL_SRC) \
CLS_FIELD(FWW_DL_DST | FWW_ETH_MCAST, dl_dst, DL_DST) \
CLS_FIELD(FWW_NW_PROTO, nw_proto, NW_PROTO) \
@ -198,6 +198,10 @@ match(const struct cls_rule *wild, const struct flow *fixed)
eq = !((fixed->nw_src ^ wild->flow.nw_src) & wild->wc.nw_src_mask);
} else if (f_idx == CLS_F_IDX_NW_DST) {
eq = !((fixed->nw_dst ^ wild->flow.nw_dst) & wild->wc.nw_dst_mask);
} else if (f_idx == CLS_F_IDX_TP_SRC) {
eq = !((fixed->tp_src ^ wild->flow.tp_src) & wild->wc.tp_src_mask);
} else if (f_idx == CLS_F_IDX_TP_DST) {
eq = !((fixed->tp_dst ^ wild->flow.tp_dst) & wild->wc.tp_dst_mask);
} else if (f_idx == CLS_F_IDX_VLAN_TCI) {
eq = !((fixed->vlan_tci ^ wild->flow.vlan_tci)
& wild->wc.vlan_tci_mask);
@ -463,6 +467,10 @@ make_rule(int wc_fields, unsigned int priority, int value_pat)
rule->cls_rule.wc.nw_src_mask = htonl(UINT32_MAX);
} else if (f_idx == CLS_F_IDX_NW_DST) {
rule->cls_rule.wc.nw_dst_mask = htonl(UINT32_MAX);
} else if (f_idx == CLS_F_IDX_TP_SRC) {
rule->cls_rule.wc.tp_src_mask = htons(UINT16_MAX);
} else if (f_idx == CLS_F_IDX_TP_DST) {
rule->cls_rule.wc.tp_dst_mask = htons(UINT16_MAX);
} else if (f_idx == CLS_F_IDX_VLAN_TCI) {
rule->cls_rule.wc.vlan_tci_mask = htons(UINT16_MAX);
} else if (f_idx == CLS_F_IDX_TUN_ID) {

View File

@ -443,13 +443,75 @@ above).
.IQ \fBtp_dst=\fIport\fR
When \fBdl_type\fR and \fBnw_proto\fR specify TCP or UDP, \fBtp_src\fR
and \fBtp_dst\fR match the UDP or TCP source or destination port
\fIport\fR, respectively. which is specified as a decimal number
\fIport\fR, respectively, which is specified as a decimal number
between 0 and 65535, inclusive (e.g. 80 to match packets originating
from a HTTP server).
.IP
When \fBdl_type\fR and \fBnw_proto\fR take other values, the values of
these settings are ignored (see \fBFlow Syntax\fR above).
.
.IP \fBtp_src=\fIport\fB/\fImask\fR
.IQ \fBtp_dst=\fIport\fB/\fImask\fR
Bitwise match on TCP (or UDP) source or destination port,
respectively. The \fIport\fR and \fImask\fR are 16-bit numbers
written in decimal or in hexadecimal prefixed by \fB0x\fR. Each 1-bit
in \fImask\fR requires that the corresponding bit in \fIport\fR must
match. Each 0-bit in \fImask\fR causes the corresponding bit to be
ignored.
.IP
Bitwise matches on transport ports are rarely useful in isolation, but
a group of them can be used to reduce the number of flows required to
match on a range of transport ports. For example, suppose that the
goal is to match TCP source ports 1000 to 1999, inclusive. One way is
to insert 1001 flows, each of which matches on a single source port.
Another way is to look at the binary representations of 1000 and 1999,
as follows:
.br
.B "01111101000"
.br
.B "11111001111"
.br
and then to transform those into a series of bitwise matches that
accomplish the same results:
.br
.B "01111101xxx"
.br
.B "0111111xxxx"
.br
.B "10xxxxxxxxx"
.br
.B "110xxxxxxxx"
.br
.B "1110xxxxxxx"
.br
.B "11110xxxxxx"
.br
.B "1111100xxxx"
.br
which become the following when written in the syntax required by
\fBovs\-ofctl\fR:
.br
.B "tcp,tp_src=0x03e8/0xfff8"
.br
.B "tcp,tp_src=0x03f0/0xfff0"
.br
.B "tcp,tp_src=0x0400/0xfe00"
.br
.B "tcp,tp_src=0x0600/0xff00"
.br
.B "tcp,tp_src=0x0700/0xff80"
.br
.B "tcp,tp_src=0x0780/0xffc0"
.br
.B "tcp,tp_src=0x07c0/0xfff0"
.IP
Only Open vSwitch 1.6 and later supports bitwise matching on transport
ports.
.IP
Like the exact-match forms of \fBtp_src\fR and \fBtp_dst\fR described
above, the bitwise match forms apply only when When \fBdl_type\fR and
\fBnw_proto\fR specify TCP or UDP.
.
.IP \fBicmp_type=\fItype\fR
.IQ \fBicmp_code=\fIcode\fR
When \fBdl_type\fR and \fBnw_proto\fR specify ICMP or ICMPv6, \fItype\fR