Signed-off-by: Isaku Yamahata <yamah...@valinux.co.jp> --- lib/ofp-actions.c | 140 +++++++++++++++++++++++++++++++++++++++++++----- lib/ofp-actions.h | 30 ++++++++++- ofproto/ofproto-dpif.c | 7 +++ 3 files changed, 163 insertions(+), 14 deletions(-)
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index a826078..d7df9e6 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -852,6 +852,42 @@ ofpacts_pull_openflow11_actions(struct ofpbuf *openflow, ofpacts_from_openflow11); } +static enum ofperr +ofpacts_pull_inst_actions(const struct ofp11_instruction *inst, + struct ofpbuf *ofpacts, + enum ofperr (*ofpacts_from_openflow)( + const union ofp_action *in, size_t n_in, + struct ofpbuf *out)) +{ + const union ofp_action *actions; + size_t n_actions; + enum ofperr error; + struct ofpbuf *tmp = ofpbuf_new(1024 / 8); /* same to handle_flow_mod() */ + struct ofpact_inst_actions *inst_actions; + + get_actions_from_instruction(inst, &actions, &n_actions); + error = ofpacts_from_openflow(actions, n_actions, tmp); + if (error) { + goto exit; + } + + ofpbuf_prealloc_tailroom(ofpacts, sizeof(*inst_actions) + tmp->size); + if (inst->type == CONSTANT_HTONS(OFPIT11_APPLY_ACTIONS)) { + inst_actions = ofpact_put_APPLY_ACTIONS(ofpacts); + } else if (inst->type == CONSTANT_HTONS(OFPIT11_WRITE_ACTIONS)){ + inst_actions = ofpact_put_WRITE_ACTIONS(ofpacts); + } else { + NOT_REACHED(); + } + inst_actions->ofpacts_len = tmp->size; + ofpbuf_put(ofpacts, tmp->data, tmp->size); + ofpact_update_len(ofpacts, &inst_actions->ofpact); + +exit: + ofpbuf_delete(tmp); + return error; +} + enum ofperr ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow, unsigned int instructions_len, @@ -889,21 +925,37 @@ ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow, } if (insts[OVSINST_OFPIT11_APPLY_ACTIONS]) { - const union ofp_action *actions; - size_t n_actions; - - get_actions_from_instruction(insts[OVSINST_OFPIT11_APPLY_ACTIONS], - &actions, &n_actions); - error = ofpacts_from_openflow11(actions, n_actions, ofpacts); + error = ofpacts_pull_inst_actions(insts[OVSINST_OFPIT11_APPLY_ACTIONS], + ofpacts, ofpacts_from_openflow11); if (error) { goto exit; } } + if (insts[OVSINST_OFPIT11_CLEAR_ACTIONS]) { + ofpact_put_CLEAR_ACTIONS(ofpacts); + } + if (insts[OVSINST_OFPIT11_WRITE_ACTIONS]) { + error = ofpacts_pull_inst_actions(insts[OVSINST_OFPIT11_WRITE_ACTIONS], + ofpacts, ofpacts_from_openflow11); + if (error) { + goto exit; + } + } + /* TODO:XXX WRITE_METADATA */ + if (insts[OVSINST_OFPIT11_GOTO_TABLE]) { + struct ofp11_instruction_goto_table *oigt = + (struct ofp11_instruction_goto_table *) + insts[OVSINST_OFPIT11_GOTO_TABLE]; + struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(ofpacts); + resubmit->ofpact.compat = OFPUTIL_OFPIT11_GOTO_TABLE; + resubmit->in_port = OFPP_IN_PORT; + resubmit->table_id = oigt->table_id; + } - if (insts[OVSINST_OFPIT11_GOTO_TABLE] || - insts[OVSINST_OFPIT11_WRITE_METADATA] || + if (insts[OVSINST_OFPIT11_CLEAR_ACTIONS] || insts[OVSINST_OFPIT11_WRITE_ACTIONS] || - insts[OVSINST_OFPIT11_CLEAR_ACTIONS]) { + insts[OVSINST_OFPIT11_WRITE_METADATA]) { + /* TODO: CLEAR_ACTIONS, WRITE_ACTIONS support */ error = OFPERR_OFPBIC_UNSUP_INST; goto exit; } @@ -915,10 +967,16 @@ exit: return error; } +static enum ofperr ofpacts_check__(const struct ofpact ofpacts[], + size_t ofpacts_len, const struct flow *flow, + int max_ports, bool allow_inst); + 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, + bool allow_inst) { const struct ofpact_enqueue *enqueue; + struct ofpact_inst_actions *inst_actions; switch (a->type) { case OFPACT_OUTPUT: @@ -965,7 +1023,12 @@ ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports) case OFPACT_SET_QUEUE: case OFPACT_POP_QUEUE: case OFPACT_FIN_TIMEOUT: + return 0; + case OFPACT_RESUBMIT: + if (!allow_inst && a->compat == OFPUTIL_OFPIT11_GOTO_TABLE) { + NOT_REACHED(); + } return 0; case OFPACT_LEARN: @@ -981,6 +1044,27 @@ ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports) case OFPACT_EXIT: return 0; + case OFPACT_APPLY_ACTIONS: + if (!allow_inst) { + NOT_REACHED(); + } + inst_actions = ofpact_get_APPLY_ACTIONS(a); + return ofpacts_check__(inst_actions->ofpacts, + inst_actions->ofpacts_len, + flow, max_ports, false); + + case OFPACT_WRITE_ACTIONS: + if (!allow_inst) { + NOT_REACHED(); + } + inst_actions = ofpact_get_WRITE_ACTIONS(a); + return ofpacts_check__(inst_actions->ofpacts, + inst_actions->ofpacts_len, + flow, max_ports, false); + + case OFPACT_CLEAR_ACTIONS: + return 0; + default: NOT_REACHED(); } @@ -990,13 +1074,13 @@ ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports) * appropriate for a packet with the prerequisites satisfied by 'flow' in a * switch with no more than 'max_ports' ports. */ enum ofperr -ofpacts_check(const struct ofpact ofpacts[], size_t ofpacts_len, - const struct flow *flow, int max_ports) +ofpacts_check__(const struct ofpact ofpacts[], size_t ofpacts_len, + const struct flow *flow, int max_ports, bool allow_inst) { const struct ofpact *a; 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, allow_inst); if (error) { return error; } @@ -1004,6 +1088,13 @@ ofpacts_check(const struct ofpact ofpacts[], size_t ofpacts_len, return 0; } + +enum ofperr +ofpacts_check(const struct ofpact ofpacts[], size_t ofpacts_len, + const struct flow *flow, int max_ports) +{ + return ofpacts_check__(ofpacts, ofpacts_len, flow, max_ports, true); +} /* Converting ofpacts to Nicira OpenFlow extensions. */ @@ -1173,6 +1264,9 @@ 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_APPLY_ACTIONS: + case OFPACT_CLEAR_ACTIONS: + case OFPACT_WRITE_ACTIONS: NOT_REACHED(); } } @@ -1205,6 +1299,11 @@ static void ofpact_to_openflow10(const struct ofpact *a, struct ofpbuf *out) { switch (a->type) { + case OFPACT_APPLY_ACTIONS: + case OFPACT_CLEAR_ACTIONS: + case OFPACT_WRITE_ACTIONS: + NOT_REACHED(); + case OFPACT_OUTPUT: ofpact_output_to_openflow10(ofpact_get_OUTPUT(a), out); break; @@ -1314,6 +1413,11 @@ static void ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out) { switch (a->type) { + case OFPACT_APPLY_ACTIONS: + case OFPACT_CLEAR_ACTIONS: + case OFPACT_WRITE_ACTIONS: + NOT_REACHED(); + case OFPACT_OUTPUT: return ofpact_output_to_openflow11(ofpact_get_OUTPUT(a), out); @@ -1464,6 +1568,9 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, uint16_t port) case OFPACT_AUTOPATH: case OFPACT_NOTE: case OFPACT_EXIT: + case OFPACT_APPLY_ACTIONS: + case OFPACT_CLEAR_ACTIONS: + case OFPACT_WRITE_ACTIONS: default: return false; } @@ -1708,6 +1815,13 @@ ofpact_format(const struct ofpact *a, struct ds *s) case OFPACT_EXIT: ds_put_cstr(s, "exit"); break; + + case OFPACT_APPLY_ACTIONS: + case OFPACT_CLEAR_ACTIONS: + case OFPACT_WRITE_ACTIONS: + /* TODO:XXX */ + NOT_REACHED(); + break; } } diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h index d106a66..0299b39 100644 --- a/lib/ofp-actions.h +++ b/lib/ofp-actions.h @@ -21,6 +21,7 @@ #include "meta-flow.h" #include "ofp-errors.h" #include "ofp-util.h" +#include "ofpbuf.h" #include "openflow/openflow.h" #include "openflow/nicira-ext.h" #include "openvswitch/types.h" @@ -87,7 +88,18 @@ \ /* Other. */ \ DEFINE_OFPACT(NOTE, ofpact_note, data) \ - DEFINE_OFPACT(EXIT, ofpact_null, ofpact) + DEFINE_OFPACT(EXIT, ofpact_null, ofpact) \ + \ + /* Instruction */ \ + DEFINE_OFPACT(APPLY_ACTIONS, ofpact_inst_actions, ofpacts) \ + DEFINE_OFPACT(CLEAR_ACTIONS, ofpact_inst_actions, ofpact) \ + DEFINE_OFPACT(WRITE_ACTIONS, ofpact_inst_actions, ofpacts) + + /* TODO:XXX ofpact_inst_meter */ + /* + * instruction write-metadata => reg_load with compat set + * goto-table => resubmit with compat set + */ /* enum ofpact_type, with a member OFPACT_<ENUM> for each action. */ enum OVS_PACKED_ENUM ofpact_type { @@ -380,6 +392,22 @@ struct ofpact_note { uint8_t data[]; }; +/* OFPACT_APPLY_ACTIONS, OFPACT_CLEAR_ACTIONS, OFPACT_WRITE_ACTIONS + * + * user for OFPIT11_WRITE_ACTIONS, OFPIT11_APPLY_ACTIONS, + * OFPIT11_CLEAR_ACTIONS */ +struct ofpact_inst_actions { + struct ofpact ofpact; + uint8_t pad0[OFP_ACTION_ALIGN - + (sizeof(struct ofpact) % OFP_ACTION_ALIGN)]; + /* This is required by ofpact_pull() */ + + size_t ofpacts_len; + uint8_t pad1[OFP_ACTION_ALIGN - (sizeof(size_t) % OFP_ACTION_ALIGN)]; + struct ofpact ofpacts[]; +}; +BUILD_ASSERT_DECL((sizeof(struct ofpact_inst_actions) % OFPACT_ALIGNTO) == 0); + /* Converting OpenFlow to ofpacts. */ enum ofperr ofpacts_pull_openflow10(struct ofpbuf *openflow, unsigned int actions_len, diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 5265d7b..69b9682 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -5539,6 +5539,13 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, ctx->has_fin_timeout = true; xlate_fin_timeout(ctx, ofpact_get_FIN_TIMEOUT(a)); break; + + case OFPACT_WRITE_ACTIONS: + case OFPACT_APPLY_ACTIONS: + case OFPACT_CLEAR_ACTIONS: + /* TODO:XXX */ + NOT_REACHED(); + break; } } -- 1.7.1.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev