OFPUTIL_P_NONE,
OFPUTIL_P_NONE,
}, {
- MFF_TUN_TOS, "tun_tos", NULL,
+ MFF_TUN_TTL, "tun_ttl", NULL,
MF_FIELD_SIZES(u8),
MFM_NONE,
MFS_DECIMAL,
OFPUTIL_P_NONE,
OFPUTIL_P_NONE,
}, {
- MFF_TUN_TTL, "tun_ttl", NULL,
+ MFF_TUN_TOS, "tun_tos", NULL,
MF_FIELD_SIZES(u8),
MFM_NONE,
MFS_DECIMAL,
MFM_NONE,
MFS_DECIMAL,
MFP_ARP,
- false,
+ true,
NXM_OF_ARP_OP, "NXM_OF_ARP_OP",
OXM_OF_ARP_OP, "OXM_OF_ARP_OP",
OFPUTIL_P_ANY,
MFM_FULLY,
MFS_IPV4,
MFP_ARP,
- false,
+ true,
NXM_OF_ARP_SPA, "NXM_OF_ARP_SPA",
OXM_OF_ARP_SPA, "OXM_OF_ARP_SPA",
OFPUTIL_P_ANY,
MFM_FULLY,
MFS_IPV4,
MFP_ARP,
- false,
+ true,
NXM_OF_ARP_TPA, "NXM_OF_ARP_TPA",
OXM_OF_ARP_TPA, "OXM_OF_ARP_TPA",
OFPUTIL_P_ANY,
MFM_FULLY,
MFS_ETHERNET,
MFP_ARP,
- false,
+ true,
NXM_NX_ARP_SHA, "NXM_NX_ARP_SHA",
OXM_OF_ARP_SHA, "OXM_OF_ARP_SHA",
OFPUTIL_P_NXM_OXM_ANY,
MFM_FULLY,
MFS_ETHERNET,
MFP_ARP,
- false,
+ true,
NXM_NX_ARP_THA, "NXM_NX_ARP_THA",
OXM_OF_ARP_THA, "OXM_OF_ARP_THA",
OFPUTIL_P_NXM_OXM_ANY,
static void
nxm_do_init(void)
{
- const struct mf_field *mf;
+ int i;
hmap_init(&all_fields);
shash_init(&mf_by_name);
- for (mf = mf_fields; mf < &mf_fields[MFF_N_IDS]; mf++) {
+ for (i = 0; i < MFF_N_IDS; i++) {
+ const struct mf_field *mf = &mf_fields[i];
+
+ ovs_assert(mf->id == i); /* Fields must be in the enum order. */
+
nxm_init_add_field(mf, mf->nxm_header);
if (mf->oxm_header != mf->nxm_header) {
nxm_init_add_field(mf, mf->oxm_header);
NOT_REACHED();
}
+/* Set field and it's prerequisities in the mask.
+ * This is only ever called for writeable 'mf's, but we do not make the
+ * distinction here. */
+void
+mf_mask_field_and_prereqs(const struct mf_field *mf, struct flow *mask)
+{
+ static const union mf_value exact_match_mask = MF_EXACT_MASK_INITIALIZER;
+
+ mf_set_flow_value(mf, &exact_match_mask, mask);
+
+ switch (mf->prereqs) {
+ case MFP_ND:
+ case MFP_ND_SOLICIT:
+ case MFP_ND_ADVERT:
+ mask->tp_src = OVS_BE16_MAX;
+ mask->tp_dst = OVS_BE16_MAX;
+ /* Fall through. */
+ case MFP_TCP:
+ case MFP_UDP:
+ case MFP_SCTP:
+ case MFP_ICMPV4:
+ case MFP_ICMPV6:
+ mask->nw_proto = 0xff;
+ /* Fall through. */
+ case MFP_ARP:
+ case MFP_IPV4:
+ case MFP_IPV6:
+ case MFP_MPLS:
+ case MFP_IP_ANY:
+ mask->dl_type = OVS_BE16_MAX;
+ break;
+ case MFP_VLAN_VID:
+ mask->vlan_tci |= htons(VLAN_CFI);
+ break;
+ case MFP_NONE:
+ break;
+ }
+}
+
+
/* Returns true if 'value' may be a valid value *as part of a masked match*,
* false otherwise.
*
}
}
+/* Unwildcard 'mask' member field described by 'mf'. The caller is
+ * responsible for ensuring that 'mask' meets 'mf''s prerequisites. */
+void
+mf_mask_field(const struct mf_field *mf, struct flow *mask)
+{
+ static const union mf_value exact_match_mask = MF_EXACT_MASK_INITIALIZER;
+
+ /* For MFF_DL_VLAN, we cannot send a all 1's to flow_set_dl_vlan()
+ * as that will be considered as OFP10_VLAN_NONE. So consider it as a
+ * special case. For the rest, calling mf_set_flow_value() is good
+ * enough. */
+ if (mf->id == MFF_DL_VLAN) {
+ flow_set_dl_vlan(mask, htons(VLAN_VID_MASK));
+ } else {
+ mf_set_flow_value(mf, &exact_match_mask, mask);
+ }
+}
+
/* Sets 'flow' member field described by 'mf' to 'value'. The caller is
* responsible for ensuring that 'flow' meets 'mf''s prerequisites.*/
void
break;
case MFF_IPV6_LABEL:
- value->be32 &= ~htonl(IPV6_LABEL_MASK);
+ value->be32 &= htonl(IPV6_LABEL_MASK);
break;
case MFF_IP_DSCP:
return xasprintf("%s: network prefix bits not between 1 and "
"32", s);
} else if (prefix == 32) {
- *mask = htonl(UINT32_MAX);
+ *mask = OVS_BE32_MAX;
} else {
*mask = htonl(((1u << prefix) - 1) << (32 - prefix));
}
} else if (sscanf(s, IP_SCAN_FMT, IP_SCAN_ARGS(ip)) == IP_SCAN_COUNT) {
- *mask = htonl(UINT32_MAX);
+ *mask = OVS_BE32_MAX;
} else {
return xasprintf("%s: invalid IP address", s);
}
if (ofputil_port_from_string(s, &port)) {
*valuep = htons(ofp_to_u16(port));
- *maskp = htons(UINT16_MAX);
+ *maskp = OVS_BE16_MAX;
return NULL;
}
return xasprintf("%s: port value out of range for %s", s, mf->name);
ovs_assert(mf->n_bytes == sizeof(ovs_be32));
if (ofputil_port_from_string(s, &port)) {
*valuep = ofputil_port_to_ofp11(port);
- *maskp = htonl(UINT32_MAX);
+ *maskp = OVS_BE32_MAX;
return NULL;
}
return xasprintf("%s: port value out of range for %s", s, mf->name);
mf_from_tun_flags_string(const char *s, ovs_be16 *valuep, ovs_be16 *maskp)
{
if (!parse_flow_tun_flags(s, flow_tun_flag_to_string, valuep)) {
- *maskp = htons(UINT16_MAX);
+ *maskp = OVS_BE16_MAX;
return NULL;
}
break;
case MFS_IPV4:
- ip_format_masked(value->be32, mask ? mask->be32 : htonl(UINT32_MAX),
- s);
+ ip_format_masked(value->be32, mask ? mask->be32 : OVS_BE32_MAX, s);
break;
case MFS_IPV6: