/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/* NX1.0+(29): struct nx_action_sample. */
NXAST_RAW_SAMPLE,
+
+ /* NX1.0+(34): struct nx_action_conjunction. */
+ NXAST_RAW_CONJUNCTION,
};
/* OpenFlow actions are always a multiple of 8 bytes in length. */
if (error) {
return error;
}
- if (!is_all_zeros(ofpbuf_data(&b), ofpbuf_size(&b))) {
+ if (!is_all_zeros(b.data, b.size)) {
return OFPERR_NXBRC_MUST_BE_ZERO;
}
if (output_reg->ofpact.raw == NXAST_RAW_OUTPUT_REG2
|| !mf_nxm_header(output_reg->src.field->id)) {
struct nx_action_output_reg2 *naor = put_NXAST_OUTPUT_REG2(out);
- size_t size = ofpbuf_size(out);
+ size_t size = out->size;
naor->ofs_nbits = nxm_encode_ofs_nbits(output_reg->src.ofs,
output_reg->src.n_bits);
naor->max_len = htons(output_reg->max_len);
- ofpbuf_set_size(out, size - sizeof naor->pad);
+ out->size = size - sizeof naor->pad;
nx_put_header(out, output_reg->src.field->id, 0, false);
- ofpbuf_set_size(out, size);
+ out->size = size;
} else {
struct nx_action_output_reg *naor = put_NXAST_OUTPUT_REG(out);
ofpbuf_put(ofpacts, &ofp_port, sizeof ofp_port);
}
- bundle = ofpacts->frame;
+ bundle = ofpacts->header;
ofpact_update_len(ofpacts, &bundle->ofpact);
if (!error) {
return error;
}
- if (!is_all_zeros(ofpbuf_data(&b), ofpbuf_size(&b))) {
+ if (!is_all_zeros(b.data, b.size)) {
return OFPERR_NXBRC_MUST_BE_ZERO;
}
if (error) {
return error;
}
- if (!is_all_zeros(ofpbuf_data(&b), ofpbuf_size(&b))) {
+ if (!is_all_zeros(b.data, b.size)) {
return OFPERR_NXBRC_MUST_BE_ZERO;
}
* 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);
+ size_t start_ofs = out->size;
if (ofp_version >= OFP15_VERSION) {
struct ofp15_action_copy_field *copy = put_OFPAT15_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->pad2);
+ out->size = out->size - 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
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);
+ out->size = out->size - 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 {
memset(&sf->mask, 0xff, sf->field->n_bytes);
}
- if (!is_all_zeros(ofpbuf_data(&b), ofpbuf_size(&b))) {
+ if (!is_all_zeros(b.data, b.size)) {
return OFPERR_OFPBAC_BAD_SET_ARGUMENT;
}
return OFPERR_OFPBAC_BAD_SET_ARGUMENT;
}
- /* The value must be valid for match. The OpenFlow 1.5 draft also says,
+ /* The value must be valid for match. OpenFlow 1.5 also says,
* "In an OXM_OF_VLAN_VID set-field action, the OFPVID_PRESENT bit must be
* a 1-bit in oxm_value and in oxm_mask." */
if (!mf_is_value_valid(sf->field, &sf->value)
if (error) {
return error;
}
- if (!is_all_zeros(ofpbuf_data(&b), ofpbuf_size(&b))) {
+ if (!is_all_zeros(b.data, b.size)) {
return OFPERR_OFPBAC_BAD_SET_ARGUMENT;
}
{
struct ofp12_action_set_field *oasf OVS_UNUSED;
int n_bytes = mf_from_id(field)->n_bytes;
- size_t start_ofs = ofpbuf_size(openflow);
+ size_t start_ofs = openflow->size;
union mf_value value;
value.be64 = htonll(value_ << (8 * (8 - n_bytes)));
oasf = put_OFPAT12_SET_FIELD(openflow);
- ofpbuf_set_size(openflow, ofpbuf_size(openflow) - sizeof oasf->pad);
+ openflow->size = openflow->size - sizeof oasf->pad;
nx_put_entry(openflow, field, ofp_version, &value, NULL);
pad_ofpat(openflow, start_ofs);
}
if (sf->ofpact.raw == NXAST_RAW_REG_LOAD2
|| !mf_nxm_header(sf->field->id)) {
struct nx_action_reg_load2 *narl OVS_UNUSED;
- size_t start_ofs = ofpbuf_size(openflow);
+ size_t start_ofs = openflow->size;
narl = put_NXAST_REG_LOAD2(openflow);
- ofpbuf_set_size(openflow, ofpbuf_size(openflow) - sizeof narl->pad);
+ openflow->size = openflow->size - sizeof narl->pad;
nx_put_entry(openflow, sf->field->id, 0, &sf->value, &sf->mask);
pad_ofpat(openflow, start_ofs);
} else {
enum ofp_version ofp_version, struct ofpbuf *out)
{
struct ofp12_action_set_field *oasf OVS_UNUSED;
- size_t start_ofs = ofpbuf_size(out);
+ size_t start_ofs = out->size;
oasf = put_OFPAT12_SET_FIELD(out);
- ofpbuf_set_size(out, ofpbuf_size(out) - sizeof oasf->pad);
+ out->size = out->size - sizeof oasf->pad;
nx_put_entry(out, sf->field->id, ofp_version, &sf->value, &sf->mask);
pad_ofpat(out, start_ofs);
}
if (error) {
return error;
}
- stack_action->subfield.n_bits = ntohs(*(const ovs_be16 *) ofpbuf_data(&b));
+ stack_action->subfield.n_bits = ntohs(*(const ovs_be16 *) b.data);
ofpbuf_pull(&b, 2);
- if (!is_all_zeros(ofpbuf_data(&b), ofpbuf_size(&b))) {
+ if (!is_all_zeros(b.data, b.size)) {
return OFPERR_NXBRC_MUST_BE_ZERO;
}
ids = ofpact_put_DEC_TTL(out);
ids->n_controllers = 1;
ofpbuf_put(out, &id, sizeof id);
- ids = out->frame;
+ ids = out->header;
ofpact_update_len(out, &ids->ofpact);
return error;
}
for (i = 0; i < ids->n_controllers; i++) {
uint16_t id = ntohs(((ovs_be16 *)(nac_ids + 1))[i]);
ofpbuf_put(out, &id, sizeof id);
- ids = out->frame;
+ ids = out->header;
}
ofpact_update_len(out, &ids->ofpact);
ofpact_put_DEC_TTL(ofpacts);
ofpbuf_put(ofpacts, &id, sizeof id);
- ids = ofpacts->frame;
+ ids = ofpacts->header;
ids->n_controllers++;
ofpact_update_len(ofpacts, &ids->ofpact);
}
uint16_t id = atoi(cntr);
ofpbuf_put(ofpacts, &id, sizeof id);
- ids = ofpacts->frame;
+ ids = ofpacts->header;
ids->n_controllers++;
}
if (!ids->n_controllers) {
* address. This is not usually the intent in MAC learning; instead, we want
* the MAC learn entry to expire when no traffic has been sent *from* the
* learned address. Use a hard timeout for that.
- */
+ *
+ *
+ * Visibility of Changes
+ * ---------------------
+ *
+ * Prior to Open vSwitch 2.4, any changes made by a "learn" action in a given
+ * flow translation are visible to flow table lookups made later in the flow
+ * translation. This means that, in the example above, a MAC learned by the
+ * learn action in table 0 would be found in table 1 (if the packet being
+ * processed had the same source and destination MAC address).
+ *
+ * In Open vSwitch 2.4 and later, changes to a flow table (whether to add or
+ * modify a flow) by a "learn" action are visible only for later flow
+ * translations, not for later lookups within the same flow translation. In
+ * the MAC learning example, a MAC learned by the learn action in table 0 would
+ * not be found in table 1 if the flow translation would resubmit to table 1
+ * after the processing of the learn action, meaning that if this MAC had not
+ * been learned before then the packet would be flooded. */
struct nx_action_learn {
ovs_be16 type; /* OFPAT_VENDOR. */
ovs_be16 len; /* At least 24. */
}
spec = ofpbuf_put_zeros(ofpacts, sizeof *spec);
- learn = ofpacts->frame;
+ learn = ofpacts->header;
learn->n_specs++;
spec->src_type = header & NX_LEARN_SRC_MASK;
struct nx_action_learn *nal;
size_t start_ofs;
- start_ofs = ofpbuf_size(out);
+ start_ofs = out->size;
nal = put_NXAST_LEARN(out);
nal->idle_timeout = htons(learn->idle_timeout);
nal->hard_timeout = htons(learn->hard_timeout);
learn_format(a, s);
}
\f
+/* Action structure for NXAST_CONJUNCTION. */
+struct nx_action_conjunction {
+ ovs_be16 type; /* OFPAT_VENDOR. */
+ ovs_be16 len; /* At least 16. */
+ ovs_be32 vendor; /* NX_VENDOR_ID. */
+ ovs_be16 subtype; /* See enum ofp_raw_action_type. */
+ uint8_t clause;
+ uint8_t n_clauses;
+ ovs_be32 id;
+};
+OFP_ASSERT(sizeof(struct nx_action_conjunction) == 16);
+
+static void
+add_conjunction(struct ofpbuf *out,
+ uint32_t id, uint8_t clause, uint8_t n_clauses)
+{
+ struct ofpact_conjunction *oc;
+
+ oc = ofpact_put_CONJUNCTION(out);
+ oc->id = id;
+ oc->clause = clause;
+ oc->n_clauses = n_clauses;
+}
+
+static enum ofperr
+decode_NXAST_RAW_CONJUNCTION(const struct nx_action_conjunction *nac,
+ struct ofpbuf *out)
+{
+ if (nac->n_clauses < 2 || nac->n_clauses > 64
+ || nac->clause >= nac->n_clauses) {
+ return OFPERR_NXBAC_BAD_CONJUNCTION;
+ } else {
+ add_conjunction(out, ntohl(nac->id), nac->clause, nac->n_clauses);
+ return 0;
+ }
+}
+
+static void
+encode_CONJUNCTION(const struct ofpact_conjunction *oc,
+ enum ofp_version ofp_version OVS_UNUSED, struct ofpbuf *out)
+{
+ struct nx_action_conjunction *nac = put_NXAST_CONJUNCTION(out);
+ nac->clause = oc->clause;
+ nac->n_clauses = oc->n_clauses;
+ nac->id = htonl(oc->id);
+}
+
+static void
+format_CONJUNCTION(const struct ofpact_conjunction *oc, struct ds *s)
+{
+ ds_put_format(s, "conjunction(%"PRIu32",%"PRIu8"/%"PRIu8")",
+ oc->id, oc->clause + 1, oc->n_clauses);
+}
+
+static char * OVS_WARN_UNUSED_RESULT
+parse_CONJUNCTION(const char *arg, struct ofpbuf *ofpacts,
+ enum ofputil_protocol *usable_protocols OVS_UNUSED)
+{
+ uint8_t n_clauses;
+ uint8_t clause;
+ uint32_t id;
+ int n;
+
+ if (!ovs_scan(arg, "%"SCNi32" , %"SCNu8" / %"SCNu8" %n",
+ &id, &clause, &n_clauses, &n) || n != strlen(arg)) {
+ return xstrdup("\"conjunction\" syntax is \"conjunction(id,i/n)\"");
+ }
+
+ if (n_clauses < 2) {
+ return xstrdup("conjunction must have at least 2 clauses");
+ } else if (n_clauses > 64) {
+ return xstrdup("conjunction must have at most 64 clauses");
+ } else if (clause < 1) {
+ return xstrdup("clause index must be positive");
+ } else if (clause > n_clauses) {
+ return xstrdup("clause index must be less than or equal to "
+ "number of clauses");
+ }
+
+ add_conjunction(ofpacts, id, clause - 1, n_clauses);
+ return NULL;
+}
+\f
/* Action structure for NXAST_MULTIPATH.
*
* This action performs the following steps in sequence:
encode_NOTE(const struct ofpact_note *note,
enum ofp_version ofp_version OVS_UNUSED, struct ofpbuf *out)
{
- size_t start_ofs = ofpbuf_size(out);
+ size_t start_ofs = out->size;
struct nx_action_note *nan;
unsigned int remainder;
unsigned int len;
put_NXAST_NOTE(out);
- ofpbuf_set_size(out, ofpbuf_size(out) - sizeof nan->note);
+ out->size = out->size - sizeof nan->note;
ofpbuf_put(out, note->data, note->length);
- len = ofpbuf_size(out) - start_ofs;
+ len = out->size - start_ofs;
remainder = len % OFP_ACTION_ALIGN;
if (remainder) {
ofpbuf_put_zeros(out, OFP_ACTION_ALIGN - remainder);
}
nan = ofpbuf_at(out, start_ofs, sizeof *nan);
- nan->len = htons(ofpbuf_size(out) - start_ofs);
+ nan->len = htons(out->size - start_ofs);
}
static char * OVS_WARN_UNUSED_RESULT
}
ofpbuf_put(ofpacts, &byte, 1);
- note = ofpacts->frame;
+ note = ofpacts->header;
note->length++;
arg += 2;
ds_put_cstr(s, "exit");
}
\f
+/* Unroll xlate action. */
+
+static void
+encode_UNROLL_XLATE(const struct ofpact_unroll_xlate *unroll OVS_UNUSED,
+ enum ofp_version ofp_version OVS_UNUSED,
+ struct ofpbuf *out OVS_UNUSED)
+{
+ OVS_NOT_REACHED();
+}
+
+static char * OVS_WARN_UNUSED_RESULT
+parse_UNROLL_XLATE(char *arg OVS_UNUSED, struct ofpbuf *ofpacts OVS_UNUSED,
+ enum ofputil_protocol *usable_protocols OVS_UNUSED)
+{
+ OVS_NOT_REACHED();
+ return NULL;
+}
+
+static void
+format_UNROLL_XLATE(const struct ofpact_unroll_xlate *a OVS_UNUSED,
+ struct ds *s)
+{
+ ds_put_cstr(s, "unroll_xlate");
+}
+\f
/* Action structure for NXAST_SAMPLE.
*
* Samples matching packets with the given probability and sends them
enum ofp_version ofp_version, struct ofpbuf *out)
{
if (ofp_version > OFP10_VERSION) {
- const size_t ofs = ofpbuf_size(out);
+ const size_t ofs = out->size;
instruction_put_OFPIT11_WRITE_ACTIONS(out);
ofpacts_put_openflow_actions(actions->actions,
/* Pull off existing actions or instructions. */
ofpact_pad(ofpacts);
- ofs = ofpbuf_size(ofpacts);
+ ofs = ofpacts->size;
ofpbuf_pull(ofpacts, ofs);
/* Add a Write-Actions instruction and then pull it off. */
/* Put the Write-Actions back on and update its length. */
on = ofpbuf_push_uninit(ofpacts, sizeof *on);
- on->ofpact.len = ofpbuf_size(ofpacts);
+ on->ofpact.len = ofpacts->size;
/* Put any previous actions or instructions back on. */
ofpbuf_push_uninit(ofpacts, ofs);
struct ofpbuf openflow;
ofpbuf_use_const(&openflow, actions, actions_len);
- while (ofpbuf_size(&openflow)) {
- const struct ofp_action_header *action = ofpbuf_data(&openflow);
+ while (openflow.size) {
+ const struct ofp_action_header *action = openflow.data;
enum ofp_raw_action_type raw;
enum ofperr error;
uint64_t arg;
if (actions == NULL) {
VLOG_WARN_RL(&rl, "OpenFlow message actions length %u exceeds "
"remaining message length (%"PRIu32")",
- actions_len, ofpbuf_size(openflow));
+ actions_len, openflow->size);
return OFPERR_OFPBRC_BAD_LEN;
}
return error;
}
- error = ofpacts_verify(ofpbuf_data(ofpacts), ofpbuf_size(ofpacts),
+ error = ofpacts_verify(ofpacts->data, ofpacts->size,
allowed_ovsinsts);
if (error) {
ofpbuf_clear(ofpacts);
case OFPACT_DEC_TTL:
case OFPACT_ENQUEUE:
case OFPACT_EXIT:
+ case OFPACT_UNROLL_XLATE:
case OFPACT_FIN_TIMEOUT:
case OFPACT_GOTO_TABLE:
case OFPACT_GROUP:
case OFPACT_LEARN:
+ case OFPACT_CONJUNCTION:
case OFPACT_METER:
case OFPACT_MULTIPATH:
case OFPACT_NOTE:
case OFPACT_CONTROLLER:
case OFPACT_ENQUEUE:
case OFPACT_EXIT:
+ case OFPACT_UNROLL_XLATE:
case OFPACT_FIN_TIMEOUT:
case OFPACT_LEARN:
+ case OFPACT_CONJUNCTION:
case OFPACT_MULTIPATH:
case OFPACT_NOTE:
case OFPACT_OUTPUT_REG:
const struct ofpact *a;
target = NULL;
- OFPACT_FOR_EACH (a, ofpbuf_data(in), ofpbuf_size(in)) {
+ OFPACT_FOR_EACH (a, in->data, in->size) {
if (a->type == filter) {
target = a;
}
{
const struct ofpact *a;
- OFPACT_FOR_EACH (a, ofpbuf_data(in), ofpbuf_size(in)) {
+ OFPACT_FOR_EACH (a, in->data, in->size) {
if (filter(a)) {
ofpact_copy(out, a);
}
* "Action Set" and "Action List" terms used in OpenFlow 1.1+.)
*
* In general this involves appending the last instance of each action that is
- * adimissible in the action set in the order described in the OpenFlow
+ * admissible in the action set in the order described in the OpenFlow
* specification.
*
* Exceptions:
{
enum ofperr error;
struct ofpact *a;
- size_t start = ofpbuf_size(out);
+ size_t start = out->size;
error = ofpacts_decode(in, n_in, version, out);
return error;
}
- OFPACT_FOR_EACH (a, ofpact_end(ofpbuf_data(out), start), ofpbuf_size(out) - start) {
+ OFPACT_FOR_EACH (a, ofpact_end(out->data, start), out->size - start) {
if (!ofpact_is_allowed_in_actions_set(a)) {
VLOG_WARN_RL(&rl, "disallowed action in action set");
return OFPERR_OFPBAC_BAD_TYPE;
case OFPACT_FIN_TIMEOUT:
case OFPACT_RESUBMIT:
case OFPACT_LEARN:
+ case OFPACT_CONJUNCTION:
case OFPACT_MULTIPATH:
case OFPACT_NOTE:
case OFPACT_EXIT:
+ case OFPACT_UNROLL_XLATE:
case OFPACT_SAMPLE:
default:
return OVSINST_OFPIT11_APPLY_ACTIONS;
if (instructions == NULL) {
VLOG_WARN_RL(&rl, "OpenFlow message instructions length %u exceeds "
"remaining message length (%"PRIu32")",
- instructions_len, ofpbuf_size(openflow));
+ instructions_len, openflow->size);
error = OFPERR_OFPBIC_BAD_LEN;
goto exit;
}
size_t start;
ofpact_pad(ofpacts);
- start = ofpbuf_size(ofpacts);
- on = ofpact_put(ofpacts, OFPACT_WRITE_ACTIONS,
- offsetof(struct ofpact_nest, actions));
+ start = ofpacts->size;
+ ofpact_put(ofpacts, OFPACT_WRITE_ACTIONS,
+ offsetof(struct ofpact_nest, actions));
get_actions_from_instruction(insts[OVSINST_OFPIT11_WRITE_ACTIONS],
&actions, &actions_len);
error = ofpacts_decode_for_action_set(actions, actions_len,
goto exit;
}
on = ofpbuf_at_assert(ofpacts, start, sizeof *on);
- on->ofpact.len = ofpbuf_size(ofpacts) - start;
+ on->ofpact.len = ofpacts->size - start;
}
if (insts[OVSINST_OFPIT11_WRITE_METADATA]) {
const struct ofp11_instruction_write_metadata *oiwm;
ogt->table_id = oigt->table_id;
}
- error = ofpacts_verify(ofpbuf_data(ofpacts), ofpbuf_size(ofpacts),
+ error = ofpacts_verify(ofpacts->data, ofpacts->size,
(1u << N_OVS_INSTRUCTIONS) - 1);
exit:
if (error) {
struct ofp11_instruction_actions *oia;
oia = ofpbuf_at_assert(openflow, ofs, sizeof *oia);
- if (ofpbuf_size(openflow) > ofs + sizeof *oia) {
- oia->len = htons(ofpbuf_size(openflow) - ofs);
+ if (openflow->size > ofs + sizeof *oia) {
+ oia->len = htons(openflow->size - ofs);
} else {
- ofpbuf_set_size(openflow, ofs);
+ openflow->size = ofs;
}
}
\f
case OFPACT_LEARN:
return learn_check(ofpact_get_LEARN(a), flow);
+ case OFPACT_CONJUNCTION:
+ return 0;
+
case OFPACT_MULTIPATH:
return multipath_check(ofpact_get_MULTIPATH(a), flow);
case OFPACT_GROUP:
return 0;
+ case OFPACT_UNROLL_XLATE:
+ /* UNROLL is an internal action that should never be seen via
+ * OpenFlow. */
+ return OFPERR_OFPBAC_BAD_TYPE;
+
default:
OVS_NOT_REACHED();
}
: 0);
}
-/* Verifies that the 'ofpacts_len' bytes of actions in 'ofpacts' are
- * in the appropriate order as defined by the OpenFlow spec. */
+/* Verifies that the 'ofpacts_len' bytes of actions in 'ofpacts' are in the
+ * appropriate order as defined by the OpenFlow spec and as required by Open
+ * vSwitch.
+ *
+ * 'allowed_ovsinsts' is a bitmap of OVSINST_* values, in which 1-bits indicate
+ * instructions that are allowed within 'ofpacts[]'. */
static enum ofperr
ofpacts_verify(const struct ofpact ofpacts[], size_t ofpacts_len,
uint32_t allowed_ovsinsts)
OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
enum ovs_instruction_type next;
+ if (a->type == OFPACT_CONJUNCTION) {
+ OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
+ if (a->type != OFPACT_CONJUNCTION && a->type != OFPACT_NOTE) {
+ VLOG_WARN("\"conjunction\" actions may be used along with "
+ "\"note\" but not any other kind of action "
+ "(such as the \"%s\" action used here)",
+ ofpact_name(a->type));
+ return OFPERR_NXBAC_BAD_CONJUNCTION;
+ }
+ }
+ return 0;
+ }
+
next = ovs_instruction_type_from_ofpact_type(a->type);
if (a > ofpacts
&& (inst == OVSINST_OFPIT11_APPLY_ACTIONS
enum ofp_version ofp_version)
{
const struct ofpact *a;
- size_t start_size = ofpbuf_size(openflow);
+ size_t start_size = openflow->size;
OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
encode_ofpact(a, ofp_version, openflow);
}
- return ofpbuf_size(openflow) - start_size;
+ return openflow->size - start_size;
}
static enum ovs_instruction_type
a = ofpacts;
while (a < end) {
if (ofpact_is_apply_actions(a)) {
- size_t ofs = ofpbuf_size(openflow);
+ size_t ofs = openflow->size;
instruction_put_OFPIT11_APPLY_ACTIONS(openflow);
do {
case OFPACT_FIN_TIMEOUT:
case OFPACT_RESUBMIT:
case OFPACT_LEARN:
+ case OFPACT_CONJUNCTION:
case OFPACT_MULTIPATH:
case OFPACT_NOTE:
case OFPACT_EXIT:
+ case OFPACT_UNROLL_XLATE:
case OFPACT_PUSH_MPLS:
case OFPACT_POP_MPLS:
case OFPACT_SAMPLE:
struct ofpact *ofpact;
ofpact_pad(ofpacts);
- ofpact = ofpacts->frame = ofpbuf_put_uninit(ofpacts, len);
+ ofpacts->header = ofpbuf_put_uninit(ofpacts, len);
+ ofpact = ofpacts->header;
ofpact_init(ofpact, type, len);
return ofpact;
}
void
ofpact_update_len(struct ofpbuf *ofpacts, struct ofpact *ofpact)
{
- ovs_assert(ofpact == ofpacts->frame);
+ ovs_assert(ofpact == ofpacts->header);
ofpact->len = (char *) ofpbuf_tail(ofpacts) - (char *) ofpact;
}
void
ofpact_pad(struct ofpbuf *ofpacts)
{
- unsigned int pad = PAD_SIZE(ofpbuf_size(ofpacts), OFPACT_ALIGNTO);
+ unsigned int pad = PAD_SIZE(ofpacts->size, OFPACT_ALIGNTO);
if (pad) {
ofpbuf_put_zeros(ofpacts, pad);
}
}
ofpact_pad(ofpacts);
- if (drop && ofpbuf_size(ofpacts)) {
+ if (drop && ofpacts->size) {
return xstrdup("\"drop\" must not be accompanied by any other action "
"or instruction");
}
- retval = ofpacts_verify(ofpbuf_data(ofpacts), ofpbuf_size(ofpacts),
+ retval = ofpacts_verify(ofpacts->data, ofpacts->size,
(allow_instructions
? (1u << N_OVS_INSTRUCTIONS) - 1
: 1u << OVSINST_OFPIT11_APPLY_ACTIONS));
ofpacts_parse(char *str, struct ofpbuf *ofpacts,
enum ofputil_protocol *usable_protocols, bool allow_instructions)
{
- uint32_t orig_size = ofpbuf_size(ofpacts);
+ uint32_t orig_size = ofpacts->size;
char *error = ofpacts_parse__(str, ofpacts, usable_protocols,
allow_instructions);
if (error) {
- ofpbuf_set_size(ofpacts, orig_size);
+ ofpacts->size = orig_size;
}
return error;
}
ofpact_pull_raw(struct ofpbuf *buf, enum ofp_version ofp_version,
enum ofp_raw_action_type *raw, uint64_t *arg)
{
- const struct ofp_action_header *oah = ofpbuf_data(buf);
+ const struct ofp_action_header *oah = buf->data;
const struct ofpact_raw_instance *action;
unsigned int length;
enum ofperr error;
*raw = *arg = 0;
- error = ofpact_decode_raw(ofp_version, oah, ofpbuf_size(buf), &action);
+ error = ofpact_decode_raw(ofp_version, oah, buf->size, &action);
if (error) {
return error;
}
}
length = ntohs(oah->len);
- if (length > ofpbuf_size(buf)) {
+ if (length > buf->size) {
VLOG_WARN_RL(&rl, "OpenFlow action %s length %u exceeds action buffer "
- "length %"PRIu32, action->name, length, ofpbuf_size(buf));
+ "length %"PRIu32, action->name, length, buf->size);
return OFPERR_OFPBAC_BAD_LEN;
}
if (length < action->min_length || length > action->max_length) {
{
struct ofp_action_header *oah;
- ofpbuf_put_zeros(openflow, PAD_SIZE(ofpbuf_size(openflow) - start_ofs, 8));
+ ofpbuf_put_zeros(openflow, PAD_SIZE(openflow->size - start_ofs, 8));
oah = ofpbuf_at_assert(openflow, start_ofs, sizeof *oah);
- oah->len = htons(ofpbuf_size(openflow) - start_ofs);
+ oah->len = htons(openflow->size - start_ofs);
}