X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fofp-actions.c;h=58d0098ee529ca988817562c6734ad3555502dd6;hb=bff7eeb648a03598c57ac9a8288132379640cb2c;hp=1bc8a9cd3eb8e414ef571aac6a300c3b80ff637c;hpb=6813ee7c06fbd2496fb73edd54a462a9053c6161;p=sliver-openvswitch.git diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index 1bc8a9cd3..58d0098ee 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -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); @@ -209,14 +209,33 @@ dec_ttl_cnt_ids_from_openflow(const struct nx_action_cnt_ids *nac_ids, 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->l2; ofpact_update_len(out, &ids->ofpact); return 0; } +static enum ofperr +sample_from_openflow(const struct nx_action_sample *nas, + struct ofpbuf *out) +{ + struct ofpact_sample *sample; + + sample = ofpact_put_SAMPLE(out); + sample->probability = ntohs(nas->probability); + sample->collector_set_id = ntohl(nas->collector_set_id); + sample->obs_domain_id = ntohl(nas->obs_domain_id); + sample->obs_point_id = ntohl(nas->obs_point_id); + + if (sample->probability == 0) { + return OFPERR_OFPBAC_BAD_ARGUMENT; + } + + return 0; +} + static enum ofperr decode_nxast_action(const union ofp_action *a, enum ofputil_action_code *code) { @@ -339,6 +358,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 +385,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 +425,39 @@ 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; + } + + case OFPUTIL_NXAST_SAMPLE: + error = sample_from_openflow( + (const struct nx_action_sample *) a, out); + break; } return error; @@ -773,6 +830,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 +879,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; \ } \ \ @@ -967,6 +1052,7 @@ ofpacts_pull_openflow11_actions(struct ofpbuf *openflow, enum ofperr ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow, unsigned int instructions_len, + uint8_t table_id, struct ofpbuf *ofpacts) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); @@ -1034,6 +1120,10 @@ ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow, oigt = instruction_get_OFPIT11_GOTO_TABLE( insts[OVSINST_OFPIT11_GOTO_TABLE]); + if (table_id >= oigt->table_id) { + error = OFPERR_OFPBRC_BAD_TABLE_ID; + goto exit; + } ogt = ofpact_put_GOTO_TABLE(ofpacts); ogt->table_id = oigt->table_id; } @@ -1052,7 +1142,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; @@ -1097,7 +1188,15 @@ ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports) case OFPACT_REG_LOAD: 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 +1210,21 @@ 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_SAMPLE: + return 0; + case OFPACT_CLEAR_ACTIONS: case OFPACT_WRITE_METADATA: case OFPACT_GOTO_TABLE: @@ -1136,9 +1243,24 @@ 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; + struct flow updated_flow; OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) { - enum ofperr error = ofpact_check__(a, flow, max_ports); + enum ofperr error; + + /* If the dl_type was changed by an action then its new value + * should be present in the flow passed to ofpact_check__(). */ + if (flow->dl_type != dl_type) { + /* Only copy flow at most once */ + if (flow != &updated_flow) { + updated_flow = *flow; + flow = &updated_flow; + } + updated_flow.dl_type = dl_type; + } + + error = ofpact_check__(a, flow, max_ports, &dl_type); if (error) { return error; } @@ -1311,6 +1433,19 @@ ofpact_fin_timeout_to_nxast(const struct ofpact_fin_timeout *fin_timeout, naft->fin_hard_timeout = htons(fin_timeout->fin_hard_timeout); } +static void +ofpact_sample_to_nxast(const struct ofpact_sample *os, + struct ofpbuf *out) +{ + struct nx_action_sample *nas; + + nas = ofputil_put_NXAST_SAMPLE(out); + nas->probability = htons(os->probability); + nas->collector_set_id = htonl(os->collector_set_id); + nas->obs_domain_id = htonl(os->obs_domain_id); + nas->obs_point_id = htonl(os->obs_point_id); +} + static void ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out) { @@ -1335,10 +1470,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; @@ -1372,10 +1524,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; @@ -1384,6 +1532,20 @@ 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_SAMPLE: + ofpact_sample_to_nxast(ofpact_get_SAMPLE(a), out); + break; + case OFPACT_OUTPUT: case OFPACT_ENQUEUE: case OFPACT_SET_VLAN_VID: @@ -1499,7 +1661,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: @@ -1508,9 +1674,11 @@ 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: + case OFPACT_SAMPLE: ofpact_to_nxast(a, out); break; } @@ -1631,10 +1799,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(); @@ -1644,15 +1832,17 @@ 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: + case OFPACT_SAMPLE: ofpact_to_nxast(a, out); break; } @@ -1764,7 +1954,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: @@ -1773,9 +1967,11 @@ 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_SAMPLE: case OFPACT_CLEAR_ACTIONS: case OFPACT_GOTO_TABLE: default: @@ -1864,10 +2060,10 @@ 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; + const struct ofpact_sample *sample; uint16_t port; switch (a->type) { @@ -1983,10 +2179,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, @@ -2034,23 +2247,33 @@ 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; + case OFPACT_SAMPLE: + sample = ofpact_get_SAMPLE(a); + ds_put_format( + s, "sample(probability=%"PRIu16",collector_set_id=%"PRIu32 + ",obs_domain_id=%"PRIu32",obs_point_id=%"PRIu32")", + sample->probability, sample->collector_set_id, + sample->obs_domain_id, sample->obs_point_id); + break; + case OFPACT_CLEAR_ACTIONS: ds_put_format(s, "%s", ofpact_instruction_name_from_type( @@ -2131,7 +2354,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; }