[ovs-dev] [PATCH v2 10/15] Native OpenFlow 1.2 set field action.

Jarno Rajahalme jrajahalme at nicira.com
Wed Oct 23 00:20:48 UTC 2013


Signed-off-by: Jarno Rajahalme <jrajahalme at 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 14ee470..31a4980 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
@@ -51,7 +51,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",
@@ -62,7 +62,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",
@@ -73,7 +73,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",
@@ -84,7 +84,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,
@@ -95,7 +95,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,
@@ -106,7 +106,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,
@@ -117,7 +117,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",
@@ -128,7 +128,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",
@@ -139,7 +139,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",
@@ -150,7 +150,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,
@@ -161,7 +161,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",
@@ -175,7 +175,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,     \
@@ -219,7 +219,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",
@@ -230,7 +230,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",
@@ -241,7 +241,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",
@@ -254,7 +254,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",
@@ -265,7 +265,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,
@@ -273,10 +273,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",
@@ -287,7 +287,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,
@@ -298,7 +298,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",
@@ -314,7 +314,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",
@@ -325,7 +325,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",
@@ -336,7 +336,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",
@@ -353,7 +353,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",
@@ -364,7 +364,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",
@@ -377,7 +377,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",
@@ -388,7 +388,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",
@@ -400,7 +400,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",
@@ -413,7 +413,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",
@@ -424,7 +424,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",
@@ -435,7 +435,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",
@@ -446,18 +446,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",
@@ -468,7 +468,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",
@@ -481,7 +481,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",
@@ -492,7 +492,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",
@@ -503,7 +503,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",
@@ -514,7 +514,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",
@@ -525,7 +525,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",
@@ -542,7 +542,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",
@@ -553,7 +553,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",
@@ -566,7 +566,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",
@@ -577,7 +577,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",
@@ -590,7 +590,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",
@@ -601,7 +601,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",
@@ -614,7 +614,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",
@@ -625,7 +625,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",
@@ -638,7 +638,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",
@@ -649,7 +649,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",
@@ -666,7 +666,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",
@@ -677,7 +677,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",
@@ -688,7 +688,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",
@@ -964,9 +964,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;
 
@@ -1023,7 +1023,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:
@@ -1053,6 +1053,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.
  *
@@ -1064,7 +1148,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:
@@ -2134,7 +2219,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 f1b7c72..989fef0 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -759,6 +759,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)
 {
@@ -884,7 +982,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;
@@ -932,6 +1030,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:
@@ -996,6 +1095,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:
@@ -1277,6 +1377,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:
@@ -1559,6 +1660,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:
@@ -1652,6 +1754,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);
 
@@ -1974,6 +2085,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;
@@ -2179,6 +2294,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:
@@ -2381,6 +2497,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:
@@ -2537,6 +2654,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:
@@ -2692,6 +2810,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) {
@@ -2825,6 +2945,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;
@@ -3042,15 +3170,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 44e60d8..9065237 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 6303c44..d3a129e 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -2288,6 +2288,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;
@@ -2432,6 +2434,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




More information about the dev mailing list