X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fofp-actions.c;h=d405d2d4e3dd20bcf16bf485a74c0977683c7b85;hb=d978fa4832bbc5176e05edd05bcdf2452a8dded2;hp=b758c7c92356f5eb527a8fb964b2b9fecd5931b1;hpb=15549878535c7331c3952e656a2eb9944d0021bb;p=sliver-openvswitch.git diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index b758c7c92..d405d2d4e 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc. + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ #include #include "ofp-actions.h" -#include "autopath.h" #include "bundle.h" #include "byte-order.h" #include "compiler.h" @@ -27,6 +26,7 @@ #include "nx-match.h" #include "ofp-util.h" #include "ofpbuf.h" +#include "util.h" #include "vlog.h" VLOG_DEFINE_THIS_MODULE(ofp_actions); @@ -339,6 +339,16 @@ ofpact_from_nxast(const union ofp_action *a, enum ofputil_action_code code, (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); @@ -356,11 +366,6 @@ ofpact_from_nxast(const union ofp_action *a, enum ofputil_action_code code, 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); @@ -401,6 +406,34 @@ ofpact_from_nxast(const union ofp_action *a, enum ofputil_action_code code, 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; @@ -717,7 +750,7 @@ ofpact_from_openflow11(const union ofp_action *a, struct ofpbuf *out) case OFPUTIL_OFPAT11_PUSH_VLAN: if (((const struct ofp11_action_push *)a)->ethertype != htons(ETH_TYPE_VLAN_8021Q)) { - /* TODO:XXX 802.1AD(QinQ) isn't supported at the moment */ + /* XXX 802.1AD(QinQ) isn't supported at the moment */ return OFPERR_OFPBAC_BAD_ARGUMENT; } ofpact_put_PUSH_VLAN(out); @@ -773,6 +806,34 @@ ofpact_from_openflow11(const union ofp_action *a, struct ofpbuf *out) 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); @@ -794,7 +855,7 @@ ofpacts_from_openflow11(const union ofp_action *in, size_t n_in, static inline const struct STRUCT * \ instruction_get_##ENUM(const struct ofp11_instruction *inst)\ { \ - assert(inst->type == htons(ENUM)); \ + ovs_assert(inst->type == htons(ENUM)); \ return (struct STRUCT *)inst; \ } \ \ @@ -1016,7 +1077,7 @@ ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow, insts[OVSINST_OFPIT11_CLEAR_ACTIONS]); ofpact_put_CLEAR_ACTIONS(ofpacts); } - /* TODO:XXX Write-Actions */ + /* XXX Write-Actions */ if (insts[OVSINST_OFPIT11_WRITE_METADATA]) { const struct ofp11_instruction_write_metadata *oiwm; struct ofpact_metadata *om; @@ -1052,7 +1113,8 @@ exit: } 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; @@ -1095,9 +1157,23 @@ ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports) 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: @@ -1111,13 +1187,18 @@ ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports) 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: @@ -1136,9 +1217,10 @@ ofpacts_check(const struct ofpact ofpacts[], size_t ofpacts_len, 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; } @@ -1153,23 +1235,38 @@ enum ofperr ofpacts_verify(const struct ofpact ofpacts[], size_t ofpacts_len) { const struct ofpact *a; - const struct ofpact_metadata *om = NULL; + enum ovs_instruction_type inst; + inst = OVSINST_OFPIT11_APPLY_ACTIONS; OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) { - if (om) { - if (a->type == OFPACT_WRITE_METADATA) { - VLOG_WARN("duplicate write_metadata instruction specified"); - return OFPERR_OFPBAC_UNSUPPORTED_ORDER; + enum ovs_instruction_type next; + + if (a->type == OFPACT_CLEAR_ACTIONS) { + next = OVSINST_OFPIT11_CLEAR_ACTIONS; + } else if (a->type == OFPACT_WRITE_METADATA) { + next = OVSINST_OFPIT11_WRITE_METADATA; + } else if (a->type == OFPACT_GOTO_TABLE) { + next = OVSINST_OFPIT11_GOTO_TABLE; + } else { + next = OVSINST_OFPIT11_APPLY_ACTIONS; + } + + if (inst != OVSINST_OFPIT11_APPLY_ACTIONS && next <= inst) { + const char *name = ofpact_instruction_name_from_type(inst); + const char *next_name = ofpact_instruction_name_from_type(next); + + if (next == inst) { + VLOG_WARN("duplicate %s instruction not allowed, for OpenFlow " + "1.1+ compatibility", name); } else { - VLOG_WARN("write_metadata instruction must be specified after " - "other instructions/actions"); - return OFPERR_OFPBAC_UNSUPPORTED_ORDER; + VLOG_WARN("invalid instruction ordering: %s must appear " + "before %s, for OpenFlow 1.1+ compatibility", + next_name, name); } + return OFPERR_OFPBAC_UNSUPPORTED_ORDER; } - if (a->type == OFPACT_WRITE_METADATA) { - om = (const struct ofpact_metadata *) a; - } + inst = next; } return 0; @@ -1320,10 +1417,27 @@ ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out) 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; @@ -1357,10 +1471,6 @@ ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out) 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; @@ -1369,6 +1479,16 @@ ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out) 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: @@ -1476,7 +1596,7 @@ ofpact_to_openflow10(const struct ofpact *a, struct ofpbuf *out) case OFPACT_PUSH_VLAN: case OFPACT_CLEAR_ACTIONS: case OFPACT_GOTO_TABLE: - /* TODO:XXX */ + /* XXX */ break; case OFPACT_CONTROLLER: @@ -1484,7 +1604,11 @@ ofpact_to_openflow10(const struct ofpact *a, struct ofpbuf *out) 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: @@ -1493,9 +1617,10 @@ ofpact_to_openflow10(const struct ofpact *a, struct ofpbuf *out) 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; } @@ -1567,7 +1692,7 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out) break; case OFPACT_PUSH_VLAN: - /* TODO:XXX ETH_TYPE_VLAN_8021AD case */ + /* XXX ETH_TYPE_VLAN_8021AD case */ ofputil_put_OFPAT11_PUSH_VLAN(out)->ethertype = htons(ETH_TYPE_VLAN_8021Q); break; @@ -1616,10 +1741,30 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out) 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(); @@ -1629,13 +1774,14 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out) 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); @@ -1682,7 +1828,7 @@ ofpacts_put_openflow11_instructions(const struct ofpact ofpacts[], const struct ofpact *a; OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) { - /* TODO:XXX Write-Actions */ + /* XXX Write-Actions */ if (a->type == OFPACT_CLEAR_ACTIONS) { instruction_put_OFPIT11_CLEAR_ACTIONS(openflow); @@ -1749,7 +1895,11 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, uint16_t port) 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: @@ -1758,9 +1908,10 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, uint16_t port) 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: @@ -1849,7 +2000,6 @@ ofpact_format(const struct ofpact *a, struct ds *s) { 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; @@ -1924,7 +2074,7 @@ ofpact_format(const struct ofpact *a, struct ds *s) break; case OFPACT_PUSH_VLAN: - /* TODO:XXX 802.1AD case*/ + /* XXX 802.1AD case*/ ds_put_format(s, "push_vlan:%#"PRIx16, ETH_TYPE_VLAN_8021Q); break; @@ -1940,12 +2090,12 @@ ofpact_format(const struct ofpact *a, struct ds *s) case OFPACT_SET_IPV4_SRC: ds_put_format(s, "mod_nw_src:"IP_FMT, - IP_ARGS(&ofpact_get_SET_IPV4_SRC(a)->ipv4)); + IP_ARGS(ofpact_get_SET_IPV4_SRC(a)->ipv4)); break; case OFPACT_SET_IPV4_DST: ds_put_format(s, "mod_nw_dst:"IP_FMT, - IP_ARGS(&ofpact_get_SET_IPV4_DST(a)->ipv4)); + IP_ARGS(ofpact_get_SET_IPV4_DST(a)->ipv4)); break; case OFPACT_SET_IPV4_DSCP: @@ -1968,10 +2118,27 @@ ofpact_format(const struct ofpact *a, struct ds *s) 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, @@ -2019,19 +2186,20 @@ ofpact_format(const struct ofpact *a, struct ds *s) 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; @@ -2079,7 +2247,7 @@ ofpacts_format(const struct ofpact *ofpacts, size_t ofpacts_len, ds_put_cstr(string, ","); } - /* TODO:XXX write-actions */ + /* XXX write-actions */ ofpact_format(a, string); } } @@ -2116,7 +2284,7 @@ ofpact_init(struct ofpact *ofpact, enum ofpact_type type, size_t len) void ofpact_update_len(struct ofpbuf *ofpacts, struct ofpact *ofpact) { - assert(ofpact == ofpacts->l2); + ovs_assert(ofpact == ofpacts->l2); ofpact->len = (char *) ofpbuf_tail(ofpacts) - (char *) ofpact; }