[ovs-dev] [PATCH 09/17] ofp-actions: implement instruction encoder
Isaku Yamahata
yamahata at valinux.co.jp
Wed Jul 18 11:41:23 UTC 2012
Signed-off-by: Isaku Yamahata <yamahata at 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
More information about the dev
mailing list