#include <config.h>
#include "ofp-actions.h"
-#include "autopath.h"
#include "bundle.h"
#include "byte-order.h"
#include "compiler.h"
(const struct nx_action_reg_load *) a, out);
break;
+ case OFPUTIL_NXAST_STACK_PUSH:
+ error = nxm_stack_push_from_openflow(
+ (const struct nx_action_stack *) a, out);
+ break;
+
+ case OFPUTIL_NXAST_STACK_POP:
+ error = nxm_stack_pop_from_openflow(
+ (const struct nx_action_stack *) a, out);
+ break;
+
case OFPUTIL_NXAST_NOTE:
nan = (const struct nx_action_note *) a;
note_from_openflow(nan, out);
ofpact_put_MULTIPATH(out));
break;
- case OFPUTIL_NXAST_AUTOPATH__DEPRECATED:
- error = autopath_from_openflow((const struct nx_action_autopath *) a,
- ofpact_put_AUTOPATH(out));
- break;
-
case OFPUTIL_NXAST_BUNDLE:
case OFPUTIL_NXAST_BUNDLE_LOAD:
error = bundle_from_openflow((const struct nx_action_bundle *) a, out);
case OFPUTIL_NXAST_CONTROLLER:
controller_from_openflow((const struct nx_action_controller *) a, out);
break;
+
+ case OFPUTIL_NXAST_PUSH_MPLS: {
+ struct nx_action_push_mpls *nxapm = (struct nx_action_push_mpls *)a;
+ if (!eth_type_mpls(nxapm->ethertype)) {
+ return OFPERR_OFPBAC_BAD_ARGUMENT;
+ }
+ ofpact_put_PUSH_MPLS(out)->ethertype = nxapm->ethertype;
+ break;
+ }
+
+ case OFPUTIL_NXAST_SET_MPLS_TTL: {
+ struct nx_action_mpls_ttl *nxamt = (struct nx_action_mpls_ttl *)a;
+ ofpact_put_SET_MPLS_TTL(out)->ttl = nxamt->ttl;
+ break;
+ }
+
+ case OFPUTIL_NXAST_DEC_MPLS_TTL:
+ ofpact_put_DEC_MPLS_TTL(out);
+ break;
+
+ case OFPUTIL_NXAST_POP_MPLS: {
+ struct nx_action_pop_mpls *nxapm = (struct nx_action_pop_mpls *)a;
+ if (eth_type_mpls(nxapm->ethertype)) {
+ return OFPERR_OFPBAC_BAD_ARGUMENT;
+ }
+ ofpact_put_POP_MPLS(out)->ethertype = nxapm->ethertype;
+ break;
+ }
}
return error;
return nxm_reg_load_from_openflow12_set_field(
(const struct ofp12_action_set_field *)a, out);
+ case OFPUTIL_OFPAT11_SET_MPLS_TTL: {
+ struct ofp11_action_mpls_ttl *oamt = (struct ofp11_action_mpls_ttl *)a;
+ ofpact_put_SET_MPLS_TTL(out)->ttl = oamt->mpls_ttl;
+ break;
+ }
+
+ case OFPUTIL_OFPAT11_DEC_MPLS_TTL:
+ ofpact_put_DEC_MPLS_TTL(out);
+ break;
+
+ case OFPUTIL_OFPAT11_PUSH_MPLS: {
+ struct ofp11_action_push *oap = (struct ofp11_action_push *)a;
+ if (!eth_type_mpls(oap->ethertype)) {
+ return OFPERR_OFPBAC_BAD_ARGUMENT;
+ }
+ ofpact_put_PUSH_MPLS(out)->ethertype = oap->ethertype;
+ break;
+ }
+
+ case OFPUTIL_OFPAT11_POP_MPLS: {
+ struct ofp11_action_pop_mpls *oapm = (struct ofp11_action_pop_mpls *)a;
+ if (eth_type_mpls(oapm->ethertype)) {
+ return OFPERR_OFPBAC_BAD_ARGUMENT;
+ }
+ ofpact_put_POP_MPLS(out)->ethertype = oapm->ethertype;
+ break;
+ }
+
#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) case OFPUTIL_##ENUM:
#include "ofp-util.def"
return ofpact_from_nxast(a, code, out);
}
\f
static enum ofperr
-ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports)
+ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports,
+ ovs_be16 *dl_type)
{
const struct ofpact_enqueue *enqueue;
return nxm_reg_move_check(ofpact_get_REG_MOVE(a), flow);
case OFPACT_REG_LOAD:
- return nxm_reg_load_check(ofpact_get_REG_LOAD(a), flow);
+ if (*dl_type != flow->dl_type) {
+ struct flow updated_flow = *flow;
+ updated_flow.dl_type = *dl_type;
+ return nxm_reg_load_check(ofpact_get_REG_LOAD(a), &updated_flow);
+ } else {
+ return nxm_reg_load_check(ofpact_get_REG_LOAD(a), flow);
+ }
+
+ case OFPACT_STACK_PUSH:
+ return nxm_stack_push_check(ofpact_get_STACK_PUSH(a), flow);
+
+ case OFPACT_STACK_POP:
+ return nxm_stack_pop_check(ofpact_get_STACK_POP(a), flow);
case OFPACT_DEC_TTL:
+ case OFPACT_SET_MPLS_TTL:
+ case OFPACT_DEC_MPLS_TTL:
case OFPACT_SET_TUNNEL:
case OFPACT_SET_QUEUE:
case OFPACT_POP_QUEUE:
case OFPACT_MULTIPATH:
return multipath_check(ofpact_get_MULTIPATH(a), flow);
- case OFPACT_AUTOPATH:
- return autopath_check(ofpact_get_AUTOPATH(a), flow);
-
case OFPACT_NOTE:
case OFPACT_EXIT:
return 0;
+ case OFPACT_PUSH_MPLS:
+ *dl_type = ofpact_get_PUSH_MPLS(a)->ethertype;
+ return 0;
+
+ case OFPACT_POP_MPLS:
+ *dl_type = ofpact_get_POP_MPLS(a)->ethertype;
+ return 0;
+
case OFPACT_CLEAR_ACTIONS:
case OFPACT_WRITE_METADATA:
case OFPACT_GOTO_TABLE:
const struct flow *flow, int max_ports)
{
const struct ofpact *a;
+ ovs_be16 dl_type = flow->dl_type;
OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
- enum ofperr error = ofpact_check__(a, flow, max_ports);
+ enum ofperr error = ofpact_check__(a, flow, max_ports, &dl_type);
if (error) {
return error;
}
nxm_reg_load_to_nxast(ofpact_get_REG_LOAD(a), out);
break;
+ case OFPACT_STACK_PUSH:
+ nxm_stack_push_to_nxast(ofpact_get_STACK_PUSH(a), out);
+ break;
+
+ case OFPACT_STACK_POP:
+ nxm_stack_pop_to_nxast(ofpact_get_STACK_POP(a), out);
+ break;
+
case OFPACT_DEC_TTL:
ofpact_dec_ttl_to_nxast(ofpact_get_DEC_TTL(a), out);
break;
+ case OFPACT_SET_MPLS_TTL:
+ ofputil_put_NXAST_SET_MPLS_TTL(out)->ttl
+ = ofpact_get_SET_MPLS_TTL(a)->ttl;
+ break;
+
+ case OFPACT_DEC_MPLS_TTL:
+ ofputil_put_NXAST_DEC_MPLS_TTL(out);
+ break;
+
case OFPACT_SET_TUNNEL:
ofpact_set_tunnel_to_nxast(ofpact_get_SET_TUNNEL(a), out);
break;
multipath_to_nxast(ofpact_get_MULTIPATH(a), out);
break;
- case OFPACT_AUTOPATH:
- autopath_to_nxast(ofpact_get_AUTOPATH(a), out);
- break;
-
case OFPACT_NOTE:
ofpact_note_to_nxast(ofpact_get_NOTE(a), out);
break;
ofputil_put_NXAST_EXIT(out);
break;
+ case OFPACT_PUSH_MPLS:
+ ofputil_put_NXAST_PUSH_MPLS(out)->ethertype =
+ ofpact_get_PUSH_MPLS(a)->ethertype;
+ break;
+
+ case OFPACT_POP_MPLS:
+ ofputil_put_NXAST_POP_MPLS(out)->ethertype =
+ ofpact_get_POP_MPLS(a)->ethertype;
+ break;
+
case OFPACT_OUTPUT:
case OFPACT_ENQUEUE:
case OFPACT_SET_VLAN_VID:
case OFPACT_BUNDLE:
case OFPACT_REG_MOVE:
case OFPACT_REG_LOAD:
+ case OFPACT_STACK_PUSH:
+ case OFPACT_STACK_POP:
case OFPACT_DEC_TTL:
+ case OFPACT_SET_MPLS_TTL:
+ case OFPACT_DEC_MPLS_TTL:
case OFPACT_SET_TUNNEL:
case OFPACT_WRITE_METADATA:
case OFPACT_SET_QUEUE:
case OFPACT_RESUBMIT:
case OFPACT_LEARN:
case OFPACT_MULTIPATH:
- case OFPACT_AUTOPATH:
case OFPACT_NOTE:
case OFPACT_EXIT:
+ case OFPACT_PUSH_MPLS:
+ case OFPACT_POP_MPLS:
ofpact_to_nxast(a, out);
break;
}
ofpact_dec_ttl_to_openflow11(ofpact_get_DEC_TTL(a), out);
break;
+ case OFPACT_SET_MPLS_TTL:
+ ofputil_put_OFPAT11_SET_MPLS_TTL(out)->mpls_ttl
+ = ofpact_get_SET_MPLS_TTL(a)->ttl;
+ break;
+
+ case OFPACT_DEC_MPLS_TTL:
+ ofputil_put_OFPAT11_DEC_MPLS_TTL(out);
+ break;
+
case OFPACT_WRITE_METADATA:
/* OpenFlow 1.1 uses OFPIT_WRITE_METADATA to express this action. */
break;
+ case OFPACT_PUSH_MPLS:
+ ofputil_put_OFPAT11_PUSH_MPLS(out)->ethertype =
+ ofpact_get_PUSH_MPLS(a)->ethertype;
+ break;
+
+ case OFPACT_POP_MPLS:
+ ofputil_put_OFPAT11_POP_MPLS(out)->ethertype =
+ ofpact_get_POP_MPLS(a)->ethertype;
+
+ break;
+
case OFPACT_CLEAR_ACTIONS:
case OFPACT_GOTO_TABLE:
NOT_REACHED();
case OFPACT_BUNDLE:
case OFPACT_REG_MOVE:
case OFPACT_REG_LOAD:
+ case OFPACT_STACK_PUSH:
+ case OFPACT_STACK_POP:
case OFPACT_SET_TUNNEL:
case OFPACT_POP_QUEUE:
case OFPACT_FIN_TIMEOUT:
case OFPACT_RESUBMIT:
case OFPACT_LEARN:
case OFPACT_MULTIPATH:
- case OFPACT_AUTOPATH:
case OFPACT_NOTE:
case OFPACT_EXIT:
ofpact_to_nxast(a, out);
case OFPACT_SET_L4_DST_PORT:
case OFPACT_REG_MOVE:
case OFPACT_REG_LOAD:
+ case OFPACT_STACK_PUSH:
+ case OFPACT_STACK_POP:
case OFPACT_DEC_TTL:
+ case OFPACT_SET_MPLS_TTL:
+ case OFPACT_DEC_MPLS_TTL:
case OFPACT_SET_TUNNEL:
case OFPACT_WRITE_METADATA:
case OFPACT_SET_QUEUE:
case OFPACT_RESUBMIT:
case OFPACT_LEARN:
case OFPACT_MULTIPATH:
- case OFPACT_AUTOPATH:
case OFPACT_NOTE:
case OFPACT_EXIT:
+ case OFPACT_PUSH_MPLS:
+ case OFPACT_POP_MPLS:
case OFPACT_CLEAR_ACTIONS:
case OFPACT_GOTO_TABLE:
default:
{
const struct ofpact_enqueue *enqueue;
const struct ofpact_resubmit *resubmit;
- const struct ofpact_autopath *autopath;
const struct ofpact_controller *controller;
const struct ofpact_metadata *metadata;
const struct ofpact_tunnel *tunnel;
nxm_format_reg_load(ofpact_get_REG_LOAD(a), s);
break;
+ case OFPACT_STACK_PUSH:
+ nxm_format_stack_push(ofpact_get_STACK_PUSH(a), s);
+ break;
+
+ case OFPACT_STACK_POP:
+ nxm_format_stack_pop(ofpact_get_STACK_POP(a), s);
+ break;
+
case OFPACT_DEC_TTL:
print_dec_ttl(ofpact_get_DEC_TTL(a), s);
break;
+ case OFPACT_SET_MPLS_TTL:
+ ds_put_format(s, "set_mpls_ttl(%"PRIu8")",
+ ofpact_get_SET_MPLS_TTL(a)->ttl);
+ break;
+
+ case OFPACT_DEC_MPLS_TTL:
+ ds_put_cstr(s, "dec_mpls_ttl");
+ break;
+
case OFPACT_SET_TUNNEL:
tunnel = ofpact_get_SET_TUNNEL(a);
ds_put_format(s, "set_tunnel%s:%#"PRIx64,
multipath_format(ofpact_get_MULTIPATH(a), s);
break;
- case OFPACT_AUTOPATH:
- autopath = ofpact_get_AUTOPATH(a);
- ds_put_cstr(s, "autopath(");
- ofputil_format_port(autopath->port, s);
- ds_put_char(s, ',');
- mf_format_subfield(&autopath->dst, s);
- ds_put_char(s, ')');
- break;
-
case OFPACT_NOTE:
print_note(ofpact_get_NOTE(a), s);
break;
+ case OFPACT_PUSH_MPLS:
+ ds_put_format(s, "push_mpls:0x%04"PRIx16,
+ ntohs(ofpact_get_PUSH_MPLS(a)->ethertype));
+ break;
+
+ case OFPACT_POP_MPLS:
+ ds_put_format(s, "pop_mpls:0x%04"PRIx16,
+ ntohs(ofpact_get_POP_MPLS(a)->ethertype));
+ break;
+
case OFPACT_EXIT:
ds_put_cstr(s, "exit");
break;