X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fofp-actions.c;h=4a72e29cd5341e829b2f9115129b3e322c1dc728;hb=61a7b1e6fee6c81b0d8551898d2b108de2b42536;hp=db603b6e5e06fe5ef59d1d43a68cddaedb044e28;hpb=c2d967a562aaa57b679c302a5041d5a941154143;p=openvswitch diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index db603b6e..4a72e29c 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks. + * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -282,7 +282,7 @@ ofpact_from_nxast(const union ofp_action *a, enum ofputil_action_code code, switch (code) { case OFPUTIL_ACTION_INVALID: #define OFPAT10_ACTION(ENUM, STRUCT, NAME) case OFPUTIL_##ENUM: -#define OFPAT11_ACTION(ENUM, STRUCT, NAME) case OFPUTIL_##ENUM: +#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) case OFPUTIL_##ENUM: #include "ofp-util.def" NOT_REACHED(); @@ -333,7 +333,7 @@ ofpact_from_nxast(const union ofp_action *a, enum ofputil_action_code code, ofpact_put_MULTIPATH(out)); break; - case OFPUTIL_NXAST_AUTOPATH: + case OFPUTIL_NXAST_AUTOPATH__DEPRECATED: error = autopath_from_openflow((const struct nx_action_autopath *) a, ofpact_put_AUTOPATH(out)); break; @@ -396,7 +396,7 @@ ofpact_from_openflow10(const union ofp_action *a, struct ofpbuf *out) switch (code) { case OFPUTIL_ACTION_INVALID: -#define OFPAT11_ACTION(ENUM, STRUCT, NAME) case OFPUTIL_##ENUM: +#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) case OFPUTIL_##ENUM: #include "ofp-util.def" NOT_REACHED(); @@ -607,19 +607,24 @@ static enum ofperr decode_openflow11_action(const union ofp_action *a, enum ofputil_action_code *code) { + uint16_t len; + switch (a->type) { case CONSTANT_HTONS(OFPAT11_EXPERIMENTER): return decode_nxast_action(a, code); -#define OFPAT11_ACTION(ENUM, STRUCT, NAME) \ - case CONSTANT_HTONS(ENUM): \ - if (a->header.len == htons(sizeof(struct STRUCT))) { \ - *code = OFPUTIL_##ENUM; \ - return 0; \ - } else { \ - return OFPERR_OFPBAC_BAD_LEN; \ - } \ - break; +#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \ + case CONSTANT_HTONS(ENUM): \ + len = ntohs(a->header.len); \ + if (EXTENSIBLE \ + ? len >= sizeof(struct STRUCT) \ + : len == sizeof(struct STRUCT)) { \ + *code = OFPUTIL_##ENUM; \ + return 0; \ + } else { \ + return OFPERR_OFPBAC_BAD_LEN; \ + } \ + NOT_REACHED(); #include "ofp-util.def" default: @@ -713,6 +718,10 @@ ofpact_from_openflow11(const union ofp_action *a, struct ofpbuf *out) ofpact_put_SET_L4_DST_PORT(out)->port = ntohs(a->tp_port.tp_port); break; + case OFPUTIL_OFPAT12_SET_FIELD: + return nxm_reg_load_from_openflow12_set_field( + (const struct ofp12_action_set_field *)a, out); + #define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) case OFPUTIL_##ENUM: #include "ofp-util.def" return ofpact_from_nxast(a, code, out); @@ -770,13 +779,7 @@ OVS_INSTRUCTIONS const char * ofpact_instruction_name_from_type(enum ovs_instruction_type type) { - const struct instruction_type_info *p; - for (p = inst_info; p < &inst_info[ARRAY_SIZE(inst_info)]; p++) { - if (p->type == type) { - return p->name; - } - } - return NULL; + return inst_info[type].name; } int @@ -863,7 +866,7 @@ decode_openflow11_instructions(const struct ofp11_instruction insts[], } if (out[type]) { - return OFPERR_NXBIC_DUP_TYPE; + return OFPERR_OFPIT_BAD_INSTRUCTION; } out[type] = inst; } @@ -955,11 +958,25 @@ ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow, goto exit; } } + if (insts[OVSINST_OFPIT11_CLEAR_ACTIONS]) { + instruction_get_OFPIT11_CLEAR_ACTIONS( + insts[OVSINST_OFPIT11_CLEAR_ACTIONS]); + ofpact_put_CLEAR_ACTIONS(ofpacts); + } + /* TODO:XXX Write-Actions */ + /* TODO:XXX Write-Metadata */ + if (insts[OVSINST_OFPIT11_GOTO_TABLE]) { + const struct ofp11_instruction_goto_table *oigt; + struct ofpact_goto_table *ogt; + + oigt = instruction_get_OFPIT11_GOTO_TABLE( + insts[OVSINST_OFPIT11_GOTO_TABLE]); + ogt = ofpact_put_GOTO_TABLE(ofpacts); + ogt->table_id = oigt->table_id; + } - if (insts[OVSINST_OFPIT11_GOTO_TABLE] || - insts[OVSINST_OFPIT11_WRITE_METADATA] || - insts[OVSINST_OFPIT11_WRITE_ACTIONS] || - insts[OVSINST_OFPIT11_CLEAR_ACTIONS]) { + if (insts[OVSINST_OFPIT11_WRITE_METADATA] || + insts[OVSINST_OFPIT11_WRITE_ACTIONS]) { error = OFPERR_OFPBIC_UNSUP_INST; goto exit; } @@ -1037,6 +1054,10 @@ ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports) case OFPACT_EXIT: return 0; + case OFPACT_CLEAR_ACTIONS: + case OFPACT_GOTO_TABLE: + return 0; + default: NOT_REACHED(); } @@ -1252,6 +1273,8 @@ ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out) case OFPACT_SET_IPV4_DSCP: case OFPACT_SET_L4_SRC_PORT: case OFPACT_SET_L4_DST_PORT: + case OFPACT_CLEAR_ACTIONS: + case OFPACT_GOTO_TABLE: NOT_REACHED(); } } @@ -1341,6 +1364,11 @@ ofpact_to_openflow10(const struct ofpact *a, struct ofpbuf *out) = htons(ofpact_get_SET_L4_DST_PORT(a)->port); break; + case OFPACT_CLEAR_ACTIONS: + case OFPACT_GOTO_TABLE: + /* TODO:XXX */ + break; + case OFPACT_CONTROLLER: case OFPACT_OUTPUT_REG: case OFPACT_BUNDLE: @@ -1449,6 +1477,10 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out) = htons(ofpact_get_SET_L4_DST_PORT(a)->port); break; + case OFPACT_CLEAR_ACTIONS: + case OFPACT_GOTO_TABLE: + NOT_REACHED(); + case OFPACT_CONTROLLER: case OFPACT_OUTPUT_REG: case OFPACT_BUNDLE: @@ -1487,18 +1519,10 @@ ofpacts_put_openflow11_actions(const struct ofpact ofpacts[], return openflow->size - start_size; } -void -ofpacts_put_openflow11_instructions(const struct ofpact ofpacts[], - size_t ofpacts_len, - struct ofpbuf *openflow) +static void +ofpacts_update_instruction_actions(struct ofpbuf *openflow, size_t ofs) { struct ofp11_instruction_actions *oia; - size_t ofs; - - /* Put an OFPIT11_APPLY_ACTIONS instruction and fill it in. */ - ofs = openflow->size; - instruction_put_OFPIT11_APPLY_ACTIONS(openflow); - ofpacts_put_openflow11_actions(ofpacts, ofpacts_len, openflow); /* Update the instruction's length (or, if it's empty, delete it). */ oia = ofpbuf_at_assert(openflow, ofs, sizeof *oia); @@ -1508,6 +1532,47 @@ ofpacts_put_openflow11_instructions(const struct ofpact ofpacts[], openflow->size = ofs; } } + +void +ofpacts_put_openflow11_instructions(const struct ofpact ofpacts[], + size_t ofpacts_len, + struct ofpbuf *openflow) +{ + const struct ofpact *a; + + OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) { + /* TODO:XXX Write-Actions */ + /* TODO:XXX Write-Metadata */ + if (a->type == OFPACT_CLEAR_ACTIONS) { + struct ofp11_instruction *oi; + oi = instruction_put_OFPIT11_CLEAR_ACTIONS(openflow); + } else if (a->type == OFPACT_GOTO_TABLE) { + struct ofp11_instruction_goto_table *oigt; + + oigt = instruction_put_OFPIT11_GOTO_TABLE(openflow); + oigt->table_id = ofpact_get_GOTO_TABLE(a)->table_id; + memset(oigt->pad, 0, sizeof oigt->pad); + } else if (!ofpact_is_instruction(a)) { + /* Apply-actions */ + const size_t ofs = openflow->size; + const size_t ofpacts_len_left = + (uint8_t*)ofpact_end(ofpacts, ofpacts_len) - (uint8_t*)a; + const struct ofpact *action; + const struct ofpact *processed = a; + + instruction_put_OFPIT11_APPLY_ACTIONS(openflow); + OFPACT_FOR_EACH(action, a, ofpacts_len_left) { + if (ofpact_is_instruction(action)) { + break; + } + ofpact_to_openflow11(action, openflow); + processed = action; + } + ofpacts_update_instruction_actions(openflow, ofs); + a = processed; + } + } +} /* Returns true if 'action' outputs to 'port', false otherwise. */ static bool @@ -1546,6 +1611,8 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, uint16_t port) case OFPACT_AUTOPATH: case OFPACT_NOTE: case OFPACT_EXIT: + case OFPACT_CLEAR_ACTIONS: + case OFPACT_GOTO_TABLE: default: return false; } @@ -1773,7 +1840,8 @@ ofpact_format(const struct ofpact *a, struct ds *s) case OFPACT_RESUBMIT: resubmit = ofpact_get_RESUBMIT(a); if (resubmit->in_port != OFPP_IN_PORT && resubmit->table_id == 255) { - ds_put_format(s, "resubmit:%"PRIu16, resubmit->in_port); + ds_put_cstr(s, "resubmit:"); + ofputil_format_port(resubmit->in_port, s); } else { ds_put_format(s, "resubmit("); if (resubmit->in_port != OFPP_IN_PORT) { @@ -1797,7 +1865,9 @@ ofpact_format(const struct ofpact *a, struct ds *s) case OFPACT_AUTOPATH: autopath = ofpact_get_AUTOPATH(a); - ds_put_format(s, "autopath(%u,", autopath->port); + 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; @@ -1809,6 +1879,19 @@ ofpact_format(const struct ofpact *a, struct ds *s) case OFPACT_EXIT: ds_put_cstr(s, "exit"); break; + + case OFPACT_CLEAR_ACTIONS: + ds_put_format(s, "%s", + ofpact_instruction_name_from_type( + OVSINST_OFPIT11_CLEAR_ACTIONS)); + break; + + case OFPACT_GOTO_TABLE: + ds_put_format(s, "%s:%"PRIu8, + ofpact_instruction_name_from_type( + OVSINST_OFPIT11_GOTO_TABLE), + ofpact_get_GOTO_TABLE(a)->table_id); + break; } } @@ -1828,6 +1911,9 @@ ofpacts_format(const struct ofpact *ofpacts, size_t ofpacts_len, if (a != ofpacts) { ds_put_cstr(string, ","); } + + /* TODO:XXX write-actions */ + /* TODO:XXX write-metadata */ ofpact_format(a, string); } } @@ -1886,3 +1972,15 @@ ofpact_pad(struct ofpbuf *ofpacts) ofpbuf_put_zeros(ofpacts, OFPACT_ALIGNTO - rem); } } + +void +ofpact_set_field_init(struct ofpact_reg_load *load, const struct mf_field *mf, + const void *src) +{ + load->ofpact.compat = OFPUTIL_OFPAT12_SET_FIELD; + load->dst.field = mf; + load->dst.ofs = 0; + load->dst.n_bits = mf->n_bits; + bitwise_copy(src, mf->n_bytes, load->dst.ofs, + &load->subvalue, sizeof load->subvalue, 0, mf->n_bits); +}