/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
struct ofp11_action_push push;
struct ofp11_action_pop_mpls ofp11_pop_mpls;
struct ofp11_action_set_queue ofp11_set_queue;
+ struct ofp11_action_mpls_label ofp11_mpls_label;
+ struct ofp11_action_mpls_tc ofp11_mpls_tc;
struct ofp11_action_mpls_ttl ofp11_mpls_ttl;
struct ofp11_action_group group;
struct ofp12_action_set_field set_field;
struct nx_action_pop_mpls pop_mpls;
struct nx_action_sample sample;
struct nx_action_learn learn;
+ struct nx_action_mpls_label mpls_label;
+ struct nx_action_mpls_tc mpls_tc;
};
static enum ofperr
ids->ofpact.compat = compat;
ids->n_controllers = 1;
ofpbuf_put(out, &id, sizeof id);
- ids = out->l2;
+ ids = out->frame;
ofpact_update_len(out, &ids->ofpact);
return error;
}
}
if (ids_size < ids->n_controllers * sizeof(ovs_be16)) {
- VLOG_WARN_RL(&rl, "Nicira action dec_ttl_cnt_ids only has %zu bytes "
- "allocated for controller ids. %zu bytes are required for "
+ VLOG_WARN_RL(&rl, "Nicira action dec_ttl_cnt_ids only has %"PRIuSIZE" bytes "
+ "allocated for controller ids. %"PRIuSIZE" bytes are required for "
"%"PRIu16" controllers.", ids_size,
ids->n_controllers * sizeof(ovs_be16), ids->n_controllers);
return OFPERR_OFPBAC_BAD_LEN;
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->l2;
+ ids = out->frame;
}
ofpact_update_len(out, &ids->ofpact);
}
static enum ofperr
-push_mpls_from_openflow(ovs_be16 ethertype, enum ofpact_mpls_position position,
- struct ofpbuf *out)
+push_mpls_from_openflow(ovs_be16 ethertype, struct ofpbuf *out)
{
struct ofpact_push_mpls *oam;
}
oam = ofpact_put_PUSH_MPLS(out);
oam->ethertype = ethertype;
- oam->position = position;
return 0;
}
} else { \
return OFPERR_OFPBAC_BAD_LEN; \
} \
- NOT_REACHED();
+ OVS_NOT_REACHED();
#include "ofp-util.def"
case CONSTANT_HTONS(NXAST_SNAT__OBSOLETE):
case OFPUTIL_ACTION_INVALID:
#define OFPAT10_ACTION(ENUM, STRUCT, NAME) case OFPUTIL_##ENUM:
#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) case OFPUTIL_##ENUM:
+#define OFPAT13_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) case OFPUTIL_##ENUM:
#include "ofp-util.def"
- NOT_REACHED();
+ OVS_NOT_REACHED();
case OFPUTIL_NXAST_RESUBMIT:
resubmit_from_openflow(&a->resubmit, out);
break;
case OFPUTIL_NXAST_PUSH_MPLS:
- error = push_mpls_from_openflow(a->push_mpls.ethertype,
- OFPACT_MPLS_AFTER_VLAN, out);
+ error = push_mpls_from_openflow(a->push_mpls.ethertype, out);
+ break;
+
+ case OFPUTIL_NXAST_SET_MPLS_LABEL:
+ ofpact_put_SET_MPLS_LABEL(out)->label = a->mpls_label.label;
+ break;
+
+ case OFPUTIL_NXAST_SET_MPLS_TC:
+ ofpact_put_SET_MPLS_TC(out)->tc = a->mpls_tc.tc;
break;
case OFPUTIL_NXAST_SET_MPLS_TTL:
switch (code) {
case OFPUTIL_ACTION_INVALID:
#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) case OFPUTIL_##ENUM:
+#define OFPAT13_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) case OFPUTIL_##ENUM:
#include "ofp-util.def"
- NOT_REACHED();
+ OVS_NOT_REACHED();
case OFPUTIL_OFPAT10_OUTPUT:
return output_from_openflow10(&a->output10, out);
ds_init(&s);
ds_put_hex_dump(&s, actions, max_actions * OFP_ACTION_ALIGN, 0, false);
- VLOG_WARN("bad action at offset %#tx (%s):\n%s",
+ VLOG_WARN("bad action at offset %#"PRIxPTR" (%s):\n%s",
(char *)bad_action - (char *)actions,
ofperr_get_name(error), ds_cstr(&s));
ds_destroy(&s);
unsigned int actions_len,
enum ofp_version version,
struct ofpbuf *ofpacts) {
- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
const union ofp_action *actions;
enum ofperr error;
actions = ofpbuf_try_pull(openflow, actions_len);
if (actions == NULL) {
VLOG_WARN_RL(&rl, "OpenFlow message actions length %u exceeds "
- "remaining message length (%zu)",
- actions_len, openflow->size);
+ "remaining message length (%"PRIu32")",
+ actions_len, ofpbuf_size(openflow));
return OFPERR_OFPBRC_BAD_LEN;
}
return error;
}
- error = ofpacts_verify(ofpacts->data, ofpacts->size);
+ error = ofpacts_verify(ofpbuf_data(ofpacts), ofpbuf_size(ofpacts));
if (error) {
ofpbuf_clear(ofpacts);
}
} else { \
return OFPERR_OFPBAC_BAD_LEN; \
} \
- NOT_REACHED();
+ OVS_NOT_REACHED();
#include "ofp-util.def"
default:
sf->value.mac, ETH_ADDR_LEN);
break;
+ case MFF_MPLS_LABEL:
+ ofputil_put_OFPAT11_SET_MPLS_LABEL(openflow)->mpls_label =
+ sf->value.be32;
+ break;
+
+ case MFF_MPLS_TC:
+ ofputil_put_OFPAT11_SET_MPLS_TC(openflow)->mpls_tc = sf->value.u8;
+ break;
+
case MFF_IPV4_SRC:
ofputil_put_OFPAT11_SET_NW_SRC(openflow)->nw_addr = sf->value.be32;
break;
ofputil_put_OFPAT11_SET_TP_DST(openflow)->tp_port = sf->value.be16;
break;
- case MFF_MPLS_TC: /* XXX */
- case MFF_MPLS_LABEL: /* XXX */
default:
set_field_to_nxast(sf, openflow);
break;
set_field_to_openflow(const struct ofpact_set_field *sf,
struct ofpbuf *openflow)
{
- struct ofp_header *oh = (struct ofp_header *)openflow->l2;
+ struct ofp_header *oh = (struct ofp_header *)openflow->frame;
if (oh->version >= OFP12_VERSION) {
set_field_to_openflow12(sf, openflow);
} else if (oh->version == OFP10_VERSION) {
set_field_to_openflow10(sf, openflow);
} else {
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
}
switch (code) {
case OFPUTIL_ACTION_INVALID:
#define OFPAT10_ACTION(ENUM, STRUCT, NAME) case OFPUTIL_##ENUM:
+#define OFPAT13_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) case OFPUTIL_##ENUM:
#include "ofp-util.def"
- NOT_REACHED();
+ OVS_NOT_REACHED();
case OFPUTIL_OFPAT11_OUTPUT:
return output_from_openflow11(&a->ofp11_output, out);
case OFPUTIL_OFPAT12_SET_FIELD:
return set_field_from_openflow(&a->set_field, out);
+ case OFPUTIL_OFPAT11_SET_MPLS_LABEL:
+ ofpact_put_SET_MPLS_LABEL(out)->label = a->ofp11_mpls_label.mpls_label;
+ break;
+
+ case OFPUTIL_OFPAT11_SET_MPLS_TC:
+ ofpact_put_SET_MPLS_TC(out)->tc = a->ofp11_mpls_tc.mpls_tc;
+ break;
+
case OFPUTIL_OFPAT11_SET_MPLS_TTL:
ofpact_put_SET_MPLS_TTL(out)->ttl = a->ofp11_mpls_ttl.mpls_ttl;
break;
break;
case OFPUTIL_OFPAT11_PUSH_MPLS:
- /* OpenFlow 1.3 has different semantics. */
- error = push_mpls_from_openflow(a->push.ethertype,
- version >= OFP13_VERSION ?
- OFPACT_MPLS_BEFORE_VLAN :
- OFPACT_MPLS_AFTER_VLAN, out);
+ error = push_mpls_from_openflow(a->push.ethertype, out);
break;
case OFPUTIL_OFPAT11_POP_MPLS:
case OFPACT_SET_IPV4_SRC:
case OFPACT_SET_L4_DST_PORT:
case OFPACT_SET_L4_SRC_PORT:
+ case OFPACT_SET_MPLS_LABEL:
+ case OFPACT_SET_MPLS_TC:
case OFPACT_SET_MPLS_TTL:
case OFPACT_SET_QUEUE:
case OFPACT_SET_TUNNEL:
case OFPACT_WRITE_METADATA:
return false;
default:
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
}
case OFPACT_SET_IPV4_SRC:
case OFPACT_SET_L4_DST_PORT:
case OFPACT_SET_L4_SRC_PORT:
+ case OFPACT_SET_MPLS_LABEL:
+ case OFPACT_SET_MPLS_TC:
case OFPACT_SET_MPLS_TTL:
case OFPACT_SET_QUEUE:
case OFPACT_SET_TUNNEL:
case OFPACT_WRITE_METADATA:
return false;
default:
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
}
const struct ofpact *a;
target = NULL;
- OFPACT_FOR_EACH (a, in->data, in->size) {
+ OFPACT_FOR_EACH (a, ofpbuf_data(in), ofpbuf_size(in)) {
if (a->type == filter) {
target = a;
}
{
const struct ofpact *a;
- OFPACT_FOR_EACH (a, in->data, in->size) {
+ OFPACT_FOR_EACH (a, ofpbuf_data(in), ofpbuf_size(in)) {
if (filter(a)) {
ofpact_copy(out, a);
}
{
enum ofperr error;
struct ofpact *a;
- size_t start = out->size;
+ size_t start = ofpbuf_size(out);
error = ofpacts_from_openflow(in, n_in, version, out);
return error;
}
- OFPACT_FOR_EACH (a, ofpact_end(out->data, start), out->size - start) {
+ OFPACT_FOR_EACH (a, ofpact_end(ofpbuf_data(out), start), ofpbuf_size(out) - 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_STACK_PUSH:
case OFPACT_STACK_POP:
case OFPACT_DEC_TTL:
+ case OFPACT_SET_MPLS_LABEL:
+ case OFPACT_SET_MPLS_TC:
case OFPACT_SET_MPLS_TTL:
case OFPACT_DEC_MPLS_TTL:
case OFPACT_PUSH_MPLS:
}
}
+enum ofperr
+ovs_instruction_type_from_inst_type(enum ovs_instruction_type *instruction_type,
+ const uint16_t inst_type)
+{
+ switch (inst_type) {
+
+#define DEFINE_INST(ENUM, STRUCT, EXTENSIBLE, NAME) \
+ case ENUM: \
+ *instruction_type = OVSINST_##ENUM; \
+ return 0;
+OVS_INSTRUCTIONS
+#undef DEFINE_INST
+
+ default:
+ return OFPERR_OFPBIC_UNKNOWN_INST;
+ }
+}
+
static inline struct ofp11_instruction *
instruction_next(const struct ofp11_instruction *inst)
{
}
if (left) {
- VLOG_WARN_RL(&rl, "bad instruction format at offset %zu",
+ VLOG_WARN_RL(&rl, "bad instruction format at offset %"PRIuSIZE,
(n_insts - left) * sizeof *inst);
return OFPERR_OFPBIC_BAD_LEN;
}
enum ofp_version version,
struct ofpbuf *ofpacts)
{
- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
const struct ofp11_instruction *instructions;
const struct ofp11_instruction *insts[N_OVS_INSTRUCTIONS];
enum ofperr error;
instructions = ofpbuf_try_pull(openflow, instructions_len);
if (instructions == NULL) {
VLOG_WARN_RL(&rl, "OpenFlow message instructions length %u exceeds "
- "remaining message length (%zu)",
- instructions_len, openflow->size);
+ "remaining message length (%"PRIu32")",
+ instructions_len, ofpbuf_size(openflow));
error = OFPERR_OFPBIC_BAD_LEN;
goto exit;
}
size_t start;
ofpact_pad(ofpacts);
- start = ofpacts->size;
+ start = ofpbuf_size(ofpacts);
on = ofpact_put(ofpacts, OFPACT_WRITE_ACTIONS,
offsetof(struct ofpact_nest, actions));
get_actions_from_instruction(insts[OVSINST_OFPIT11_WRITE_ACTIONS],
goto exit;
}
on = ofpbuf_at_assert(ofpacts, start, sizeof *on);
- on->ofpact.len = ofpacts->size - start;
+ on->ofpact.len = ofpbuf_size(ofpacts) - start;
}
if (insts[OVSINST_OFPIT11_WRITE_METADATA]) {
const struct ofp11_instruction_write_metadata *oiwm;
ogt->table_id = oigt->table_id;
}
- error = ofpacts_verify(ofpacts->data, ofpacts->size);
+ error = ofpacts_verify(ofpbuf_data(ofpacts), ofpbuf_size(ofpacts));
exit:
if (error) {
ofpbuf_clear(ofpacts);
}
}
-/* May modify flow->dl_type and flow->vlan_tci, caller must restore them.
+/* Removes the protocols that require consistency between match and actions
+ * (that's everything but OpenFlow 1.0) from '*usable_protocols'.
+ *
+ * (An example of an inconsistency between match and actions is a flow that
+ * does not match on an MPLS Ethertype but has an action that pops an MPLS
+ * label.) */
+static void
+inconsistent_match(enum ofputil_protocol *usable_protocols)
+{
+ *usable_protocols &= OFPUTIL_P_OF10_ANY;
+}
+
+/* May modify flow->dl_type, flow->nw_proto and flow->vlan_tci,
+ * caller must restore them.
*
* Modifies some actions, filling in fields that could not be properly set
* without context. */
static enum ofperr
-ofpact_check__(struct ofpact *a, struct flow *flow,
- bool enforce_consistency, ofp_port_t max_ports,
+ofpact_check__(enum ofputil_protocol *usable_protocols, struct ofpact *a,
+ struct flow *flow, ofp_port_t max_ports,
uint8_t table_id, uint8_t n_tables)
{
const struct ofpact_enqueue *enqueue;
(flow->vlan_tci & htons(VLAN_CFI)) == htons(VLAN_CFI);
if (!(flow->vlan_tci & htons(VLAN_CFI)) &&
!ofpact_get_SET_VLAN_VID(a)->push_vlan_if_needed) {
- goto inconsistent;
+ inconsistent_match(usable_protocols);
}
/* Temporary mark that we have a vlan tag. */
flow->vlan_tci |= htons(VLAN_CFI);
(flow->vlan_tci & htons(VLAN_CFI)) == htons(VLAN_CFI);
if (!(flow->vlan_tci & htons(VLAN_CFI)) &&
!ofpact_get_SET_VLAN_PCP(a)->push_vlan_if_needed) {
- goto inconsistent;
+ inconsistent_match(usable_protocols);
}
/* Temporary mark that we have a vlan tag. */
flow->vlan_tci |= htons(VLAN_CFI);
case OFPACT_STRIP_VLAN:
if (!(flow->vlan_tci & htons(VLAN_CFI))) {
- goto inconsistent;
+ inconsistent_match(usable_protocols);
}
/* Temporary mark that we have no vlan tag. */
flow->vlan_tci = htons(0);
case OFPACT_SET_IPV4_SRC:
case OFPACT_SET_IPV4_DST:
if (flow->dl_type != htons(ETH_TYPE_IP)) {
- goto inconsistent;
+ inconsistent_match(usable_protocols);
}
return 0;
case OFPACT_SET_IP_TTL:
case OFPACT_DEC_TTL:
if (!is_ip_any(flow)) {
- goto inconsistent;
+ inconsistent_match(usable_protocols);
}
return 0;
if (!is_ip_any(flow) ||
(flow->nw_proto != IPPROTO_TCP && flow->nw_proto != IPPROTO_UDP
&& flow->nw_proto != IPPROTO_SCTP)) {
- goto inconsistent;
+ inconsistent_match(usable_protocols);
}
/* Note on which transport protocol the port numbers are set.
* This allows this set action to be converted to an OF1.2 set field
if (!is_ip_any(flow) ||
(flow->nw_proto != IPPROTO_TCP && flow->nw_proto != IPPROTO_UDP
&& flow->nw_proto != IPPROTO_SCTP)) {
- goto inconsistent;
+ inconsistent_match(usable_protocols);
}
/* Note on which transport protocol the port numbers are set.
* This allows this set action to be converted to an OF1.2 set field
case OFPACT_STACK_POP:
return nxm_stack_pop_check(ofpact_get_STACK_POP(a), flow);
+ case OFPACT_SET_MPLS_LABEL:
+ case OFPACT_SET_MPLS_TC:
case OFPACT_SET_MPLS_TTL:
case OFPACT_DEC_MPLS_TTL:
if (!eth_type_mpls(flow->dl_type)) {
- goto inconsistent;
+ inconsistent_match(usable_protocols);
}
return 0;
case OFPACT_FIN_TIMEOUT:
if (flow->nw_proto != IPPROTO_TCP) {
- goto inconsistent;
+ inconsistent_match(usable_protocols);
}
return 0;
case OFPACT_PUSH_MPLS:
flow->dl_type = ofpact_get_PUSH_MPLS(a)->ethertype;
+ /* The packet is now MPLS and the MPLS payload is opaque.
+ * Thus nothing can be assumed about the network protocol.
+ * Temporarily mark that we have no nw_proto. */
+ flow->nw_proto = 0;
return 0;
case OFPACT_POP_MPLS:
- flow->dl_type = ofpact_get_POP_MPLS(a)->ethertype;
if (!eth_type_mpls(flow->dl_type)) {
- goto inconsistent;
+ inconsistent_match(usable_protocols);
}
+ flow->dl_type = ofpact_get_POP_MPLS(a)->ethertype;
return 0;
case OFPACT_SAMPLE:
return 0;
case OFPACT_WRITE_ACTIONS: {
+ /* Use a temporary copy of 'usable_protocols' because we can't check
+ * consistency of an action set. */
struct ofpact_nest *on = ofpact_get_WRITE_ACTIONS(a);
+ enum ofputil_protocol p = *usable_protocols;
return ofpacts_check(on->actions, ofpact_nest_get_action_len(on),
- flow, false, max_ports, table_id, n_tables);
+ flow, max_ports, table_id, n_tables, &p);
}
case OFPACT_WRITE_METADATA:
return 0;
default:
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
-
- inconsistent:
- if (enforce_consistency) {
- return OFPERR_OFPBAC_MATCH_INCONSISTENT;
- }
- return 0;
}
/* Checks that the 'ofpacts_len' bytes of actions in 'ofpacts' are
* appropriate for a packet with the prerequisites satisfied by 'flow' in a
* switch with no more than 'max_ports' ports.
*
+ * If 'ofpacts' and 'flow' are inconsistent with one another, un-sets in
+ * '*usable_protocols' the protocols that forbid the inconsistency. (An
+ * example of an inconsistency between match and actions is a flow that does
+ * not match on an MPLS Ethertype but has an action that pops an MPLS label.)
+ *
* May annotate ofpacts with information gathered from the 'flow'.
*
* May temporarily modify 'flow', but restores the changes before returning. */
enum ofperr
ofpacts_check(struct ofpact ofpacts[], size_t ofpacts_len,
- struct flow *flow, bool enforce_consistency,
- ofp_port_t max_ports,
- uint8_t table_id, uint8_t n_tables)
+ struct flow *flow, ofp_port_t max_ports,
+ uint8_t table_id, uint8_t n_tables,
+ enum ofputil_protocol *usable_protocols)
{
struct ofpact *a;
ovs_be16 dl_type = flow->dl_type;
ovs_be16 vlan_tci = flow->vlan_tci;
+ uint8_t nw_proto = flow->nw_proto;
enum ofperr error = 0;
OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
- error = ofpact_check__(a, flow, enforce_consistency,
+ error = ofpact_check__(usable_protocols, a, flow,
max_ports, table_id, n_tables);
if (error) {
break;
/* Restore fields that may have been modified. */
flow->dl_type = dl_type;
flow->vlan_tci = vlan_tci;
+ flow->nw_proto = nw_proto;
return error;
}
+/* Like ofpacts_check(), but reports inconsistencies as
+ * OFPERR_OFPBAC_MATCH_INCONSISTENT rather than clearing bits. */
+enum ofperr
+ofpacts_check_consistency(struct ofpact ofpacts[], size_t ofpacts_len,
+ struct flow *flow, ofp_port_t max_ports,
+ uint8_t table_id, uint8_t n_tables,
+ enum ofputil_protocol usable_protocols)
+{
+ enum ofputil_protocol p = usable_protocols;
+ enum ofperr error;
+
+ error = ofpacts_check(ofpacts, ofpacts_len, flow, max_ports,
+ table_id, n_tables, &p);
+ return (error ? error
+ : p != usable_protocols ? OFPERR_OFPBAC_MATCH_INCONSISTENT
+ : 0);
+}
+
/* Verifies that the 'ofpacts_len' bytes of actions in 'ofpacts' are
* in the appropriate order as defined by the OpenFlow spec. */
enum ofperr
const struct ofpact *a;
enum ovs_instruction_type inst;
- inst = OVSINST_OFPIT11_APPLY_ACTIONS;
+ inst = OVSINST_OFPIT13_METER;
OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
enum ovs_instruction_type next;
next = ovs_instruction_type_from_ofpact_type(a->type);
- if (inst == OVSINST_OFPIT11_APPLY_ACTIONS
- ? next < inst
- : next <= inst) {
+ if (a > ofpacts
+ && (inst == OVSINST_OFPIT11_APPLY_ACTIONS
+ ? next < inst
+ : next <= inst)) {
const char *name = ovs_instruction_name_from_type(inst);
const char *next_name = ovs_instruction_name_from_type(next);
static void
ofpact_note_to_nxast(const struct ofpact_note *note, struct ofpbuf *out)
{
- size_t start_ofs = out->size;
+ size_t start_ofs = ofpbuf_size(out);
struct nx_action_note *nan;
unsigned int remainder;
unsigned int len;
nan = ofputil_put_NXAST_NOTE(out);
- out->size -= sizeof nan->note;
+ ofpbuf_set_size(out, ofpbuf_size(out) - sizeof nan->note);
ofpbuf_put(out, note->data, note->length);
- len = out->size - start_ofs;
+ len = ofpbuf_size(out) - 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(out->size - start_ofs);
+ nan->len = htons(ofpbuf_size(out) - start_ofs);
}
static void
ofpact_dec_ttl_to_nxast(ofpact_get_DEC_TTL(a), out);
break;
+ case OFPACT_SET_MPLS_LABEL:
+ ofputil_put_NXAST_SET_MPLS_LABEL(out)->label
+ = ofpact_get_SET_MPLS_LABEL(a)->label;
+ break;
+
+ case OFPACT_SET_MPLS_TC:
+ ofputil_put_NXAST_SET_MPLS_TC(out)->tc
+ = ofpact_get_SET_MPLS_TC(a)->tc;
+ break;
+
case OFPACT_SET_MPLS_TTL:
ofputil_put_NXAST_SET_MPLS_TTL(out)->ttl
= ofpact_get_SET_MPLS_TTL(a)->ttl;
case OFPACT_GOTO_TABLE:
case OFPACT_METER:
case OFPACT_SET_FIELD:
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
}
\f
* follow this action. */
break;
+ case OFPACT_SET_IP_ECN:
+ case OFPACT_SET_IP_TTL:
case OFPACT_CLEAR_ACTIONS:
case OFPACT_WRITE_ACTIONS:
case OFPACT_GOTO_TABLE:
case OFPACT_STACK_PUSH:
case OFPACT_STACK_POP:
case OFPACT_DEC_TTL:
- case OFPACT_SET_IP_ECN:
- case OFPACT_SET_IP_TTL:
+ case OFPACT_SET_MPLS_LABEL:
+ case OFPACT_SET_MPLS_TC:
case OFPACT_SET_MPLS_TTL:
case OFPACT_DEC_MPLS_TTL:
case OFPACT_SET_TUNNEL:
ofpact_dec_ttl_to_openflow11(ofpact_get_DEC_TTL(a), out);
break;
+ case OFPACT_SET_MPLS_LABEL:
+ ofputil_put_OFPAT11_SET_MPLS_LABEL(out)->mpls_label
+ = ofpact_get_SET_MPLS_LABEL(a)->label;
+ break;
+
+ case OFPACT_SET_MPLS_TC:
+ ofputil_put_OFPAT11_SET_MPLS_TC(out)->mpls_tc
+ = ofpact_get_SET_MPLS_TC(a)->tc;
+ break;
+
case OFPACT_SET_MPLS_TTL:
ofputil_put_OFPAT11_SET_MPLS_TTL(out)->mpls_ttl
= ofpact_get_SET_MPLS_TTL(a)->ttl;
case OFPACT_WRITE_ACTIONS:
case OFPACT_GOTO_TABLE:
case OFPACT_METER:
- NOT_REACHED();
+ OVS_NOT_REACHED();
case OFPACT_GROUP:
ofputil_put_OFPAT11_GROUP(out)->group_id =
case OFPACT_SET_IP_ECN:
case OFPACT_SET_L4_SRC_PORT:
case OFPACT_SET_L4_DST_PORT:
+ case OFPACT_SET_MPLS_LABEL:
+ case OFPACT_SET_MPLS_TC:
case OFPACT_SET_TUNNEL: /* Convert to a set_field, too. */
switch ((int)a->type) {
value.be16 = htons(l4port->port);
break;
+ case OFPACT_SET_MPLS_LABEL:
+ field = MFF_MPLS_LABEL;
+ value.be32 = ofpact_get_SET_MPLS_LABEL(a)->label;
+ break;
+
+ case OFPACT_SET_MPLS_TC:
+ field = MFF_MPLS_TC;
+ value.u8 = ofpact_get_SET_MPLS_TC(a)->tc;
+ break;
+
case OFPACT_SET_TUNNEL:
field = MFF_TUN_ID;
value.be64 = htonll(ofpact_get_SET_TUNNEL(a)->tun_id);
enum ofp_version ofp_version)
{
const struct ofpact *a;
- size_t start_size = openflow->size;
+ size_t start_size = ofpbuf_size(openflow);
void (*translate)(const struct ofpact *a, struct ofpbuf *out) =
(ofp_version == OFP10_VERSION) ? ofpact_to_openflow10 :
OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
translate(a, openflow);
}
- return openflow->size - start_size;
+ return ofpbuf_size(openflow) - start_size;
}
static void
/* Update the instruction's length (or, if it's empty, delete it). */
oia = ofpbuf_at_assert(openflow, ofs, sizeof *oia);
- if (openflow->size > ofs + sizeof *oia) {
- oia->len = htons(openflow->size - ofs);
+ if (ofpbuf_size(openflow) > ofs + sizeof *oia) {
+ oia->len = htons(ofpbuf_size(openflow) - ofs);
} else {
- openflow->size = ofs;
+ ofpbuf_set_size(openflow, ofs);
}
}
break;
case OVSINST_OFPIT11_APPLY_ACTIONS: {
- const size_t ofs = openflow->size;
+ const size_t ofs = ofpbuf_size(openflow);
const size_t ofpacts_len_left =
(uint8_t*)ofpact_end(ofpacts, ofpacts_len) - (uint8_t*)a;
const struct ofpact *action;
}
case OVSINST_OFPIT11_WRITE_ACTIONS: {
- const size_t ofs = openflow->size;
+ const size_t ofs = ofpbuf_size(openflow);
const struct ofpact_nest *on;
on = ofpact_get_WRITE_ACTIONS(a);
case OFPACT_STACK_PUSH:
case OFPACT_STACK_POP:
case OFPACT_DEC_TTL:
+ case OFPACT_SET_MPLS_LABEL:
+ case OFPACT_SET_MPLS_TC:
case OFPACT_SET_MPLS_TTL:
case OFPACT_DEC_MPLS_TTL:
case OFPACT_SET_TUNNEL:
enqueue = ofpact_get_ENQUEUE(a);
ds_put_format(s, "enqueue:");
ofputil_format_port(enqueue->port, s);
- ds_put_format(s, "q%"PRIu32, enqueue->queue);
+ ds_put_format(s, ":%"PRIu32, enqueue->queue);
break;
case OFPACT_OUTPUT_REG:
print_dec_ttl(ofpact_get_DEC_TTL(a), s);
break;
+ case OFPACT_SET_MPLS_LABEL:
+ ds_put_format(s, "set_mpls_label(%"PRIu32")",
+ ntohl(ofpact_get_SET_MPLS_LABEL(a)->label));
+ break;
+
+ case OFPACT_SET_MPLS_TC:
+ ds_put_format(s, "set_mpls_ttl(%"PRIu8")",
+ ofpact_get_SET_MPLS_TC(a)->tc);
+ break;
+
case OFPACT_SET_MPLS_TTL:
ds_put_format(s, "set_mpls_ttl(%"PRIu8")",
ofpact_get_SET_MPLS_TTL(a)->ttl);
struct ofpact *ofpact;
ofpact_pad(ofpacts);
- ofpact = ofpacts->l2 = ofpbuf_put_uninit(ofpacts, len);
+ ofpact = ofpacts->frame = ofpbuf_put_uninit(ofpacts, len);
ofpact_init(ofpact, type, len);
return ofpact;
}
void
ofpact_update_len(struct ofpbuf *ofpacts, struct ofpact *ofpact)
{
- ovs_assert(ofpact == ofpacts->l2);
+ ovs_assert(ofpact == ofpacts->frame);
ofpact->len = (char *) ofpbuf_tail(ofpacts) - (char *) ofpact;
}
void
ofpact_pad(struct ofpbuf *ofpacts)
{
- unsigned int rem = ofpacts->size % OFPACT_ALIGNTO;
- if (rem) {
- ofpbuf_put_zeros(ofpacts, OFPACT_ALIGNTO - rem);
+ unsigned int pad = PAD_SIZE(ofpbuf_size(ofpacts), OFPACT_ALIGNTO);
+ if (pad) {
+ ofpbuf_put_zeros(ofpacts, pad);
}
}