struct hmap_node hmap_node;
enum nxm_field_index index; /* NFI_* value. */
uint32_t header; /* NXM_* value. */
- uint32_t wildcard; /* Wildcard bit, if exactly one. */
+ flow_wildcards_t wildcard; /* FWW_* bit, if exactly one. */
ovs_be16 dl_type; /* dl_type prerequisite, if nonzero. */
uint8_t nw_proto; /* nw_proto prerequisite, if nonzero. */
const char *name; /* "NXM_*" string. */
\f
/* nx_pull_match() and helpers. */
-static int
-parse_tci(struct cls_rule *rule, ovs_be16 tci, ovs_be16 mask)
-{
- enum { OFPFW_DL_TCI = OFPFW_DL_VLAN | OFPFW_DL_VLAN_PCP };
- if ((rule->wc.wildcards & OFPFW_DL_TCI) != OFPFW_DL_TCI) {
- return NXM_DUP_TYPE;
- } else {
- return cls_rule_set_dl_tci_masked(rule, tci, mask) ? 0 : NXM_INVALID;
- }
-}
-
static int
parse_nx_reg(const struct nxm_field *f,
struct flow *flow, struct flow_wildcards *wc,
/* Ethernet header. */
case NFI_NXM_OF_ETH_DST:
- if ((wc->wildcards & (OFPFW_DL_DST | FWW_ETH_MCAST))
- != (OFPFW_DL_DST | FWW_ETH_MCAST)) {
+ if ((wc->wildcards & (FWW_DL_DST | FWW_ETH_MCAST))
+ != (FWW_DL_DST | FWW_ETH_MCAST)) {
return NXM_DUP_TYPE;
} else {
- wc->wildcards &= ~(OFPFW_DL_DST | FWW_ETH_MCAST);
+ wc->wildcards &= ~(FWW_DL_DST | FWW_ETH_MCAST);
memcpy(flow->dl_dst, value, ETH_ADDR_LEN);
return 0;
}
case NFI_NXM_OF_ETH_DST_W:
- if ((wc->wildcards & (OFPFW_DL_DST | FWW_ETH_MCAST))
- != (OFPFW_DL_DST | FWW_ETH_MCAST)) {
+ if ((wc->wildcards & (FWW_DL_DST | FWW_ETH_MCAST))
+ != (FWW_DL_DST | FWW_ETH_MCAST)) {
return NXM_DUP_TYPE;
} else if (eth_addr_equals(mask, eth_mcast_1)) {
wc->wildcards &= ~FWW_ETH_MCAST;
flow->dl_dst[0] = *(uint8_t *) value & 0x01;
} else if (eth_addr_equals(mask, eth_mcast_0)) {
- wc->wildcards &= ~OFPFW_DL_DST;
+ wc->wildcards &= ~FWW_DL_DST;
memcpy(flow->dl_dst, value, ETH_ADDR_LEN);
flow->dl_dst[0] &= 0xfe;
} else if (eth_addr_equals(mask, eth_all_0s)) {
return 0;
} else if (eth_addr_equals(mask, eth_all_1s)) {
- wc->wildcards &= ~(OFPFW_DL_DST | FWW_ETH_MCAST);
+ wc->wildcards &= ~(FWW_DL_DST | FWW_ETH_MCAST);
memcpy(flow->dl_dst, value, ETH_ADDR_LEN);
return 0;
} else {
/* 802.1Q header. */
case NFI_NXM_OF_VLAN_TCI:
- return parse_tci(rule, get_unaligned_u16(value), htons(UINT16_MAX));
-
+ if (wc->vlan_tci_mask) {
+ return NXM_DUP_TYPE;
+ } else {
+ cls_rule_set_dl_tci(rule, get_unaligned_u16(value));
+ return 0;
+ }
case NFI_NXM_OF_VLAN_TCI_W:
- return parse_tci(rule, get_unaligned_u16(value),
- get_unaligned_u16(mask));
+ if (wc->vlan_tci_mask) {
+ return NXM_DUP_TYPE;
+ } else {
+ cls_rule_set_dl_tci_masked(rule, get_unaligned_u16(value),
+ get_unaligned_u16(mask));
+ return 0;
+ }
/* IP header. */
case NFI_NXM_OF_IP_TOS:
ofpbuf_put(b, &mask, sizeof mask);
}
+static void
+nxm_put_16m(struct ofpbuf *b, uint32_t header, ovs_be16 value, ovs_be16 mask)
+{
+ switch (mask) {
+ case 0:
+ break;
+
+ case CONSTANT_HTONS(UINT16_MAX):
+ nxm_put_16(b, header, value);
+ break;
+
+ default:
+ nxm_put_16w(b, NXM_MAKE_WILD_HEADER(header), value, mask);
+ break;
+ }
+}
+
static void
nxm_put_32(struct ofpbuf *b, uint32_t header, ovs_be32 value)
{
case 0:
break;
- case UINT32_MAX:
+ case CONSTANT_HTONL(UINT32_MAX):
nxm_put_32(b, header, value);
break;
nxm_put_eth_dst(struct ofpbuf *b,
uint32_t wc, const uint8_t value[ETH_ADDR_LEN])
{
- switch (wc & (OFPFW_DL_DST | FWW_ETH_MCAST)) {
- case OFPFW_DL_DST | FWW_ETH_MCAST:
+ switch (wc & (FWW_DL_DST | FWW_ETH_MCAST)) {
+ case FWW_DL_DST | FWW_ETH_MCAST:
break;
- case OFPFW_DL_DST:
+ case FWW_DL_DST:
nxm_put_header(b, NXM_OF_ETH_DST_W);
ofpbuf_put(b, value, ETH_ADDR_LEN);
ofpbuf_put(b, eth_mcast_1, ETH_ADDR_LEN);
int
nx_put_match(struct ofpbuf *b, const struct cls_rule *cr)
{
- const uint32_t wc = cr->wc.wildcards;
+ const flow_wildcards_t wc = cr->wc.wildcards;
const struct flow *flow = &cr->flow;
const size_t start_len = b->size;
- ovs_be16 vid, pcp;
int match_len;
int i;
/* Metadata. */
- if (!(wc & OFPFW_IN_PORT)) {
+ if (!(wc & FWW_IN_PORT)) {
uint16_t in_port = flow->in_port;
if (in_port == ODPP_LOCAL) {
in_port = OFPP_LOCAL;
/* Ethernet. */
nxm_put_eth_dst(b, wc, flow->dl_dst);
- if (!(wc & OFPFW_DL_SRC)) {
+ if (!(wc & FWW_DL_SRC)) {
nxm_put_eth(b, NXM_OF_ETH_SRC, flow->dl_src);
}
- if (!(wc & OFPFW_DL_TYPE)) {
+ if (!(wc & FWW_DL_TYPE)) {
nxm_put_16(b, NXM_OF_ETH_TYPE, flow->dl_type);
}
/* 802.1Q. */
- vid = flow->dl_vlan & htons(VLAN_VID_MASK);
- pcp = htons((flow->dl_vlan_pcp << VLAN_PCP_SHIFT) & VLAN_PCP_MASK);
- switch (wc & (OFPFW_DL_VLAN | OFPFW_DL_VLAN_PCP)) {
- case OFPFW_DL_VLAN | OFPFW_DL_VLAN_PCP:
- break;
- case OFPFW_DL_VLAN:
- nxm_put_16w(b, NXM_OF_VLAN_TCI_W, pcp | htons(VLAN_CFI),
- htons(VLAN_PCP_MASK | VLAN_CFI));
- break;
- case OFPFW_DL_VLAN_PCP:
- if (flow->dl_vlan == htons(OFP_VLAN_NONE)) {
- nxm_put_16(b, NXM_OF_VLAN_TCI, 0);
- } else {
- nxm_put_16w(b, NXM_OF_VLAN_TCI_W, vid | htons(VLAN_CFI),
- htons(VLAN_VID_MASK | VLAN_CFI));
- }
- break;
- case 0:
- if (flow->dl_vlan == htons(OFP_VLAN_NONE)) {
- nxm_put_16(b, NXM_OF_VLAN_TCI, 0);
- } else {
- nxm_put_16(b, NXM_OF_VLAN_TCI, vid | pcp | htons(VLAN_CFI));
- }
- break;
- }
+ nxm_put_16m(b, NXM_OF_VLAN_TCI, flow->vlan_tci, cr->wc.vlan_tci_mask);
- if (!(wc & OFPFW_DL_TYPE) && flow->dl_type == htons(ETH_TYPE_IP)) {
+ /* L3. */
+ if (!(wc & FWW_DL_TYPE) && flow->dl_type == htons(ETH_TYPE_IP)) {
/* IP. */
- if (!(wc & OFPFW_NW_TOS)) {
+ if (!(wc & FWW_NW_TOS)) {
nxm_put_8(b, NXM_OF_IP_TOS, flow->nw_tos & 0xfc);
}
nxm_put_32m(b, NXM_OF_IP_SRC, flow->nw_src, cr->wc.nw_src_mask);
nxm_put_32m(b, NXM_OF_IP_DST, flow->nw_dst, cr->wc.nw_dst_mask);
- if (!(wc & OFPFW_NW_PROTO)) {
+ if (!(wc & FWW_NW_PROTO)) {
nxm_put_8(b, NXM_OF_IP_PROTO, flow->nw_proto);
switch (flow->nw_proto) {
/* TCP. */
case IP_TYPE_TCP:
- if (!(wc & OFPFW_TP_SRC)) {
+ if (!(wc & FWW_TP_SRC)) {
nxm_put_16(b, NXM_OF_TCP_SRC, flow->tp_src);
}
- if (!(wc & OFPFW_TP_DST)) {
+ if (!(wc & FWW_TP_DST)) {
nxm_put_16(b, NXM_OF_TCP_DST, flow->tp_dst);
}
break;
/* UDP. */
case IP_TYPE_UDP:
- if (!(wc & OFPFW_TP_SRC)) {
+ if (!(wc & FWW_TP_SRC)) {
nxm_put_16(b, NXM_OF_UDP_SRC, flow->tp_src);
}
- if (!(wc & OFPFW_TP_DST)) {
+ if (!(wc & FWW_TP_DST)) {
nxm_put_16(b, NXM_OF_UDP_DST, flow->tp_dst);
}
break;
/* ICMP. */
case IP_TYPE_ICMP:
- if (!(wc & OFPFW_TP_SRC)) {
+ if (!(wc & FWW_TP_SRC)) {
nxm_put_8(b, NXM_OF_ICMP_TYPE, ntohs(flow->tp_src));
}
- if (!(wc & OFPFW_TP_DST)) {
+ if (!(wc & FWW_TP_DST)) {
nxm_put_8(b, NXM_OF_ICMP_CODE, ntohs(flow->tp_dst));
}
break;
}
}
- } else if (!(wc & OFPFW_DL_TYPE) && flow->dl_type == htons(ETH_TYPE_ARP)) {
+ } else if (!(wc & FWW_DL_TYPE) && flow->dl_type == htons(ETH_TYPE_ARP)) {
/* ARP. */
- if (!(wc & OFPFW_NW_PROTO)) {
+ if (!(wc & FWW_NW_PROTO)) {
nxm_put_16(b, NXM_OF_ARP_OP, htons(flow->nw_proto));
}
nxm_put_32m(b, NXM_OF_ARP_SPA, flow->nw_src, cr->wc.nw_src_mask);
}
/* Tunnel ID. */
- if (!(wc & NXFW_TUN_ID)) {
+ if (!(wc & FWW_TUN_ID)) {
nxm_put_64(b, NXM_NX_TUN_ID, htonll(ntohl(flow->tun_id)));
}
parse_hex_bytes(struct ofpbuf *b, const char *s, unsigned int n)
{
while (n--) {
- int low, high;
uint8_t byte;
+ bool ok;
s += strspn(s, " ");
- low = hexit_value(*s);
- high = low < 0 ? low : hexit_value(s[1]);
- if (low < 0 || high < 0) {
+ byte = hexits_value(s, 2, &ok);
+ if (!ok) {
ovs_fatal(0, "%.2s: hex digits expected", s);
}
- byte = 16 * low + high;
ofpbuf_put(b, &byte, 1);
s += 2;
}
return ntohs(flow->dl_type);
case NFI_NXM_OF_VLAN_TCI:
- if (flow->dl_vlan == htons(OFP_VLAN_NONE)) {
- return 0;
- } else {
- return (ntohs(flow->dl_vlan & htons(VLAN_VID_MASK))
- | ((flow->dl_vlan_pcp << VLAN_PCP_SHIFT) & VLAN_PCP_MASK)
- | VLAN_CFI);
- }
+ return ntohs(flow->vlan_tci);
case NFI_NXM_OF_IP_TOS:
return flow->nw_tos;
if (NXM_IS_NX_REG(dst->header)) {
flow->regs[NXM_NX_REG_IDX(dst->header)] = new_data;
} else if (dst->header == NXM_OF_VLAN_TCI) {
- ovs_be16 vlan_tci = htons(new_data & VLAN_CFI ? new_data : 0);
- flow->dl_vlan = htons(vlan_tci_to_vid(vlan_tci));
- flow->dl_vlan_pcp = vlan_tci_to_pcp(vlan_tci);
+ flow->vlan_tci = htons(new_data);
} else if (dst->header == NXM_NX_TUN_ID) {
flow->tun_id = htonl(new_data);
} else {