[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