lib: Move vlog.h to <openvswitch/vlog.h>
[cascardo/ovs.git] / lib / ofp-actions.c
index ced4f2f..4680d81 100644 (file)
@@ -30,7 +30,7 @@
 #include "ofpbuf.h"
 #include "unaligned.h"
 #include "util.h"
-#include "vlog.h"
+#include "openvswitch/vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(ofp_actions);
 
@@ -218,6 +218,8 @@ enum ofp_raw_action_type {
 
     /* OF1.5+(28): struct ofp15_action_copy_field, ... */
     OFPAT_RAW15_COPY_FIELD,
+    /* ONF1.3-1.4(3200): struct onf_action_copy_field, ... */
+    ONFACT_RAW13_COPY_FIELD,
     /* NX1.0-1.4(6): struct nx_action_reg_move, ... */
     NXAST_RAW_REG_MOVE,
 
@@ -326,7 +328,7 @@ static enum ofperr ofpact_pull_raw(struct ofpbuf *, enum ofp_version,
 static void *ofpact_put_raw(struct ofpbuf *, enum ofp_version,
                             enum ofp_raw_action_type, uint64_t arg);
 
-static char *WARN_UNUSED_RESULT ofpacts_parse(
+static char *OVS_WARN_UNUSED_RESULT ofpacts_parse(
     char *str, struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols,
     bool allow_instructions);
 
@@ -409,7 +411,7 @@ encode_OUTPUT(const struct ofpact_output *output,
     }
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_OUTPUT(const char *arg, struct ofpbuf *ofpacts,
              enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -464,7 +466,7 @@ encode_GROUP(const struct ofpact_group *group,
     }
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_GROUP(char *arg, struct ofpbuf *ofpacts,
                     enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -527,7 +529,7 @@ encode_CONTROLLER(const struct ofpact_controller *controller,
     nac->reason = controller->reason;
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_CONTROLLER(char *arg, struct ofpbuf *ofpacts,
                   enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -656,7 +658,7 @@ encode_ENQUEUE(const struct ofpact_enqueue *enqueue,
     }
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_ENQUEUE(char *arg, struct ofpbuf *ofpacts,
               enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -813,7 +815,7 @@ encode_OUTPUT_REG(const struct ofpact_output_reg *output_reg,
     }
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_OUTPUT_REG(const char *arg, struct ofpbuf *ofpacts,
                  enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -1017,14 +1019,14 @@ encode_BUNDLE(const struct ofpact_bundle *bundle,
     }
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_BUNDLE(const char *arg, struct ofpbuf *ofpacts,
              enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
     return bundle_parse(arg, ofpacts);
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_bundle_load(const char *arg, struct ofpbuf *ofpacts)
 {
     return bundle_parse_load(arg, ofpacts);
@@ -1087,7 +1089,7 @@ encode_SET_VLAN_VID(const struct ofpact_vlan_vid *vlan_vid,
     }
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_set_vlan_vid(char *arg, struct ofpbuf *ofpacts, bool push_vlan_if_needed)
 {
     struct ofpact_vlan_vid *vlan_vid;
@@ -1108,7 +1110,7 @@ parse_set_vlan_vid(char *arg, struct ofpbuf *ofpacts, bool push_vlan_if_needed)
     return NULL;
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_SET_VLAN_VID(char *arg, struct ofpbuf *ofpacts,
                    enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -1173,7 +1175,7 @@ encode_SET_VLAN_PCP(const struct ofpact_vlan_pcp *vlan_pcp,
     }
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_set_vlan_pcp(char *arg, struct ofpbuf *ofpacts, bool push_vlan_if_needed)
 {
     struct ofpact_vlan_pcp *vlan_pcp;
@@ -1194,7 +1196,7 @@ parse_set_vlan_pcp(char *arg, struct ofpbuf *ofpacts, bool push_vlan_if_needed)
     return NULL;
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_SET_VLAN_PCP(char *arg, struct ofpbuf *ofpacts,
                    enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -1236,7 +1238,7 @@ encode_STRIP_VLAN(const struct ofpact_null *null OVS_UNUSED,
     }
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_STRIP_VLAN(char *arg OVS_UNUSED, struct ofpbuf *ofpacts,
                  enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -1244,7 +1246,7 @@ parse_STRIP_VLAN(char *arg OVS_UNUSED, struct ofpbuf *ofpacts,
     return NULL;
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_pop_vlan(struct ofpbuf *ofpacts)
 {
     ofpact_put_STRIP_VLAN(ofpacts)->ofpact.raw = OFPAT_RAW11_POP_VLAN;
@@ -1285,7 +1287,7 @@ encode_PUSH_VLAN(const struct ofpact_null *null OVS_UNUSED,
     }
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_PUSH_VLAN(char *arg, struct ofpbuf *ofpacts,
                 enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -1376,14 +1378,14 @@ encode_SET_ETH_DST(const struct ofpact_mac *mac,
 
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_SET_ETH_SRC(char *arg, struct ofpbuf *ofpacts,
                  enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
     return str_to_mac(arg, ofpact_put_SET_ETH_SRC(ofpacts)->mac);
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_SET_ETH_DST(char *arg, struct ofpbuf *ofpacts,
                  enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -1448,14 +1450,14 @@ encode_SET_IPV4_DST(const struct ofpact_ipv4 *ipv4,
                          out);
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_SET_IPV4_SRC(char *arg, struct ofpbuf *ofpacts,
                    enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
     return str_to_ip(arg, &ofpact_put_SET_IPV4_SRC(ofpacts)->ipv4);
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_SET_IPV4_DST(char *arg, struct ofpbuf *ofpacts,
                    enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -1499,7 +1501,7 @@ encode_SET_IP_DSCP(const struct ofpact_dscp *dscp,
     }
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_SET_IP_DSCP(char *arg, struct ofpbuf *ofpacts,
                  enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -1551,7 +1553,7 @@ encode_SET_IP_ECN(const struct ofpact_ecn *ip_ecn,
     }
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_SET_IP_ECN(char *arg, struct ofpbuf *ofpacts,
                  enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -1596,7 +1598,7 @@ encode_SET_IP_TTL(const struct ofpact_ip_ttl *ttl,
     }
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_SET_IP_TTL(char *arg, struct ofpbuf *ofpacts,
                   enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -1675,7 +1677,7 @@ encode_SET_L4_DST_PORT(const struct ofpact_l4_port *l4_port,
     encode_SET_L4_port(l4_port, ofp_version, OFPAT_RAW_SET_TP_DST, field, out);
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_SET_L4_SRC_PORT(char *arg, struct ofpbuf *ofpacts,
                       enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -1683,7 +1685,7 @@ parse_SET_L4_SRC_PORT(char *arg, struct ofpbuf *ofpacts,
                       &ofpact_put_SET_L4_SRC_PORT(ofpacts)->port);
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_SET_L4_DST_PORT(char *arg, struct ofpbuf *ofpacts,
                       enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -1720,6 +1722,26 @@ struct ofp15_action_copy_field {
 };
 OFP_ASSERT(sizeof(struct ofp15_action_copy_field) == 16);
 
+/* Action structure for OpenFlow 1.3 extension copy-field action.. */
+struct onf_action_copy_field {
+    ovs_be16 type;              /* OFPAT_EXPERIMENTER. */
+    ovs_be16 len;               /* Length is padded to 64 bits. */
+    ovs_be32 experimenter;      /* ONF_VENDOR_ID. */
+    ovs_be16 exp_type;          /* 3200. */
+    uint8_t pad[2];             /* Not used. */
+    ovs_be16 n_bits;            /* Number of bits to copy. */
+    ovs_be16 src_offset;        /* Starting bit offset in source. */
+    ovs_be16 dst_offset;        /* Starting bit offset in destination. */
+    uint8_t pad2[2];            /* Not used. */
+    /* Followed by:
+     * - OXM header for source field.
+     * - OXM header for destination field.
+     * - Padding with 0-bytes (either 0 or 4 of them) to a multiple of 8 bytes.
+     * The "pad3" member is the beginning of the above. */
+    uint8_t pad3[4];            /* Not used. */
+};
+OFP_ASSERT(sizeof(struct onf_action_copy_field) == 24);
+
 /* Action structure for NXAST_REG_MOVE.
  *
  * Copies src[src_ofs:src_ofs+n_bits] to dst[dst_ofs:dst_ofs+n_bits], where
@@ -1828,21 +1850,23 @@ struct nx_action_reg_move {
 OFP_ASSERT(sizeof(struct nx_action_reg_move) == 16);
 
 static enum ofperr
-decode_OFPAT_RAW15_COPY_FIELD(const struct ofp15_action_copy_field *oacf,
-                              struct ofpbuf *ofpacts)
+decode_copy_field__(ovs_be16 src_offset, ovs_be16 dst_offset, ovs_be16 n_bits,
+                    const void *action, ovs_be16 action_len, size_t oxm_offset,
+                    struct ofpbuf *ofpacts)
 {
     struct ofpact_reg_move *move;
     enum ofperr error;
     struct ofpbuf b;
 
     move = ofpact_put_REG_MOVE(ofpacts);
-    move->src.ofs = ntohs(oacf->src_offset);
-    move->src.n_bits = ntohs(oacf->n_bits);
-    move->dst.ofs = ntohs(oacf->dst_offset);
-    move->dst.n_bits = ntohs(oacf->n_bits);
-
-    ofpbuf_use_const(&b, oacf, ntohs(oacf->len));
-    ofpbuf_pull(&b, offsetof(struct ofp15_action_copy_field, pad2));
+    move->ofpact.raw = ONFACT_RAW13_COPY_FIELD;
+    move->src.ofs = ntohs(src_offset);
+    move->src.n_bits = ntohs(n_bits);
+    move->dst.ofs = ntohs(dst_offset);
+    move->dst.n_bits = ntohs(n_bits);
+
+    ofpbuf_use_const(&b, action, ntohs(action_len));
+    ofpbuf_pull(&b, oxm_offset);
     error = nx_pull_header(&b, &move->src.field, NULL);
     if (error) {
         return error;
@@ -1859,6 +1883,24 @@ decode_OFPAT_RAW15_COPY_FIELD(const struct ofp15_action_copy_field *oacf,
     return nxm_reg_move_check(move, NULL);
 }
 
+static enum ofperr
+decode_OFPAT_RAW15_COPY_FIELD(const struct ofp15_action_copy_field *oacf,
+                              struct ofpbuf *ofpacts)
+{
+    return decode_copy_field__(oacf->src_offset, oacf->dst_offset,
+                               oacf->n_bits, oacf, oacf->len,
+                               OBJECT_OFFSETOF(oacf, pad2), ofpacts);
+}
+
+static enum ofperr
+decode_ONFACT_RAW13_COPY_FIELD(const struct onf_action_copy_field *oacf,
+                               struct ofpbuf *ofpacts)
+{
+    return decode_copy_field__(oacf->src_offset, oacf->dst_offset,
+                               oacf->n_bits, oacf, oacf->len,
+                               OBJECT_OFFSETOF(oacf, pad3), ofpacts);
+}
+
 static enum ofperr
 decode_NXAST_RAW_REG_MOVE(const struct nx_action_reg_move *narm,
                           struct ofpbuf *ofpacts)
@@ -1868,6 +1910,7 @@ decode_NXAST_RAW_REG_MOVE(const struct nx_action_reg_move *narm,
     struct ofpbuf b;
 
     move = ofpact_put_REG_MOVE(ofpacts);
+    move->ofpact.raw = NXAST_RAW_REG_MOVE;
     move->src.ofs = ntohs(narm->src_ofs);
     move->src.n_bits = ntohs(narm->n_bits);
     move->dst.ofs = ntohs(narm->dst_ofs);
@@ -1894,6 +1937,12 @@ static void
 encode_REG_MOVE(const struct ofpact_reg_move *move,
                 enum ofp_version ofp_version, struct ofpbuf *out)
 {
+    /* For OpenFlow 1.3, the choice of ONFACT_RAW13_COPY_FIELD versus
+     * NXAST_RAW_REG_MOVE is somewhat difficult.  Neither one is guaranteed to
+     * be supported by every OpenFlow 1.3 implementation.  It would be ideal to
+     * probe for support.  Until we have that ability, we currently prefer
+     * NXAST_RAW_REG_MOVE for backward compatibility with older Open vSwitch
+     * versions.  */
     size_t start_ofs = ofpbuf_size(out);
     if (ofp_version >= OFP15_VERSION) {
         struct ofp15_action_copy_field *copy = put_OFPAT15_COPY_FIELD(out);
@@ -1903,6 +1952,15 @@ encode_REG_MOVE(const struct ofpact_reg_move *move,
         ofpbuf_set_size(out, ofpbuf_size(out) - sizeof copy->pad2);
         nx_put_header(out, move->src.field->id, ofp_version, false);
         nx_put_header(out, move->dst.field->id, ofp_version, false);
+    } else if (ofp_version == OFP13_VERSION
+               && move->ofpact.raw == ONFACT_RAW13_COPY_FIELD) {
+        struct onf_action_copy_field *copy = put_ONFACT13_COPY_FIELD(out);
+        copy->n_bits = htons(move->dst.n_bits);
+        copy->src_offset = htons(move->src.ofs);
+        copy->dst_offset = htons(move->dst.ofs);
+        ofpbuf_set_size(out, ofpbuf_size(out) - sizeof copy->pad3);
+        nx_put_header(out, move->src.field->id, ofp_version, false);
+        nx_put_header(out, move->dst.field->id, ofp_version, false);
     } else {
         struct nx_action_reg_move *narm = put_NXAST_REG_MOVE(out);
         narm->n_bits = htons(move->dst.n_bits);
@@ -1914,7 +1972,7 @@ encode_REG_MOVE(const struct ofpact_reg_move *move,
     pad_ofpat(out, start_ofs);
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_REG_MOVE(const char *arg, struct ofpbuf *ofpacts,
                enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -2391,7 +2449,7 @@ encode_SET_FIELD(const struct ofpact_set_field *sf,
  *
  * Returns NULL if successful, otherwise a malloc()'d string describing the
  * error.  The caller is responsible for freeing the returned string. */
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 set_field_parse__(char *arg, struct ofpbuf *ofpacts,
                   enum ofputil_protocol *usable_protocols)
 {
@@ -2439,7 +2497,7 @@ set_field_parse__(char *arg, struct ofpbuf *ofpacts,
  *
  * Returns NULL if successful, otherwise a malloc()'d string describing the
  * error.  The caller is responsible for freeing the returned string. */
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_SET_FIELD(const char *arg, struct ofpbuf *ofpacts,
                 enum ofputil_protocol *usable_protocols)
 {
@@ -2449,7 +2507,7 @@ parse_SET_FIELD(const char *arg, struct ofpbuf *ofpacts,
     return error;
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_reg_load(char *arg, struct ofpbuf *ofpacts)
 {
     struct ofpact_set_field *sf = ofpact_put_reg_load(ofpacts);
@@ -2605,14 +2663,14 @@ encode_STACK_POP(const struct ofpact_stack *stack,
     encode_STACK_op(stack, put_NXAST_STACK_POP(out));
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_STACK_PUSH(char *arg, struct ofpbuf *ofpacts,
                  enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
     return nxm_parse_stack_action(ofpact_put_STACK_PUSH(ofpacts), arg);
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_STACK_POP(char *arg, struct ofpbuf *ofpacts,
                 enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -2747,7 +2805,7 @@ parse_noargs_dec_ttl(struct ofpbuf *ofpacts)
     ofpact_update_len(ofpacts, &ids->ofpact);
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_DEC_TTL(char *arg, struct ofpbuf *ofpacts,
               enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -2816,7 +2874,7 @@ encode_SET_MPLS_LABEL(const struct ofpact_mpls_label *label,
     }
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_SET_MPLS_LABEL(char *arg, struct ofpbuf *ofpacts,
                      enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -2855,7 +2913,7 @@ encode_SET_MPLS_TC(const struct ofpact_mpls_tc *tc,
     }
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_SET_MPLS_TC(char *arg, struct ofpbuf *ofpacts,
                   enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -2896,7 +2954,7 @@ encode_SET_MPLS_TTL(const struct ofpact_mpls_ttl *ttl,
  *
  * Returns NULL if successful, otherwise a malloc()'d string describing the
  * error.  The caller is responsible for freeing the returned string. */
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_SET_MPLS_TTL(char *arg, struct ofpbuf *ofpacts,
                    enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -2932,7 +2990,7 @@ encode_DEC_MPLS_TTL(const struct ofpact_null *null OVS_UNUSED,
     put_OFPAT_DEC_MPLS_TTL(out, ofp_version);
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_DEC_MPLS_TTL(char *arg OVS_UNUSED, struct ofpbuf *ofpacts,
                    enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -2969,7 +3027,7 @@ encode_PUSH_MPLS(const struct ofpact_push_mpls *push_mpls,
     put_OFPAT_PUSH_MPLS(out, ofp_version, push_mpls->ethertype);
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_PUSH_MPLS(char *arg, struct ofpbuf *ofpacts,
                 enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -3005,7 +3063,7 @@ encode_POP_MPLS(const struct ofpact_pop_mpls *pop_mpls,
     put_OFPAT_POP_MPLS(out, ofp_version, pop_mpls->ethertype);
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_POP_MPLS(char *arg, struct ofpbuf *ofpacts,
                     enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -3063,7 +3121,7 @@ encode_SET_TUNNEL(const struct ofpact_tunnel *tunnel,
     }
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_set_tunnel(char *arg, struct ofpbuf *ofpacts,
                  enum ofp_raw_action_type raw)
 {
@@ -3074,7 +3132,7 @@ parse_set_tunnel(char *arg, struct ofpbuf *ofpacts,
     return str_to_u64(arg, &tunnel->tun_id);
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_SET_TUNNEL(char *arg, struct ofpbuf *ofpacts,
                  enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -3106,7 +3164,7 @@ encode_SET_QUEUE(const struct ofpact_queue *queue,
     put_OFPAT_SET_QUEUE(out, ofp_version, queue->queue_id);
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_SET_QUEUE(char *arg, struct ofpbuf *ofpacts,
                 enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -3135,7 +3193,7 @@ encode_POP_QUEUE(const struct ofpact_null *null OVS_UNUSED,
     put_NXAST_POP_QUEUE(out);
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_POP_QUEUE(const char *arg OVS_UNUSED, struct ofpbuf *ofpacts,
                 enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -3205,7 +3263,7 @@ encode_FIN_TIMEOUT(const struct ofpact_fin_timeout *fin_timeout,
     naft->fin_hard_timeout = htons(fin_timeout->fin_hard_timeout);
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_FIN_TIMEOUT(char *arg, struct ofpbuf *ofpacts,
                   enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -3347,7 +3405,7 @@ encode_RESUBMIT(const struct ofpact_resubmit *resubmit,
     }
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_RESUBMIT(char *arg, struct ofpbuf *ofpacts,
                enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -3827,7 +3885,7 @@ encode_LEARN(const struct ofpact_learn *learn,
     pad_ofpat(out, start_ofs);
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_LEARN(char *arg, struct ofpbuf *ofpacts,
             enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -3947,7 +4005,7 @@ encode_MULTIPATH(const struct ofpact_multipath *mp,
     nam->dst = htonl(mf_nxm_header(mp->dst.field->id));
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_MULTIPATH(const char *arg, struct ofpbuf *ofpacts,
                 enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -4016,7 +4074,7 @@ encode_NOTE(const struct ofpact_note *note,
     nan->len = htons(ofpbuf_size(out) - start_ofs);
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_NOTE(const char *arg, struct ofpbuf *ofpacts,
            enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -4079,7 +4137,7 @@ encode_EXIT(const struct ofpact_null *null OVS_UNUSED,
     put_NXAST_EXIT(out);
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_EXIT(char *arg OVS_UNUSED, struct ofpbuf *ofpacts,
            enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -4154,7 +4212,7 @@ encode_SAMPLE(const struct ofpact_sample *sample,
  *
  * Returns NULL if successful, otherwise a malloc()'d string describing the
  * error.  The caller is responsible for freeing the returned string. */
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_SAMPLE(char *arg, struct ofpbuf *ofpacts,
              enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -4209,7 +4267,7 @@ encode_METER(const struct ofpact_meter *meter,
     }
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_METER(char *arg, struct ofpbuf *ofpacts,
             enum ofputil_protocol *usable_protocols)
 {
@@ -4235,7 +4293,7 @@ encode_CLEAR_ACTIONS(const struct ofpact_null *null OVS_UNUSED,
     }
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_CLEAR_ACTIONS(char *arg OVS_UNUSED, struct ofpbuf *ofpacts,
                     enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -4266,7 +4324,7 @@ encode_WRITE_ACTIONS(const struct ofpact_nest *actions,
     }
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_WRITE_ACTIONS(char *arg, struct ofpbuf *ofpacts,
                     enum ofputil_protocol *usable_protocols)
 {
@@ -4360,7 +4418,7 @@ encode_WRITE_METADATA(const struct ofpact_metadata *metadata,
     }
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_WRITE_METADATA(char *arg, struct ofpbuf *ofpacts,
                      enum ofputil_protocol *usable_protocols)
 {
@@ -4415,7 +4473,7 @@ encode_GOTO_TABLE(const struct ofpact_goto_table *goto_table,
     }
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 parse_GOTO_TABLE(char *arg, struct ofpbuf *ofpacts,
                  enum ofputil_protocol *usable_protocols OVS_UNUSED)
 {
@@ -6007,7 +6065,7 @@ ofpact_pad(struct ofpbuf *ofpacts)
 
 
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 ofpact_parse(enum ofpact_type type, char *value, struct ofpbuf *ofpacts,
              enum ofputil_protocol *usable_protocols)
 {
@@ -6040,7 +6098,7 @@ ofpact_type_from_name(const char *name, enum ofpact_type *type)
  *
  * Returns NULL if successful, otherwise a malloc()'d string describing the
  * error.  The caller is responsible for freeing the returned string. */
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 ofpacts_parse__(char *str, struct ofpbuf *ofpacts,
                 enum ofputil_protocol *usable_protocols,
                 bool allow_instructions)
@@ -6125,7 +6183,7 @@ ofpacts_parse__(char *str, struct ofpbuf *ofpacts,
     return NULL;
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 ofpacts_parse(char *str, struct ofpbuf *ofpacts,
               enum ofputil_protocol *usable_protocols, bool allow_instructions)
 {
@@ -6138,7 +6196,7 @@ ofpacts_parse(char *str, struct ofpbuf *ofpacts,
     return error;
 }
 
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
 ofpacts_parse_copy(const char *s_, struct ofpbuf *ofpacts,
                    enum ofputil_protocol *usable_protocols,
                    bool allow_instructions)
@@ -6159,7 +6217,7 @@ ofpacts_parse_copy(const char *s_, struct ofpbuf *ofpacts,
  *
  * Returns NULL if successful, otherwise a malloc()'d string describing the
  * error.  The caller is responsible for freeing the returned string. */
-char * WARN_UNUSED_RESULT
+char * OVS_WARN_UNUSED_RESULT
 ofpacts_parse_actions(const char *s, struct ofpbuf *ofpacts,
                       enum ofputil_protocol *usable_protocols)
 {
@@ -6171,7 +6229,7 @@ ofpacts_parse_actions(const char *s, struct ofpbuf *ofpacts,
  *
  * Returns NULL if successful, otherwise a malloc()'d string describing the
  * error.  The caller is responsible for freeing the returned string. */
-char * WARN_UNUSED_RESULT
+char * OVS_WARN_UNUSED_RESULT
 ofpacts_parse_instructions(const char *s, struct ofpbuf *ofpacts,
                            enum ofputil_protocol *usable_protocols)
 {
@@ -6253,15 +6311,20 @@ struct ofp_action_header {
 };
 OFP_ASSERT(sizeof(struct ofp_action_header) == 8);
 
-/* Header for Nicira-defined actions. */
-struct nx_action_header {
+/* Header for Nicira-defined actions and for ONF vendor extensions.
+ *
+ * This cannot be used as an entirely generic vendor extension action header,
+ * because OpenFlow does not specify the location or size of the action
+ * subtype; it just happens that ONF extensions and Nicira extensions share
+ * this format. */
+struct ext_action_header {
     ovs_be16 type;                  /* OFPAT_VENDOR. */
     ovs_be16 len;                   /* At least 16. */
-    ovs_be32 vendor;                /* NX_VENDOR_ID. */
+    ovs_be32 vendor;                /* NX_VENDOR_ID or ONF_VENDOR_ID. */
     ovs_be16 subtype;               /* See enum ofp_raw_action_type. */
     uint8_t pad[6];
 };
-OFP_ASSERT(sizeof(struct nx_action_header) == 16);
+OFP_ASSERT(sizeof(struct ext_action_header) == 16);
 
 static bool
 ofpact_hdrs_equal(const struct ofpact_hdrs *a,
@@ -6339,11 +6402,11 @@ ofpact_decode_raw(enum ofp_version ofp_version,
     if (oah->type == htons(OFPAT_VENDOR)) {
         /* Get vendor. */
         hdrs.vendor = ntohl(oah->vendor);
-        if (hdrs.vendor == NX_VENDOR_ID) {
-            /* Get Nicira action type. */
-            const struct nx_action_header *nah;
+        if (hdrs.vendor == NX_VENDOR_ID || hdrs.vendor == ONF_VENDOR_ID) {
+            /* Get extension subtype. */
+            const struct ext_action_header *nah;
 
-            nah = ALIGNED_CAST(const struct nx_action_header *, oah);
+            nah = ALIGNED_CAST(const struct ext_action_header *, oah);
             if (length < sizeof *nah) {
                 return OFPERR_OFPBAC_BAD_LEN;
             }
@@ -6462,8 +6525,9 @@ ofpact_put_raw(struct ofpbuf *buf, enum ofp_version ofp_version,
     case 0:
         break;
 
-    case NX_VENDOR_ID: {
-        struct nx_action_header *nah = (struct nx_action_header *) oah;
+    case NX_VENDOR_ID:
+    case ONF_VENDOR_ID: {
+        struct ext_action_header *nah = (struct ext_action_header *) oah;
         nah->subtype = htons(hdrs->type);
         break;
     }