void
cls_rule_set_nw_dscp(struct cls_rule *rule, uint8_t nw_dscp)
{
- rule->wc.nw_tos_mask |= IP_DSCP_MASK;
+ rule->wc.wildcards &= ~FWW_NW_DSCP;
rule->flow.nw_tos &= ~IP_DSCP_MASK;
rule->flow.nw_tos |= nw_dscp & IP_DSCP_MASK;
}
void
cls_rule_set_nw_ecn(struct cls_rule *rule, uint8_t nw_ecn)
{
- rule->wc.nw_tos_mask |= IP_ECN_MASK;
+ rule->wc.wildcards &= ~FWW_NW_ECN;
rule->flow.nw_tos &= ~IP_ECN_MASK;
rule->flow.nw_tos |= nw_ecn & IP_ECN_MASK;
}
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 6);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
if (rule->priority != OFP_DEFAULT_PRIORITY) {
ds_put_format(s, "priority=%d,", rule->priority);
ETH_ADDR_ARGS(f->arp_tha));
}
}
- if (wc->nw_tos_mask & IP_DSCP_MASK) {
+ if (!(w & FWW_NW_DSCP)) {
ds_put_format(s, "nw_tos=%"PRIu8",", f->nw_tos & IP_DSCP_MASK);
}
- if (wc->nw_tos_mask & IP_ECN_MASK) {
+ if (!(w & FWW_NW_ECN)) {
ds_put_format(s, "nw_ecn=%"PRIu8",", f->nw_tos & IP_ECN_MASK);
}
if (!(w & FWW_NW_TTL)) {
const flow_wildcards_t wc = wildcards->wildcards;
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 6);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
for (i = 0; i < FLOW_N_REGS; i++) {
if ((a->regs[i] ^ b->regs[i]) & wildcards->reg_masks[i]) {
|| !((a->dl_dst[0] ^ b->dl_dst[0]) & 0x01))
&& (wc & FWW_NW_PROTO || a->nw_proto == b->nw_proto)
&& (wc & FWW_NW_TTL || a->nw_ttl == b->nw_ttl)
- && !((a->nw_tos ^ b->nw_tos) & wildcards->nw_tos_mask)
+ && (wc & FWW_NW_DSCP || !((a->nw_tos ^ b->nw_tos) & IP_DSCP_MASK))
+ && (wc & FWW_NW_ECN || !((a->nw_tos ^ b->nw_tos) & IP_ECN_MASK))
&& !((a->nw_frag ^ b->nw_frag) & wildcards->nw_frag_mask)
&& (wc & FWW_ARP_SHA || eth_addr_equals(a->arp_sha, b->arp_sha))
&& (wc & FWW_ARP_THA || eth_addr_equals(a->arp_tha, b->arp_tha))
const flow_wildcards_t wc = wildcards->wildcards;
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 6);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
for (i = 0; i < FLOW_N_REGS; i++) {
flow->regs[i] &= wildcards->reg_masks[i];
if (wc & FWW_IPV6_LABEL) {
flow->ipv6_label = htonl(0);
}
- flow->nw_tos &= wildcards->nw_tos_mask;
+ if (wc & FWW_NW_DSCP) {
+ flow->nw_tos &= ~IP_DSCP_MASK;
+ }
+ if (wc & FWW_NW_ECN) {
+ flow->nw_tos &= ~IP_ECN_MASK;
+ }
if (wc & FWW_NW_TTL) {
flow->nw_ttl = 0;
}
void
flow_wildcards_init_catchall(struct flow_wildcards *wc)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 6);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
wc->wildcards = FWW_ALL;
wc->tun_id_mask = htonll(0);
wc->ipv6_dst_mask = in6addr_any;
memset(wc->reg_masks, 0, sizeof wc->reg_masks);
wc->vlan_tci_mask = htons(0);
- wc->nw_tos_mask = 0;
wc->nw_frag_mask = 0;
memset(wc->zeros, 0, sizeof wc->zeros);
}
void
flow_wildcards_init_exact(struct flow_wildcards *wc)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 6);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
wc->wildcards = 0;
wc->tun_id_mask = htonll(UINT64_MAX);
wc->ipv6_dst_mask = in6addr_exact;
memset(wc->reg_masks, 0xff, sizeof wc->reg_masks);
wc->vlan_tci_mask = htons(UINT16_MAX);
- wc->nw_tos_mask = UINT8_MAX;
wc->nw_frag_mask = UINT8_MAX;
memset(wc->zeros, 0, sizeof wc->zeros);
}
{
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 6);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
if (wc->wildcards
|| wc->tun_id_mask != htonll(UINT64_MAX)
|| wc->vlan_tci_mask != htons(UINT16_MAX)
|| !ipv6_mask_is_exact(&wc->ipv6_src_mask)
|| !ipv6_mask_is_exact(&wc->ipv6_dst_mask)
- || wc->nw_tos_mask != UINT8_MAX
|| wc->nw_frag_mask != UINT8_MAX) {
return false;
}
{
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 6);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
if (wc->wildcards != FWW_ALL
|| wc->tun_id_mask != htonll(0)
|| wc->vlan_tci_mask != htons(0)
|| !ipv6_mask_is_any(&wc->ipv6_src_mask)
|| !ipv6_mask_is_any(&wc->ipv6_dst_mask)
- || wc->nw_tos_mask != 0
|| wc->nw_frag_mask != 0) {
return false;
}
/* 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 6
+#define FLOW_WC_SEQ 7
#define FLOW_N_REGS 5
BUILD_ASSERT_DECL(FLOW_N_REGS <= NXM_NX_MAX_REGS);
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 == 6);
+BUILD_ASSERT_DECL(FLOW_SIG_SIZE == 130 && FLOW_WC_SEQ == 7);
void flow_extract(struct ofpbuf *, uint32_t priority, ovs_be64 tun_id,
uint16_t in_port, struct flow *);
#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_ALL ((OVS_FORCE flow_wildcards_t) (((1 << 13)) - 1))
+#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))
/* Remember to update FLOW_WC_SEQ when adding or removing FWW_*. */
-BUILD_ASSERT_DECL(FWW_ALL == ((1 << 13) - 1) && FLOW_WC_SEQ == 6);
+BUILD_ASSERT_DECL(FWW_ALL == ((1 << 15) - 1) && FLOW_WC_SEQ == 7);
/* Information on wildcards for a flow, as a supplement to "struct flow".
*
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. */
- uint8_t nw_tos_mask; /* 1-bit in each significant nw_tos bit. */
uint8_t nw_frag_mask; /* 1-bit in each significant nw_frag bit. */
- uint8_t zeros[4]; /* Padding field set to zero. */
+ uint8_t zeros[5]; /* 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 == 6);
+BUILD_ASSERT_DECL(sizeof(struct flow_wildcards) == 80 && FLOW_WC_SEQ == 7);
void flow_wildcards_init_catchall(struct flow_wildcards *);
void flow_wildcards_init_exact(struct flow_wildcards *);
}, {
MFF_IP_DSCP, "nw_tos", NULL,
MF_FIELD_SIZES(u8),
- MFM_NONE, 0,
+ MFM_NONE, FWW_NW_DSCP,
MFS_DECIMAL,
MFP_IP_ANY,
NXM_OF_IP_TOS,
}, {
MFF_IP_ECN, "nw_ecn", NULL,
1, 2,
- MFM_NONE, 0,
+ MFM_NONE, FWW_NW_ECN,
MFS_DECIMAL,
MFP_IP_ANY,
NXM_NX_IP_ECN,
case MFF_ETH_SRC:
case MFF_ETH_TYPE:
case MFF_IP_PROTO:
+ case MFF_IP_DSCP:
+ case MFF_IP_ECN:
case MFF_IP_TTL:
case MFF_IPV6_LABEL:
case MFF_ARP_OP:
case MFF_IPV6_DST:
return ipv6_mask_is_any(&wc->ipv6_dst_mask);
- case MFF_IP_DSCP:
- return !(wc->nw_tos_mask & IP_DSCP_MASK);
- case MFF_IP_ECN:
- return !(wc->nw_tos_mask & IP_ECN_MASK);
case MFF_IP_FRAG:
return !(wc->nw_frag_mask & FLOW_NW_FRAG_MASK);
case MFF_ETH_SRC:
case MFF_ETH_TYPE:
case MFF_IP_PROTO:
+ case MFF_IP_DSCP:
+ case MFF_IP_ECN:
case MFF_IP_TTL:
case MFF_IPV6_LABEL:
case MFF_ARP_OP:
mask->ipv6 = wc->ipv6_dst_mask;
break;
- case MFF_IP_DSCP:
- mask->u8 = wc->nw_tos_mask & IP_DSCP_MASK;
- break;
- case MFF_IP_ECN:
- mask->u8 = wc->nw_tos_mask & IP_ECN_MASK;
- break;
case MFF_IP_FRAG:
mask->u8 = wc->nw_frag_mask & FLOW_NW_FRAG_MASK;
break;
break;
case MFF_IP_DSCP:
- rule->wc.nw_tos_mask |= IP_DSCP_MASK;
+ rule->wc.wildcards |= FWW_NW_DSCP;
rule->flow.nw_tos &= ~IP_DSCP_MASK;
break;
case MFF_IP_ECN:
- rule->wc.nw_tos_mask |= IP_ECN_MASK;
+ rule->wc.wildcards |= FWW_NW_ECN;
rule->flow.nw_tos &= ~IP_ECN_MASK;
break;
int match_len;
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 6);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
/* Metadata. */
if (!(wc & FWW_IN_PORT)) {
nxm_put_32m(b, NXM_OF_IP_DST, flow->nw_dst, cr->wc.nw_dst_mask);
nxm_put_frag(b, cr);
- if (cr->wc.nw_tos_mask & IP_DSCP_MASK) {
+ if (!(wc & FWW_NW_DSCP)) {
nxm_put_8(b, NXM_OF_IP_TOS, flow->nw_tos & IP_DSCP_MASK);
}
- if (cr->wc.nw_tos_mask & IP_ECN_MASK) {
+ if (!(wc & FWW_NW_ECN)) {
nxm_put_8(b, NXM_NX_IP_ECN, flow->nw_tos & IP_ECN_MASK);
}
nxm_put_32(b, NXM_NX_IPV6_LABEL, flow->ipv6_label);
}
- if (cr->wc.nw_tos_mask & IP_DSCP_MASK) {
+ if (!(wc & FWW_NW_DSCP)) {
nxm_put_8(b, NXM_OF_IP_TOS, flow->nw_tos & IP_DSCP_MASK);
}
- if (cr->wc.nw_tos_mask & IP_ECN_MASK) {
+ if (!(wc & FWW_NW_ECN)) {
nxm_put_8(b, NXM_NX_IP_ECN, flow->nw_tos & IP_ECN_MASK);
}
void
ofputil_wildcard_from_openflow(uint32_t ofpfw, struct flow_wildcards *wc)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 6);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
/* Initialize most of rule->wc. */
flow_wildcards_init_catchall(wc);
wc->wildcards = (OVS_FORCE flow_wildcards_t) ofpfw & WC_INVARIANTS;
/* Wildcard fields that aren't defined by ofp_match or tun_id. */
- wc->wildcards |= (FWW_ARP_SHA | FWW_ARP_THA | FWW_NW_TTL
+ wc->wildcards |= (FWW_ARP_SHA | FWW_ARP_THA | FWW_NW_ECN | FWW_NW_TTL
| FWW_ND_TARGET | FWW_IPV6_LABEL);
- if (!(ofpfw & OFPFW_NW_TOS)) {
- wc->nw_tos_mask |= IP_DSCP_MASK;
+ if (ofpfw & OFPFW_NW_TOS) {
+ /* OpenFlow 1.0 defines a TOS wildcard, but it's much later in
+ * the enum than we can use. */
+ wc->wildcards |= FWW_NW_DSCP;
}
wc->nw_src_mask = ofputil_wcbits_to_netmask(ofpfw >> OFPFW_NW_SRC_SHIFT);
ofpfw = (OVS_FORCE uint32_t) (wc->wildcards & WC_INVARIANTS);
ofpfw |= ofputil_netmask_to_wcbits(wc->nw_src_mask) << OFPFW_NW_SRC_SHIFT;
ofpfw |= ofputil_netmask_to_wcbits(wc->nw_dst_mask) << OFPFW_NW_DST_SHIFT;
- if (!(wc->nw_tos_mask & IP_DSCP_MASK)) {
+ if (wc->wildcards & FWW_NW_DSCP) {
ofpfw |= OFPFW_NW_TOS;
}
{
const struct flow_wildcards *wc = &rule->wc;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 6);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 7);
/* Only NXM supports separately wildcards the Ethernet multicast bit. */
if (!(wc->wildcards & FWW_DL_DST) != !(wc->wildcards & FWW_ETH_MCAST)) {
}
/* Only NXM supports matching IP ECN bits. */
- if (wc->nw_tos_mask & IP_ECN_MASK) {
+ if (!(wc->wildcards & FWW_NW_ECN)) {
return NXFF_NXM;
}
wc.wildcards |= FWW_NW_PROTO;
}
if (!(may_match & MAY_IPVx)) {
- wc.nw_tos_mask = 0;
- wc.nw_frag_mask = 0;
+ wc.wildcards |= FWW_NW_DSCP;
+ wc.wildcards |= FWW_NW_ECN;
wc.wildcards |= FWW_NW_TTL;
}
if (!(may_match & MAY_ARP_SHA)) {
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) \
- CLS_FIELD(0, nw_tos, NW_TOS)
+ CLS_FIELD(FWW_NW_DSCP, nw_tos, NW_DSCP)
/* Field indexes.
*
& wild->wc.vlan_tci_mask);
} else if (f_idx == CLS_F_IDX_TUN_ID) {
eq = !((fixed->tun_id ^ wild->flow.tun_id) & wild->wc.tun_id_mask);
- } else if (f_idx == CLS_F_IDX_NW_TOS) {
- eq = !((fixed->nw_tos ^ wild->flow.nw_tos)
- & wild->wc.nw_tos_mask);
+ } else if (f_idx == CLS_F_IDX_NW_DSCP) {
+ eq = !((fixed->nw_tos ^ wild->flow.nw_tos) & IP_DSCP_MASK);
} else {
NOT_REACHED();
}
static uint8_t dl_dst_values[][6] = { { 0x4a, 0x27, 0x71, 0xae, 0x64, 0xc1 },
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
static uint8_t nw_proto_values[] = { IPPROTO_TCP, IPPROTO_ICMP };
-static uint8_t nw_tos_values[] = { 48, 0 };
+static uint8_t nw_dscp_values[] = { 48, 0 };
static void *values[CLS_N_FIELDS][2];
values[CLS_F_IDX_NW_PROTO][0] = &nw_proto_values[0];
values[CLS_F_IDX_NW_PROTO][1] = &nw_proto_values[1];
- values[CLS_F_IDX_NW_TOS][0] = &nw_tos_values[0];
- values[CLS_F_IDX_NW_TOS][1] = &nw_tos_values[1];
+ values[CLS_F_IDX_NW_DSCP][0] = &nw_dscp_values[0];
+ values[CLS_F_IDX_NW_DSCP][1] = &nw_dscp_values[1];
values[CLS_F_IDX_TP_SRC][0] = &tp_src_values[0];
values[CLS_F_IDX_TP_SRC][1] = &tp_src_values[1];
#define N_DL_SRC_VALUES ARRAY_SIZE(dl_src_values)
#define N_DL_DST_VALUES ARRAY_SIZE(dl_dst_values)
#define N_NW_PROTO_VALUES ARRAY_SIZE(nw_proto_values)
-#define N_NW_TOS_VALUES ARRAY_SIZE(nw_tos_values)
+#define N_NW_DSCP_VALUES ARRAY_SIZE(nw_dscp_values)
#define N_FLOW_VALUES (N_NW_SRC_VALUES * \
N_NW_DST_VALUES * \
N_DL_SRC_VALUES * \
N_DL_DST_VALUES * \
N_NW_PROTO_VALUES * \
- N_NW_TOS_VALUES)
+ N_NW_DSCP_VALUES)
static unsigned int
get_value(unsigned int *x, unsigned n_values)
memcpy(flow.dl_dst, dl_dst_values[get_value(&x, N_DL_DST_VALUES)],
ETH_ADDR_LEN);
flow.nw_proto = nw_proto_values[get_value(&x, N_NW_PROTO_VALUES)];
- flow.nw_tos = nw_tos_values[get_value(&x, N_NW_TOS_VALUES)];
+ flow.nw_tos = nw_dscp_values[get_value(&x, N_NW_DSCP_VALUES)];
cr0 = classifier_lookup(cls, &flow);
cr1 = tcls_lookup(tcls, &flow);
rule->cls_rule.wc.vlan_tci_mask = htons(UINT16_MAX);
} else if (f_idx == CLS_F_IDX_TUN_ID) {
rule->cls_rule.wc.tun_id_mask = htonll(UINT64_MAX);
- } else if (f_idx == CLS_F_IDX_NW_TOS) {
- rule->cls_rule.wc.nw_tos_mask = UINT8_MAX;
} else {
NOT_REACHED();
}