Signed-off-by: Isaku Yamahata <yamah...@valinux.co.jp> --- lib/ofp-actions.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++++----- lib/ofp-util.c | 26 ++++++++ 2 files changed, 191 insertions(+), 17 deletions(-)
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index 2489879..a88c253 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -1499,38 +1499,186 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out) /* Converts the ofpacts in 'ofpacts' (terminated by OFPACT_END) into OpenFlow * 1.1 actions in 'openflow', appending the actions to any existing data in * 'openflow'. */ -void -ofpacts_put_openflow11_actions(const struct ofpact ofpacts[], - size_t ofpacts_len, struct ofpbuf *openflow) +static void +ofpacts_put_openflow11_actions__(const struct ofpact ofpacts[], + size_t ofpacts_len, struct ofpbuf *openflow, + void (*ofpact_to_openflow)( + const struct ofpact *a, + struct ofpbuf *out)) { const struct ofpact *a; OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) { - ofpact_to_openflow11(a, openflow); + assert(!ofpact_is_instruction(a)); + ofpact_to_openflow(a, openflow); } } void -ofpacts_put_openflow11_instructions(const struct ofpact ofpacts[], +ofpacts_put_openflow11_actions(const struct ofpact ofpacts[], + size_t ofpacts_len, struct ofpbuf *openflow) +{ + return ofpacts_put_openflow11_actions__(ofpacts, ofpacts_len, openflow, + ofpact_to_openflow11); +} + +static void +ofpacts_put_openflow11_inst_actions(const struct ofpact ofpacts[], size_t ofpacts_len, - struct ofpbuf *openflow) + struct ofpbuf *openflow, + enum ofp11_instruction_type type, + void (*ofpact_to_openflow)( + const struct ofpact *a, + struct ofpbuf *out)) { + size_t start_len; 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); + if (ofpacts_len == 0) { + /* If no action is contained, delete the instruction */ + return; + } - /* Update the instruction's length (or, if it's empty, delete it). */ - oia = ofpbuf_at_assert(openflow, ofs, sizeof *oia); - if (openflow->size > ofs + sizeof *oia) { - oia->len = htons(openflow->size - ofs); - } else { - openflow->size = ofs; + start_len = openflow->size; + switch (type) { + case OFPIT11_WRITE_ACTIONS: + oia = instruction_put_OFPIT11_WRITE_ACTIONS(openflow); + break; + + case OFPIT11_APPLY_ACTIONS: + oia = instruction_put_OFPIT11_APPLY_ACTIONS(openflow); + break; + + case OFPIT11_GOTO_TABLE: + case OFPIT11_WRITE_METADATA: + case OFPIT11_CLEAR_ACTIONS: + case OFPIT11_EXPERIMENTER: + default: + NOT_REACHED(); + break; + } + + ofpacts_put_openflow11_actions__(ofpacts, ofpacts_len, openflow, + ofpact_to_openflow); + oia = ofpbuf_at_assert(openflow, start_len, sizeof *oia); + oia->len = htons(openflow->size - start_len); + memset(oia->pad, 0, sizeof oia->pad); +} + +static void +ofpacts_put_openflow11_instruction__(const struct ofpact *ofpact, + struct ofpbuf *openflow, + void (*ofpact_to_openflow)( + const struct ofpact *a, + struct ofpbuf *out)) +{ + struct ofp11_instruction *oi; + + switch (ofpact->type) { + case OFPACT_RESUBMIT: { + struct ofpact_resubmit *resubmit; + struct ofp11_instruction_goto_table *oigt; + + resubmit = ofpact_get_RESUBMIT(ofpact); + assert(resubmit->in_port == OFPP_IN_PORT); + assert(resubmit->ofpact.compat == OFPUTIL_OFPIT11_GOTO_TABLE); + + oigt = instruction_put_OFPIT11_GOTO_TABLE(openflow); + oigt->table_id = resubmit->table_id; + memset(oigt->pad, 0, sizeof oigt->pad); + break; + } + + case OFPACT_WRITE_ACTIONS: + case OFPACT_APPLY_ACTIONS: { + const struct ofpact_inst_actions *inst_actions; + enum ofp11_instruction_type type; + + if (ofpact->type == OFPACT_WRITE_ACTIONS) { + inst_actions = ofpact_get_WRITE_ACTIONS(ofpact); + type = OFPIT11_WRITE_ACTIONS; + } else { + inst_actions = ofpact_get_APPLY_ACTIONS(ofpact); + type = OFPIT11_APPLY_ACTIONS; + } + ofpacts_put_openflow11_inst_actions(&inst_actions->ofpact, + inst_actions->ofpacts_len, + openflow, type, + ofpact_to_openflow); + break; + } + + case OFPACT_CLEAR_ACTIONS: + oi = instruction_put_OFPIT11_CLEAR_ACTIONS(openflow); + memset(oi->pad, 0, sizeof oi->pad); + break; + + /* FIXME: write-metadata, experimenter, meter */ + + case OFPACT_OUTPUT: + case OFPACT_CONTROLLER: + case OFPACT_ENQUEUE: + case OFPACT_OUTPUT_REG: + case OFPACT_BUNDLE: + case OFPACT_SET_VLAN_VID: + case OFPACT_SET_VLAN_PCP: + case OFPACT_STRIP_VLAN: + case OFPACT_SET_ETH_SRC: + case OFPACT_SET_ETH_DST: + case OFPACT_SET_IPV4_SRC: + case OFPACT_SET_IPV4_DST: + case OFPACT_SET_IPV4_DSCP: + case OFPACT_SET_L4_SRC_PORT: + case OFPACT_SET_L4_DST_PORT: + case OFPACT_REG_MOVE: + case OFPACT_REG_LOAD: + case OFPACT_DEC_TTL: + case OFPACT_SET_TUNNEL: + case OFPACT_SET_QUEUE: + case OFPACT_POP_QUEUE: + case OFPACT_FIN_TIMEOUT: + case OFPACT_LEARN: + case OFPACT_MULTIPATH: + case OFPACT_AUTOPATH: + case OFPACT_NOTE: + case OFPACT_EXIT: + default: + NOT_REACHED(); + } +} + +static void +ofpacts_put_openflow11_instructions__(const struct ofpact ofpacts[], + size_t ofpacts_len, + struct ofpbuf *openflow, + void (*ofpact_to_openflow)( + const struct ofpact *a, + struct ofpbuf *out)) +{ + const struct ofpact *a; + + if (!ofpact_is_instruction(ofpacts)) { + ofpacts_put_openflow11_inst_actions(ofpacts, ofpacts_len, + openflow, OFPIT11_APPLY_ACTIONS, + ofpact_to_openflow); + return; + } + + OFPACT_FOR_EACH(a, ofpacts, ofpacts_len) { + assert(ofpact_is_instruction(a)); + ofpacts_put_openflow11_instruction__(a, openflow, ofpact_to_openflow); } } + +void +ofpacts_put_openflow11_instructions(const struct ofpact ofpacts[], + size_t ofpacts_len, + struct ofpbuf *openflow) +{ + return ofpacts_put_openflow11_instructions__(ofpacts, ofpacts_len, + openflow, + ofpact_to_openflow11); +} /* Returns true if 'action' outputs to 'port', false otherwise. */ static bool diff --git a/lib/ofp-util.c b/lib/ofp-util.c index f8a4cd3..15ae0b0 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -1788,6 +1788,32 @@ ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm, : fm->command); switch (protocol) { +#if 0 + case OFPUTIL_P_OF11: { + struct ofp11_flow_mod *ofm11; + msg = ofpbuf_new(sizeof *ofm11 + NXM_TYPICAL_LEN + fm->ofpacts_len); + ofm11 = put_openflow(sizeof *ofm11, ofp_version, OFPT11_FLOW_MOD, msg); + ofm11->cookie = fm->new_cookie; + ofm11->cookie_mask = fm->cookie_mask; + ofm11->table_id = fm->table_id; + ofm11->command = fm->command; + ofm11->idle_timeout = htons(fm->idle_timeout); + ofm11->hard_timeout = htons(fm->hard_timeout); + ofm11->priority = htons(fm->cr.priority); + ofm11->buffer_id = htonl(fm->buffer_id); + ofm11->out_port = ofputil_port_to_ofp11(fm->out_port); + ofm11->out_group = htonl(OFPG11_ANY); + ofm11->flags = htons(fm->flags); + memset(ofm11->pad, 0, sizeof ofm11->pad); + /* XXX ofm11::match */ + if (fm->ofpacts) { + ofpacts_put_openflow11_instructions(fm->ofpacts, fm->ofpacts_len, + msg); + } + break; + } +#endif + case OFPUTIL_P_OF10: case OFPUTIL_P_OF10_TID: msg = ofpbuf_new(sizeof *ofm + fm->ofpacts_len); -- 1.7.1.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev