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