Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com> --- lib/meta-flow.c | 203 ++++++++++++++++++++++++++++++------------ lib/meta-flow.h | 20 ++++- lib/nx-match.c | 135 ++-------------------------- lib/nx-match.h | 2 - lib/ofp-actions.c | 142 ++++++++++++++++++++++++++--- lib/ofp-actions.h | 15 +++- lib/ofp-parse.c | 13 ++- lib/ofp-util.h | 1 + ofproto/ofproto-dpif-xlate.c | 9 ++ ofproto/ofproto.c | 2 +- utilities/ovs-ofctl.c | 6 +- 11 files changed, 328 insertions(+), 220 deletions(-)
diff --git a/lib/meta-flow.c b/lib/meta-flow.c index b0a2900..0a29192 100644 --- a/lib/meta-flow.c +++ b/lib/meta-flow.c @@ -53,7 +53,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be64), MFM_FULLY, MFS_HEXADECIMAL, - MFP_NONE, + MFP_NONE, MFP_NONE, true, NXM_NX_TUN_ID, "NXM_NX_TUN_ID", OXM_OF_TUNNEL_ID, "OXM_OF_TUNNEL_ID", @@ -64,7 +64,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be32), MFM_FULLY, MFS_IPV4, - MFP_NONE, + MFP_NONE, MFP_NONE, true, NXM_NX_TUN_IPV4_SRC, "NXM_NX_TUN_IPV4_SRC", NXM_NX_TUN_IPV4_SRC, "NXM_NX_TUN_IPV4_SRC", @@ -75,7 +75,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be32), MFM_FULLY, MFS_IPV4, - MFP_NONE, + MFP_NONE, MFP_NONE, true, NXM_NX_TUN_IPV4_DST, "NXM_NX_TUN_IPV4_DST", NXM_NX_TUN_IPV4_DST, "NXM_NX_TUN_IPV4_DST", @@ -86,7 +86,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be16), MFM_NONE, MFS_TNL_FLAGS, - MFP_NONE, + MFP_NONE, MFP_NONE, false, 0, NULL, 0, NULL, @@ -97,7 +97,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(u8), MFM_NONE, MFS_DECIMAL, - MFP_NONE, + MFP_NONE, MFP_NONE, false, 0, NULL, 0, NULL, @@ -108,7 +108,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(u8), MFM_NONE, MFS_DECIMAL, - MFP_NONE, + MFP_NONE, MFP_NONE, false, 0, NULL, 0, NULL, @@ -119,7 +119,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be64), MFM_FULLY, MFS_HEXADECIMAL, - MFP_NONE, + MFP_NONE, MFP_NONE, true, OXM_OF_METADATA, "OXM_OF_METADATA", OXM_OF_METADATA, "OXM_OF_METADATA", @@ -130,7 +130,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be16), MFM_NONE, MFS_OFP_PORT, - MFP_NONE, + MFP_NONE, MFP_NONE, true, NXM_OF_IN_PORT, "NXM_OF_IN_PORT", NXM_OF_IN_PORT, "NXM_OF_IN_PORT", @@ -141,7 +141,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be32), MFM_NONE, MFS_OFP_PORT_OXM, - MFP_NONE, + MFP_NONE, MFP_NONE, true, OXM_OF_IN_PORT, "OXM_OF_IN_PORT", OXM_OF_IN_PORT, "OXM_OF_IN_PORT", @@ -152,7 +152,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be32), MFM_NONE, MFS_HEXADECIMAL, - MFP_NONE, + MFP_NONE, MFP_NONE, false, 0, NULL, 0, NULL, @@ -163,7 +163,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be32), MFM_FULLY, MFS_HEXADECIMAL, - MFP_NONE, + MFP_NONE, MFP_NONE, true, NXM_NX_PKT_MARK, "NXM_NX_PKT_MARK", NXM_NX_PKT_MARK, "NXM_NX_PKT_MARK", @@ -177,7 +177,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be32), \ MFM_FULLY, \ MFS_HEXADECIMAL, \ - MFP_NONE, \ + MFP_NONE, MFP_NONE, \ true, \ NXM_NX_REG(IDX), "NXM_NX_REG" #IDX, \ NXM_NX_REG(IDX), "NXM_NX_REG" #IDX, \ @@ -221,7 +221,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(mac), MFM_FULLY, MFS_ETHERNET, - MFP_NONE, + MFP_NONE, MFP_NONE, true, NXM_OF_ETH_SRC, "NXM_OF_ETH_SRC", OXM_OF_ETH_SRC, "OXM_OF_ETH_SRC", @@ -232,7 +232,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(mac), MFM_FULLY, MFS_ETHERNET, - MFP_NONE, + MFP_NONE, MFP_NONE, true, NXM_OF_ETH_DST, "NXM_OF_ETH_DST", OXM_OF_ETH_DST, "OXM_OF_ETH_DST", @@ -243,7 +243,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be16), MFM_NONE, MFS_HEXADECIMAL, - MFP_NONE, + MFP_NONE, MFP_NONE, false, NXM_OF_ETH_TYPE, "NXM_OF_ETH_TYPE", OXM_OF_ETH_TYPE, "OXM_OF_ETH_TYPE", @@ -256,7 +256,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be16), MFM_FULLY, MFS_HEXADECIMAL, - MFP_NONE, + MFP_NONE, MFP_NONE, true, NXM_OF_VLAN_TCI, "NXM_OF_VLAN_TCI", NXM_OF_VLAN_TCI, "NXM_OF_VLAN_TCI", @@ -267,7 +267,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { sizeof(ovs_be16), 12, MFM_NONE, MFS_DECIMAL, - MFP_NONE, + MFP_NONE, MFP_NONE, true, 0, NULL, 0, NULL, @@ -275,10 +275,10 @@ const struct mf_field mf_fields[MFF_N_IDS] = { OFPUTIL_P_NXM_OXM_ANY, }, { MFF_VLAN_VID, "vlan_vid", NULL, - sizeof(ovs_be16), 12, + sizeof(ovs_be16), 12, /* 12 bits for setting, 13 bits for matching. */ MFM_FULLY, MFS_DECIMAL, - MFP_NONE, + MFP_NONE, MFP_VLAN_VID, /* Prerequisite for set field only. */ true, OXM_OF_VLAN_VID, "OXM_OF_VLAN_VID", OXM_OF_VLAN_VID, "OXM_OF_VLAN_VID", @@ -289,7 +289,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { 1, 3, MFM_NONE, MFS_DECIMAL, - MFP_NONE, + MFP_NONE, MFP_NONE, true, 0, NULL, 0, NULL, @@ -300,7 +300,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { 1, 3, MFM_NONE, MFS_DECIMAL, - MFP_VLAN_VID, + MFP_VLAN_VID, MFP_VLAN_VID, true, OXM_OF_VLAN_PCP, "OXM_OF_VLAN_PCP", OXM_OF_VLAN_PCP, "OXM_OF_VLAN_PCP", @@ -316,7 +316,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { 4, 20, MFM_NONE, MFS_DECIMAL, - MFP_MPLS, + MFP_MPLS, MFP_MPLS, true, OXM_OF_MPLS_LABEL, "OXM_OF_MPLS_LABEL", OXM_OF_MPLS_LABEL, "OXM_OF_MPLS_LABEL", @@ -327,7 +327,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { 1, 3, MFM_NONE, MFS_DECIMAL, - MFP_MPLS, + MFP_MPLS, MFP_MPLS, true, OXM_OF_MPLS_TC, "OXM_OF_MPLS_TC", OXM_OF_MPLS_TC, "OXM_OF_MPLS_TC", @@ -338,7 +338,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { 1, 1, MFM_NONE, MFS_DECIMAL, - MFP_MPLS, + MFP_MPLS, MFP_MPLS, false, OXM_OF_MPLS_BOS, "OXM_OF_MPLS_BOS", OXM_OF_MPLS_BOS, "OXM_OF_MPLS_BOS", @@ -355,7 +355,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be32), MFM_FULLY, MFS_IPV4, - MFP_IPV4, + MFP_IPV4, MFP_IPV4, true, NXM_OF_IP_SRC, "NXM_OF_IP_SRC", OXM_OF_IPV4_SRC, "OXM_OF_IPV4_SRC", @@ -366,7 +366,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be32), MFM_FULLY, MFS_IPV4, - MFP_IPV4, + MFP_IPV4, MFP_IPV4, true, NXM_OF_IP_DST, "NXM_OF_IP_DST", OXM_OF_IPV4_DST, "OXM_OF_IPV4_DST", @@ -379,7 +379,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(ipv6), MFM_FULLY, MFS_IPV6, - MFP_IPV6, + MFP_IPV6, MFP_IPV6, true, NXM_NX_IPV6_SRC, "NXM_NX_IPV6_SRC", OXM_OF_IPV6_SRC, "OXM_OF_IPV6_SRC", @@ -390,7 +390,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(ipv6), MFM_FULLY, MFS_IPV6, - MFP_IPV6, + MFP_IPV6, MFP_IPV6, true, NXM_NX_IPV6_DST, "NXM_NX_IPV6_DST", OXM_OF_IPV6_DST, "OXM_OF_IPV6_DST", @@ -402,7 +402,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { 4, 20, MFM_FULLY, MFS_HEXADECIMAL, - MFP_IPV6, + MFP_IPV6, MFP_IPV6, false, NXM_NX_IPV6_LABEL, "NXM_NX_IPV6_LABEL", OXM_OF_IPV6_FLABEL, "OXM_OF_IPV6_FLABEL", @@ -415,7 +415,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(u8), MFM_NONE, MFS_DECIMAL, - MFP_IP_ANY, + MFP_IP_ANY, MFP_IP_ANY, false, NXM_OF_IP_PROTO, "NXM_OF_IP_PROTO", OXM_OF_IP_PROTO, "OXM_OF_IP_PROTO", @@ -426,7 +426,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(u8), MFM_NONE, MFS_DECIMAL, - MFP_IP_ANY, + MFP_IP_ANY, MFP_IP_ANY, true, NXM_OF_IP_TOS, "NXM_OF_IP_TOS", NXM_OF_IP_TOS, "NXM_OF_IP_TOS", @@ -437,7 +437,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { 1, 6, MFM_NONE, MFS_DECIMAL, - MFP_IP_ANY, + MFP_IP_ANY, MFP_IP_ANY, true, OXM_OF_IP_DSCP, "OXM_OF_IP_DSCP", OXM_OF_IP_DSCP, "OXM_OF_IP_DSCP", @@ -448,18 +448,18 @@ const struct mf_field mf_fields[MFF_N_IDS] = { 1, 2, MFM_NONE, MFS_DECIMAL, - MFP_IP_ANY, + MFP_IP_ANY, MFP_IP_ANY, true, NXM_NX_IP_ECN, "NXM_NX_IP_ECN", OXM_OF_IP_ECN, "OXM_OF_IP_ECN", OFPUTIL_P_NXM_OXM_ANY, OFPUTIL_P_NONE, }, { - MFF_IP_TTL, "nw_ttl", NULL, + MFF_IP_TTL, "nw_ttl", "ip_ttl", MF_FIELD_SIZES(u8), MFM_NONE, MFS_DECIMAL, - MFP_IP_ANY, + MFP_IP_ANY, MFP_IP_ANY, true, NXM_NX_IP_TTL, "NXM_NX_IP_TTL", NXM_NX_IP_TTL, "NXM_NX_IP_TTL", @@ -470,7 +470,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { 1, 2, MFM_FULLY, MFS_FRAG, - MFP_IP_ANY, + MFP_IP_ANY, MFP_IP_ANY, false, NXM_NX_IP_FRAG, "NXM_NX_IP_FRAG", NXM_NX_IP_FRAG, "NXM_NX_IP_FRAG", @@ -483,7 +483,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be16), MFM_NONE, MFS_DECIMAL, - MFP_ARP, + MFP_ARP, MFP_ARP, true, NXM_OF_ARP_OP, "NXM_OF_ARP_OP", OXM_OF_ARP_OP, "OXM_OF_ARP_OP", @@ -494,7 +494,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be32), MFM_FULLY, MFS_IPV4, - MFP_ARP, + MFP_ARP, MFP_ARP, true, NXM_OF_ARP_SPA, "NXM_OF_ARP_SPA", OXM_OF_ARP_SPA, "OXM_OF_ARP_SPA", @@ -505,7 +505,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be32), MFM_FULLY, MFS_IPV4, - MFP_ARP, + MFP_ARP, MFP_ARP, true, NXM_OF_ARP_TPA, "NXM_OF_ARP_TPA", OXM_OF_ARP_TPA, "OXM_OF_ARP_TPA", @@ -516,7 +516,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(mac), MFM_FULLY, MFS_ETHERNET, - MFP_ARP, + MFP_ARP, MFP_ARP, true, NXM_NX_ARP_SHA, "NXM_NX_ARP_SHA", OXM_OF_ARP_SHA, "OXM_OF_ARP_SHA", @@ -527,7 +527,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(mac), MFM_FULLY, MFS_ETHERNET, - MFP_ARP, + MFP_ARP, MFP_ARP, true, NXM_NX_ARP_THA, "NXM_NX_ARP_THA", OXM_OF_ARP_THA, "OXM_OF_ARP_THA", @@ -544,7 +544,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be16), MFM_FULLY, MFS_DECIMAL, - MFP_TCP, + MFP_TCP, MFP_TCP, true, NXM_OF_TCP_SRC, "NXM_OF_TCP_SRC", OXM_OF_TCP_SRC, "OXM_OF_TCP_SRC", @@ -555,7 +555,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be16), MFM_FULLY, MFS_DECIMAL, - MFP_TCP, + MFP_TCP, MFP_TCP, true, NXM_OF_TCP_DST, "NXM_OF_TCP_DST", OXM_OF_TCP_DST, "OXM_OF_TCP_DST", @@ -568,7 +568,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be16), MFM_FULLY, MFS_DECIMAL, - MFP_UDP, + MFP_UDP, MFP_UDP, true, NXM_OF_UDP_SRC, "NXM_OF_UDP_SRC", OXM_OF_UDP_SRC, "OXM_OF_UDP_SRC", @@ -579,7 +579,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be16), MFM_FULLY, MFS_DECIMAL, - MFP_UDP, + MFP_UDP, MFP_UDP, true, NXM_OF_UDP_DST, "NXM_OF_UDP_DST", OXM_OF_UDP_DST, "OXM_OF_UDP_DST", @@ -592,7 +592,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be16), MFM_FULLY, MFS_DECIMAL, - MFP_SCTP, + MFP_SCTP, MFP_SCTP, true, OXM_OF_SCTP_SRC, "OXM_OF_SCTP_SRC", OXM_OF_SCTP_SRC, "OXM_OF_SCTP_SRC", @@ -603,7 +603,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(be16), MFM_FULLY, MFS_DECIMAL, - MFP_SCTP, + MFP_SCTP, MFP_SCTP, true, OXM_OF_SCTP_DST, "OXM_OF_SCTP_DST", OXM_OF_SCTP_DST, "OXM_OF_SCTP_DST", @@ -616,7 +616,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(u8), MFM_NONE, MFS_DECIMAL, - MFP_ICMPV4, + MFP_ICMPV4, MFP_ICMPV4, false, NXM_OF_ICMP_TYPE, "NXM_OF_ICMP_TYPE", OXM_OF_ICMPV4_TYPE, "OXM_OF_ICMPV4_TYPE", @@ -627,7 +627,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(u8), MFM_NONE, MFS_DECIMAL, - MFP_ICMPV4, + MFP_ICMPV4, MFP_ICMPV4, false, NXM_OF_ICMP_CODE, "NXM_OF_ICMP_CODE", OXM_OF_ICMPV4_CODE, "OXM_OF_ICMPV4_CODE", @@ -640,7 +640,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(u8), MFM_NONE, MFS_DECIMAL, - MFP_ICMPV6, + MFP_ICMPV6, MFP_ICMPV6, false, NXM_NX_ICMPV6_TYPE, "NXM_NX_ICMPV6_TYPE", OXM_OF_ICMPV6_TYPE, "OXM_OF_ICMPV6_TYPE", @@ -651,7 +651,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(u8), MFM_NONE, MFS_DECIMAL, - MFP_ICMPV6, + MFP_ICMPV6, MFP_ICMPV6, false, NXM_NX_ICMPV6_CODE, "NXM_NX_ICMPV6_CODE", OXM_OF_ICMPV6_CODE, "OXM_OF_ICMPV6_CODE", @@ -668,7 +668,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(ipv6), MFM_FULLY, MFS_IPV6, - MFP_ND, + MFP_ND, MFP_ND, false, NXM_NX_ND_TARGET, "NXM_NX_ND_TARGET", OXM_OF_IPV6_ND_TARGET, "OXM_OF_IPV6_ND_TARGET", @@ -679,7 +679,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(mac), MFM_FULLY, MFS_ETHERNET, - MFP_ND_SOLICIT, + MFP_ND_SOLICIT, MFP_ND_SOLICIT, false, NXM_NX_ND_SLL, "NXM_NX_ND_SLL", OXM_OF_IPV6_ND_SLL, "OXM_OF_IPV6_ND_SLL", @@ -690,7 +690,7 @@ const struct mf_field mf_fields[MFF_N_IDS] = { MF_FIELD_SIZES(mac), MFM_FULLY, MFS_ETHERNET, - MFP_ND_ADVERT, + MFP_ND_ADVERT, MFP_ND_ADVERT, false, NXM_NX_ND_TLL, "NXM_NX_ND_TLL", OXM_OF_IPV6_ND_TLL, "OXM_OF_IPV6_ND_TLL", @@ -966,9 +966,9 @@ is_icmpv6(const struct flow *flow) /* Returns true if 'flow' meets the prerequisites for 'mf', false otherwise. */ bool -mf_are_prereqs_ok(const struct mf_field *mf, const struct flow *flow) +mf_are_prereqs_ok(enum mf_prereqs prereqs, const struct flow *flow) { - switch (mf->prereqs) { + switch (prereqs) { case MFP_NONE: return true; @@ -1025,7 +1025,7 @@ mf_mask_field_and_prereqs(const struct mf_field *mf, struct flow *mask) mf_set_flow_value(mf, &exact_match_mask, mask); - switch (mf->prereqs) { + switch (mf->set_prereqs) { case MFP_ND: case MFP_ND_SOLICIT: case MFP_ND_ADVERT: @@ -1055,6 +1055,90 @@ mf_mask_field_and_prereqs(const struct mf_field *mf, struct flow *mask) } +/* Returns true if 'value' may be a valid value *as part of a set field + * action*, false otherwise. + * + * A value is rejected if it is not valid for the field in question. + * For example, the MFF_VLAN_TCI field will never have a nonzero value + * without the VLAN_CFI bit being set, so we reject those values. + * Similarly, the MFF_VLAN_VID can have the CFI bit set for matching, but + * not for setting a field value, so we reject values that have the CFI bit + * set. + */ +bool +mf_is_value_valid_for_set_field(const struct mf_field *mf, + const union mf_value *value) +{ + if (!mf->writable) { + VLOG_WARN_RL(&rl, "destination field %s is not writable", + mf->name); + return false; + } + + /* Check that the field has no extra bits set. */ + if (mf->n_bits < mf->n_bytes * 8) { + /* Check only cases for which we support. */ + switch (mf->n_bytes) { + case 1: + if (value->u8 & ~0u << mf->n_bits) { + goto invalid_value; + } + break; + case 2: + if (ntohs(value->be16) & ~0u << mf->n_bits) { + goto invalid_value; + } + break; + case 4: + if (ntohl(value->be32) & ~0u << mf->n_bits) { + goto invalid_value; + } + break; + default: + goto invalid_value; + } + } + + /* Check only fields for which the bit size check above is not enough. */ + switch ((int)mf->id) { + + case MFF_IN_PORT_OXM: { + ofp_port_t port; + if (ofputil_port_from_ofp11(value->be32, &port)) { + goto invalid_value; + } + } + break; + case MFF_IP_DSCP: /* Low bits must be zero. */ + if (value->u8 & ~IP_DSCP_MASK) { + goto invalid_value; + } + break; + + case MFF_ARP_OP: /* Only really has 8 bits. */ + if (value->be16 & htons(0xff00)) { + goto invalid_value; + } + break; + + case MFF_VLAN_TCI: /* CFI must be set for all non-zero values. */ + if (value->be16 && !(value->be16 & htons(VLAN_CFI))) { + goto invalid_value; + } + break; + } + return true; + + invalid_value: { + struct ds ds = DS_EMPTY_INITIALIZER; + mf_format(mf, value, NULL, &ds); + VLOG_WARN_RL(&rl, "Invalid value for destination field %s: %s", + mf->name, ds_cstr(&ds)); + ds_destroy(&ds); + } + return false; +} + /* Returns true if 'value' may be a valid value *as part of a masked match*, * false otherwise. * @@ -1066,7 +1150,8 @@ mf_mask_field_and_prereqs(const struct mf_field *mf, struct flow *mask) * for NXM_OF_VLAN_TCI in nicira-ext.h). On the other hand, there is never a * reason to set the low bit of MFF_IP_DSCP to 1, so we reject that. */ bool -mf_is_value_valid(const struct mf_field *mf, const union mf_value *value) +mf_is_value_valid_for_match(const struct mf_field *mf, + const union mf_value *value) { switch (mf->id) { case MFF_TUN_ID: @@ -2136,7 +2221,7 @@ mf_check__(const struct mf_subfield *sf, const struct flow *flow, "of %s field %s", sf->ofs, sf->n_bits, sf->field->n_bits, type, sf->field->name); return OFPERR_OFPBAC_BAD_SET_LEN; - } else if (flow && !mf_are_prereqs_ok(sf->field, flow)) { + } else if (flow && !mf_are_prereqs_ok(sf->field->set_prereqs, flow)) { VLOG_WARN_RL(&rl, "%s field %s lacks correct prerequisites", type, sf->field->name); return OFPERR_OFPBAC_MATCH_INCONSISTENT; diff --git a/lib/meta-flow.h b/lib/meta-flow.h index ab7db86..413404f 100644 --- a/lib/meta-flow.h +++ b/lib/meta-flow.h @@ -178,7 +178,15 @@ enum OVS_PACKED_ENUM mf_field_id { * * A field may only be matched if the correct lower-level protocols are also * matched. For example, the TCP port may be matched only if the Ethernet type - * matches ETH_TYPE_IP and the IP protocol matches IPPROTO_TCP. */ + * matches ETH_TYPE_IP and the IP protocol matches IPPROTO_TCP. + * + * Prerequisities are also checked on the set field and reg load actions. + * OF 1.2 set field actions apply for existing fields only, so the VLAN CFI + * bit must be present in the flow for the set field OXM_OF_VLAN_VID to apply. + * However, on match OXM_OF_VLAN_VID explicitly includes the CFI bit, so it + * can not have a prerequisite. To accomodate this, struct mf_field has two + * sets of prereqs, one for match and the other for set field action. + */ enum OVS_PACKED_ENUM mf_prereqs { MFP_NONE, @@ -256,7 +264,8 @@ struct mf_field { /* Properties. */ enum mf_maskable maskable; enum mf_string string; - enum mf_prereqs prereqs; + enum mf_prereqs match_prereqs; /* Prereqs on match. */ + enum mf_prereqs set_prereqs; /* Prereqs on set field. */ bool writable; /* May be written by actions? */ /* NXM and OXM properties. @@ -350,11 +359,14 @@ void mf_get_mask(const struct mf_field *, const struct flow_wildcards *, union mf_value *mask); /* Prerequisites. */ -bool mf_are_prereqs_ok(const struct mf_field *, const struct flow *); +bool mf_are_prereqs_ok(enum mf_prereqs, const struct flow *); void mf_mask_field_and_prereqs(const struct mf_field *, struct flow *mask); /* Field values. */ -bool mf_is_value_valid(const struct mf_field *, const union mf_value *value); +bool mf_is_value_valid_for_match(const struct mf_field *, + const union mf_value *value); +bool mf_is_value_valid_for_set_field(const struct mf_field *, + const union mf_value *value); void mf_get_value(const struct mf_field *, const struct flow *, union mf_value *value); diff --git a/lib/nx-match.c b/lib/nx-match.c index 11cbff3..98b1ea7 100644 --- a/lib/nx-match.c +++ b/lib/nx-match.c @@ -144,7 +144,7 @@ nx_pull_raw(const uint8_t *p, unsigned int match_len, bool strict, } else { continue; } - } else if (!mf_are_prereqs_ok(mf, &match->flow)) { + } else if (!mf_are_prereqs_ok(mf->match_prereqs, &match->flow)) { error = OFPERR_OFPBMC_BAD_PREREQ; } else if (!mf_is_all_wild(mf, &match->wc)) { error = OFPERR_OFPBMC_DUP_FIELD; @@ -153,7 +153,7 @@ nx_pull_raw(const uint8_t *p, unsigned int match_len, bool strict, union mf_value value; memcpy(&value, p + 4, width); - if (!mf_is_value_valid(mf, &value)) { + if (!mf_is_value_valid_for_match(mf, &value)) { error = OFPERR_OFPBMC_BAD_VALUE; } else if (!NXM_HASMASK(header)) { error = 0; @@ -1088,39 +1088,14 @@ nxm_format_reg_move(const struct ofpact_reg_move *move, struct ds *s) mf_format_subfield(&move->dst, s); } -static void -set_field_format(const struct ofpact_reg_load *load, struct ds *s) -{ - const struct mf_field *mf = load->dst.field; - union mf_value value; - - ovs_assert(load->ofpact.compat == OFPUTIL_OFPAT12_SET_FIELD); - ds_put_format(s, "set_field:"); - memset(&value, 0, sizeof value); - bitwise_copy(&load->subvalue, sizeof load->subvalue, 0, - &value, mf->n_bytes, 0, load->dst.n_bits); - mf_format(mf, &value, NULL, s); - ds_put_format(s, "->%s", mf->name); -} - -static void -load_format(const struct ofpact_reg_load *load, struct ds *s) +void +nxm_format_reg_load(const struct ofpact_reg_load *load, struct ds *s) { ds_put_cstr(s, "load:"); mf_format_subvalue(&load->subvalue, s); ds_put_cstr(s, "->"); mf_format_subfield(&load->dst, s); } - -void -nxm_format_reg_load(const struct ofpact_reg_load *load, struct ds *s) -{ - if (load->ofpact.compat == OFPUTIL_OFPAT12_SET_FIELD) { - set_field_format(load, s); - } else { - load_format(load, s); - } -} enum ofperr nxm_reg_move_from_openflow(const struct nx_action_reg_move *narm, @@ -1160,38 +1135,6 @@ nxm_reg_load_from_openflow(const struct nx_action_reg_load *narl, return nxm_reg_load_check(load, NULL); } - -enum ofperr -nxm_reg_load_from_openflow12_set_field( - const struct ofp12_action_set_field * oasf, struct ofpbuf *ofpacts) -{ - uint16_t oasf_len = ntohs(oasf->len); - uint32_t oxm_header = ntohl(oasf->dst); - uint8_t oxm_length = NXM_LENGTH(oxm_header); - struct ofpact_reg_load *load; - const struct mf_field *mf; - - /* ofp12_action_set_field is padded to 64 bits by zero */ - if (oasf_len != ROUND_UP(sizeof(*oasf) + oxm_length, 8)) { - return OFPERR_OFPBAC_BAD_SET_LEN; - } - if (!is_all_zeros((const uint8_t *)(oasf) + sizeof *oasf + oxm_length, - oasf_len - oxm_length - sizeof *oasf)) { - return OFPERR_OFPBAC_BAD_SET_ARGUMENT; - } - - if (NXM_HASMASK(oxm_header)) { - return OFPERR_OFPBAC_BAD_SET_TYPE; - } - mf = mf_from_nxm_header(oxm_header); - if (!mf) { - return OFPERR_OFPBAC_BAD_SET_TYPE; - } - load = ofpact_put_REG_LOAD(ofpacts); - ofpact_set_field_init(load, mf, oasf + 1); - - return nxm_reg_load_check(load, NULL); -} enum ofperr nxm_reg_move_check(const struct ofpact_reg_move *move, const struct flow *flow) @@ -1226,8 +1169,9 @@ nxm_reg_move_to_nxast(const struct ofpact_reg_move *move, narm->dst = htonl(move->dst.field->nxm_header); } -static void -reg_load_to_nxast(const struct ofpact_reg_load *load, struct ofpbuf *openflow) +void +nxm_reg_load_to_nxast(const struct ofpact_reg_load *load, + struct ofpbuf *openflow) { struct nx_action_reg_load *narl; @@ -1236,71 +1180,6 @@ reg_load_to_nxast(const struct ofpact_reg_load *load, struct ofpbuf *openflow) narl->dst = htonl(load->dst.field->nxm_header); narl->value = load->subvalue.be64[1]; } - -static void -set_field_to_ofast(const struct ofpact_reg_load *load, - struct ofpbuf *openflow) -{ - const struct mf_field *mf = load->dst.field; - uint16_t padded_value_len = ROUND_UP(mf->n_bytes, 8); - struct ofp12_action_set_field *oasf; - char *value; - - /* Set field is the only action of variable length (so far), - * so handling the variable length portion is open-coded here */ - oasf = ofputil_put_OFPAT12_SET_FIELD(openflow); - oasf->dst = htonl(mf->oxm_header); - oasf->len = htons(ntohs(oasf->len) + padded_value_len); - - value = ofpbuf_put_zeros(openflow, padded_value_len); - bitwise_copy(&load->subvalue, sizeof load->subvalue, load->dst.ofs, - value, mf->n_bytes, load->dst.ofs, load->dst.n_bits); -} - -void -nxm_reg_load_to_nxast(const struct ofpact_reg_load *load, - struct ofpbuf *openflow) -{ - - if (load->ofpact.compat == OFPUTIL_OFPAT12_SET_FIELD) { - struct ofp_header *oh = (struct ofp_header *)openflow->l2; - - switch(oh->version) { - case OFP13_VERSION: - case OFP12_VERSION: - set_field_to_ofast(load, openflow); - break; - - case OFP11_VERSION: - case OFP10_VERSION: - if (load->dst.n_bits < 64) { - reg_load_to_nxast(load, openflow); - } else { - /* Split into 64bit chunks */ - int chunk, ofs; - for (ofs = 0; ofs < load->dst.n_bits; ofs += chunk) { - struct ofpact_reg_load subload = *load; - - chunk = MIN(load->dst.n_bits - ofs, 64); - - subload.dst.field = load->dst.field; - subload.dst.ofs = load->dst.ofs + ofs; - subload.dst.n_bits = chunk; - bitwise_copy(&load->subvalue, sizeof load->subvalue, ofs, - &subload.subvalue, sizeof subload.subvalue, 0, - chunk); - reg_load_to_nxast(&subload, openflow); - } - } - break; - - default: - NOT_REACHED(); - } - } else { - reg_load_to_nxast(load, openflow); - } -} /* nxm_execute_reg_move(), nxm_execute_reg_load(). */ diff --git a/lib/nx-match.h b/lib/nx-match.h index 7065225..ee3f24c 100644 --- a/lib/nx-match.h +++ b/lib/nx-match.h @@ -70,8 +70,6 @@ enum ofperr nxm_reg_move_from_openflow(const struct nx_action_reg_move *, struct ofpbuf *ofpacts); enum ofperr nxm_reg_load_from_openflow(const struct nx_action_reg_load *, struct ofpbuf *ofpacts); -enum ofperr nxm_reg_load_from_openflow12_set_field( - const struct ofp12_action_set_field * oasf, struct ofpbuf *ofpacts); enum ofperr nxm_reg_move_check(const struct ofpact_reg_move *, const struct flow *); diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index 4400245..2cb1d54 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -760,6 +760,104 @@ decode_openflow11_action(const union ofp_action *a, } static enum ofperr +set_field_from_openflow(const struct ofp12_action_set_field *oasf, + struct ofpbuf *ofpacts) +{ + uint16_t oasf_len = ntohs(oasf->len); + uint32_t oxm_header = ntohl(oasf->dst); + uint8_t oxm_length = NXM_LENGTH(oxm_header); + struct ofpact_set_field *sf; + const struct mf_field *mf; + + /* ofp12_action_set_field is padded to 64 bits by zero */ + if (oasf_len != ROUND_UP(sizeof(*oasf) + oxm_length, 8)) { + return OFPERR_OFPBAC_BAD_SET_LEN; + } + if (!is_all_zeros((const uint8_t *)(oasf) + sizeof *oasf + oxm_length, + oasf_len - oxm_length - sizeof *oasf)) { + return OFPERR_OFPBAC_BAD_SET_ARGUMENT; + } + + if (NXM_HASMASK(oxm_header)) { + return OFPERR_OFPBAC_BAD_SET_TYPE; + } + mf = mf_from_nxm_header(oxm_header); + if (!mf) { + return OFPERR_OFPBAC_BAD_SET_TYPE; + } + ovs_assert(mf->n_bytes == oxm_length); + /* oxm_length is now validated to be compatible with mf_value. */ + + sf = ofpact_put_SET_FIELD(ofpacts); + sf->field = mf->id; + memcpy(&sf->value.u8, oasf + 1, mf->n_bytes); + + if (!mf_is_value_valid_for_set_field(mf, &sf->value)) { + return OFPERR_OFPBAC_BAD_SET_ARGUMENT; + } + return 0; +} + +static void +set_field_to_ofast(const struct ofpact_set_field *sf, + struct ofpbuf *openflow) +{ + const struct mf_field *mf = mf_from_id(sf->field); + uint16_t padded_value_len = ROUND_UP(mf->n_bytes, 8); + struct ofp12_action_set_field *oasf; + char *value; + + /* Set field is the only action of variable length (so far), + * so handling the variable length portion is open-coded here */ + oasf = ofputil_put_OFPAT12_SET_FIELD(openflow); + oasf->dst = htonl(mf->oxm_header); + oasf->len = htons(ntohs(oasf->len) + padded_value_len); + + value = ofpbuf_put_zeros(openflow, padded_value_len); + memcpy(value, &sf->value, mf->n_bytes); +} + +static void +set_field_to_openflow(const struct ofpact_set_field *sf, + struct ofpbuf *openflow) +{ + struct ofp_header *oh = (struct ofp_header *)openflow->l2; + struct nx_action_reg_load *narl; + const struct mf_field *mf; + + if (oh->version >= OFP12_VERSION) { + set_field_to_ofast(sf, openflow); + return; + } + + mf = mf_from_id(sf->field); + + /* Convert to one or two REG_LOADs */ + + if (mf->n_bits > 64) { + ovs_assert(mf->n_bytes == 16); /* IPv6 addr. */ + /* Split into 64bit chunks */ + /* Lower bits first. */ + narl = ofputil_put_NXAST_REG_LOAD(openflow); + narl->ofs_nbits = nxm_encode_ofs_nbits(0, 64); + narl->dst = htonl(mf->nxm_header); + narl->value = *(&sf->value.be64 + 1); + /* Higher bits next. */ + narl = ofputil_put_NXAST_REG_LOAD(openflow); + narl->ofs_nbits = nxm_encode_ofs_nbits(64, mf->n_bits - 64); + narl->dst = htonl(mf->nxm_header); + narl->value = sf->value.be64; + } else { + narl = ofputil_put_NXAST_REG_LOAD(openflow); + narl->ofs_nbits = nxm_encode_ofs_nbits(0, mf->n_bits); + narl->dst = htonl(mf->nxm_header); + memset(&narl->value, 0, 8 - mf->n_bytes); + memcpy((char*)&narl->value + (8 - mf->n_bytes), + &sf->value, mf->n_bytes); + } +} + +static enum ofperr output_from_openflow11(const struct ofp11_action_output *oao, struct ofpbuf *out) { @@ -885,7 +983,7 @@ ofpact_from_openflow11(const union ofp_action *a, struct ofpbuf *out) break; case OFPUTIL_OFPAT12_SET_FIELD: - return nxm_reg_load_from_openflow12_set_field(&a->set_field, out); + return set_field_from_openflow(&a->set_field, out); case OFPUTIL_OFPAT11_SET_MPLS_TTL: ofpact_put_SET_MPLS_TTL(out)->ttl = a->ofp11_mpls_ttl.mpls_ttl; @@ -933,6 +1031,7 @@ static bool ofpact_is_set_action(const struct ofpact *a) { switch (a->type) { + case OFPACT_SET_FIELD: case OFPACT_REG_LOAD: case OFPACT_SET_ETH_DST: case OFPACT_SET_ETH_SRC: @@ -997,6 +1096,7 @@ ofpact_is_allowed_in_actions_set(const struct ofpact *a) case OFPACT_PUSH_MPLS: case OFPACT_PUSH_VLAN: case OFPACT_REG_LOAD: + case OFPACT_SET_FIELD: case OFPACT_SET_ETH_DST: case OFPACT_SET_ETH_SRC: case OFPACT_SET_IP_DSCP: @@ -1278,6 +1378,7 @@ ovs_instruction_type_from_ofpact_type(enum ofpact_type type) case OFPACT_SET_L4_DST_PORT: case OFPACT_REG_MOVE: case OFPACT_REG_LOAD: + case OFPACT_SET_FIELD: case OFPACT_STACK_PUSH: case OFPACT_STACK_POP: case OFPACT_DEC_TTL: @@ -1560,6 +1661,7 @@ ofpact_check__(struct ofpact *a, struct flow *flow, ofp_port_t max_ports, uint8_t table_id, bool enforce_consistency) { const struct ofpact_enqueue *enqueue; + const struct mf_field *mf; switch (a->type) { case OFPACT_OUTPUT: @@ -1662,6 +1764,15 @@ ofpact_check__(struct ofpact *a, struct flow *flow, ofp_port_t max_ports, case OFPACT_REG_LOAD: return nxm_reg_load_check(ofpact_get_REG_LOAD(a), flow); + case OFPACT_SET_FIELD: + mf = mf_from_id(ofpact_get_SET_FIELD(a)->field); + if (!mf_are_prereqs_ok(mf->set_prereqs, flow)) { + VLOG_WARN_RL(&rl, "set_field %s lacks correct prerequisities", + mf->name); + return OFPERR_OFPBAC_MATCH_INCONSISTENT; + } + return 0; + case OFPACT_STACK_PUSH: return nxm_stack_push_check(ofpact_get_STACK_PUSH(a), flow); @@ -1975,6 +2086,10 @@ ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out) nxm_reg_load_to_nxast(ofpact_get_REG_LOAD(a), out); break; + case OFPACT_SET_FIELD: + set_field_to_openflow(ofpact_get_SET_FIELD(a), out); + break; + case OFPACT_STACK_PUSH: nxm_stack_push_to_nxast(ofpact_get_STACK_PUSH(a), out); break; @@ -2180,6 +2295,7 @@ ofpact_to_openflow10(const struct ofpact *a, struct ofpbuf *out) case OFPACT_BUNDLE: case OFPACT_REG_MOVE: case OFPACT_REG_LOAD: + case OFPACT_SET_FIELD: case OFPACT_STACK_PUSH: case OFPACT_STACK_POP: case OFPACT_DEC_TTL: @@ -2382,6 +2498,7 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out) case OFPACT_BUNDLE: case OFPACT_REG_MOVE: case OFPACT_REG_LOAD: + case OFPACT_SET_FIELD: case OFPACT_STACK_PUSH: case OFPACT_STACK_POP: case OFPACT_SET_TUNNEL: @@ -2538,6 +2655,7 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, ofp_port_t port) case OFPACT_SET_L4_DST_PORT: case OFPACT_REG_MOVE: case OFPACT_REG_LOAD: + case OFPACT_SET_FIELD: case OFPACT_STACK_PUSH: case OFPACT_STACK_POP: case OFPACT_DEC_TTL: @@ -2693,6 +2811,8 @@ ofpact_format(const struct ofpact *a, struct ds *s) const struct ofpact_metadata *metadata; const struct ofpact_tunnel *tunnel; const struct ofpact_sample *sample; + const struct ofpact_set_field *set_field; + const struct mf_field *mf; ofp_port_t port; switch (a->type) { @@ -2826,6 +2946,14 @@ ofpact_format(const struct ofpact *a, struct ds *s) nxm_format_reg_load(ofpact_get_REG_LOAD(a), s); break; + case OFPACT_SET_FIELD: + set_field = ofpact_get_SET_FIELD(a); + mf = mf_from_id(set_field->field); + ds_put_format(s, "set_field:"); + mf_format(mf, &set_field->value, NULL, s); + ds_put_format(s, "->%s", mf->name); + break; + case OFPACT_STACK_PUSH: nxm_format_stack_push(ofpact_get_STACK_PUSH(a), s); break; @@ -3043,15 +3171,3 @@ ofpact_pad(struct ofpbuf *ofpacts) ofpbuf_put_zeros(ofpacts, OFPACT_ALIGNTO - rem); } } - -void -ofpact_set_field_init(struct ofpact_reg_load *load, const struct mf_field *mf, - const void *src) -{ - load->ofpact.compat = OFPUTIL_OFPAT12_SET_FIELD; - load->dst.field = mf; - load->dst.ofs = 0; - load->dst.n_bits = mf->n_bits; - bitwise_copy(src, mf->n_bytes, load->dst.ofs, - &load->subvalue, sizeof load->subvalue, 0, mf->n_bits); -} diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h index 7be4e92..1809db0 100644 --- a/lib/ofp-actions.h +++ b/lib/ofp-actions.h @@ -59,6 +59,7 @@ DEFINE_OFPACT(BUNDLE, ofpact_bundle, slaves) \ \ /* Header changes. */ \ + DEFINE_OFPACT(SET_FIELD, ofpact_set_field, ofpact) \ DEFINE_OFPACT(SET_VLAN_VID, ofpact_vlan_vid, ofpact) \ DEFINE_OFPACT(SET_VLAN_PCP, ofpact_vlan_pcp, ofpact) \ DEFINE_OFPACT(STRIP_VLAN, ofpact_null, ofpact) \ @@ -352,7 +353,7 @@ struct ofpact_stack { /* OFPACT_REG_LOAD. * - * Used for NXAST_REG_LOAD, OFPAT12_SET_FIELD. */ + * Used for NXAST_REG_LOAD. */ struct ofpact_reg_load { struct ofpact ofpact; struct mf_subfield dst; @@ -372,6 +373,15 @@ enum ofpact_mpls_position { OFPACT_MPLS_AFTER_VLAN }; +/* OFPACT_SET_FIELD. + * + * Used for OFPAT12_SET_FIELD. */ +struct ofpact_set_field { + struct ofpact ofpact; + enum mf_field_id field; + union mf_value value; /* Most-significant bits are used. */ +}; + /* OFPACT_PUSH_VLAN/MPLS/PBB * * Used for NXAST_PUSH_MPLS, OFPAT11_PUSH_MPLS. */ @@ -730,7 +740,4 @@ const char *ovs_instruction_name_from_type(enum ovs_instruction_type type); int ovs_instruction_type_from_name(const char *name); enum ovs_instruction_type ovs_instruction_type_from_ofpact_type( enum ofpact_type); - -void ofpact_set_field_init(struct ofpact_reg_load *load, - const struct mf_field *mf, const void *src); #endif /* ofp-actions.h */ diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index 1ada870..abe5297 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -465,13 +465,12 @@ static char * WARN_UNUSED_RESULT set_field_parse__(char *arg, struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols) { - struct ofpact_reg_load *load = ofpact_put_REG_LOAD(ofpacts); + struct ofpact_set_field *sf = ofpact_put_SET_FIELD(ofpacts); char *value; char *delim; char *key; const struct mf_field *mf; char *error; - union mf_value mf_value; value = arg; delim = strstr(arg, "->"); @@ -490,16 +489,16 @@ set_field_parse__(char *arg, struct ofpbuf *ofpacts, if (!mf->writable) { return xasprintf("%s is read-only", key); } - + sf->field = mf->id; delim[0] = '\0'; - error = mf_parse_value(mf, value, &mf_value); + error = mf_parse_value(mf, value, &sf->value); if (error) { return error; } - if (!mf_is_value_valid(mf, &mf_value)) { + + if (!mf_is_value_valid_for_set_field(mf, &sf->value)) { return xasprintf("%s is not a valid value for field %s", value, key); } - ofpact_set_field_init(load, mf, &mf_value); *usable_protocols &= mf->usable_protocols; return NULL; @@ -1982,7 +1981,7 @@ parse_ofp_exact_flow(struct flow *flow, struct flow *mask, const char *s, goto exit; } - if (!mf_are_prereqs_ok(mf, flow)) { + if (!mf_are_prereqs_ok(mf->match_prereqs, flow)) { error = xasprintf("%s: prerequisites not met for setting %s", s, key); goto exit; diff --git a/lib/ofp-util.h b/lib/ofp-util.h index 1f77808..d7df58b 100644 --- a/lib/ofp-util.h +++ b/lib/ofp-util.h @@ -31,6 +31,7 @@ struct ofpbuf; union ofp_action; +struct ofpact_set_field; /* Port numbers. */ enum ofperr ofputil_port_from_ofp11(ovs_be32 ofp11_port, diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 3340eea..bee6123 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -2292,6 +2292,8 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) { struct ofpact_controller *controller; const struct ofpact_metadata *metadata; + const struct ofpact_set_field *set_field; + const struct mf_field *mf; if (ctx->exit) { break; @@ -2436,6 +2438,13 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, nxm_execute_reg_load(ofpact_get_REG_LOAD(a), flow, wc); break; + case OFPACT_SET_FIELD: + set_field = ofpact_get_SET_FIELD(a); + mf = mf_from_id(set_field->field); + mf_mask_field_and_prereqs(mf, &wc->masks); + mf_set_flow_value(mf, &set_field->value, flow); + break; + case OFPACT_STACK_PUSH: nxm_execute_stack_push(ofpact_get_STACK_PUSH(a), flow, wc, &ctx->stack); diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index f40f053..420889c 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -6366,7 +6366,7 @@ eviction_group_hash_rule(struct rule *rule) sf < &table->eviction_fields[table->n_eviction_fields]; sf++) { - if (mf_are_prereqs_ok(sf->field, &flow)) { + if (mf_are_prereqs_ok(sf->field->match_prereqs, &flow)) { union mf_value value; mf_get_value(sf->field, &flow, &value); diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 1a1d423..b04ffd7 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -933,8 +933,10 @@ compare_flows(const void *afs_, const void *bfs_) } else { bool ina, inb; - ina = mf_are_prereqs_ok(f, &a->flow) && !mf_is_all_wild(f, &a->wc); - inb = mf_are_prereqs_ok(f, &b->flow) && !mf_is_all_wild(f, &b->wc); + ina = mf_are_prereqs_ok(f->match_prereqs, &a->flow) + && !mf_is_all_wild(f, &a->wc); + inb = mf_are_prereqs_ok(f->match_prereqs, &b->flow) + && !mf_is_all_wild(f, &b->wc); if (ina != inb) { /* Skip the test for sc->order, so that missing fields always * sort to the end whether we're sorting in ascending or -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev