#include "ofpbuf.h"
#include "unaligned.h"
#include "util.h"
-#include "vlog.h"
+#include "openvswitch/vlog.h"
VLOG_DEFINE_THIS_MODULE(ofp_actions);
/* 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,
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);
}
}
-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)
{
}
}
-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)
{
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)
{
}
}
-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)
{
}
}
-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)
{
}
}
-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);
}
}
-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;
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)
{
}
}
-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;
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)
{
}
}
-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)
{
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;
}
}
-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)
{
}
-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)
{
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)
{
}
}
-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)
{
}
}
-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)
{
}
}
-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)
{
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)
{
&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)
{
};
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
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;
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)
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);
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);
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);
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)
{
*
* 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)
{
*
* 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)
{
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);
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)
{
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)
{
}
}
-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)
{
}
}
-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)
{
*
* 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)
{
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)
{
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)
{
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)
{
}
}
-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)
{
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)
{
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)
{
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)
{
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)
{
}
}
-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)
{
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)
{
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)
{
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)
{
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)
{
*
* 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)
{
}
}
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
parse_METER(char *arg, struct ofpbuf *ofpacts,
enum ofputil_protocol *usable_protocols)
{
}
}
-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)
{
}
}
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
parse_WRITE_ACTIONS(char *arg, struct ofpbuf *ofpacts,
enum ofputil_protocol *usable_protocols)
{
}
}
-static char * WARN_UNUSED_RESULT
+static char * OVS_WARN_UNUSED_RESULT
parse_WRITE_METADATA(char *arg, struct ofpbuf *ofpacts,
enum ofputil_protocol *usable_protocols)
{
}
}
-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)
{
-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)
{
*
* 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)
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)
{
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)
*
* 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)
{
*
* 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)
{
};
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,
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;
}
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;
}