[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