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;
}
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);
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_CONTROLLER:
case OFPACT_ENQUEUE:
case OFPACT_EXIT:
+ case OFPACT_UNROLL_XLATE:
case OFPACT_FIN_TIMEOUT:
case OFPACT_LEARN:
case OFPACT_CONJUNCTION:
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_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_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();
}
if (a->type == OFPACT_CONJUNCTION) {
OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
- if (a->type != OFPACT_CONJUNCTION) {
- VLOG_WARN("when %s action is present, it must be the only "
- "kind of action used", ofpact_name(a->type));
+ 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;
}
}
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_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);
}