[ovs-dev] [PATCH v5 6/6] instruction/write-actions: add text parser/formater, of packet decoder/encoder

Isaku Yamahata yamahata at valinux.co.jp
Tue Aug 28 17:19:05 UTC 2012


Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
---
v5
- manual rebase

v4
- write-action part is split out
- man page
---
 lib/ofp-actions.c        |   55 +++++++++++++++++++++++++++++++++++++--------
 lib/ofp-actions.h        |   11 ++++++---
 lib/ofp-parse.c          |    6 +---
 ofproto/ofproto-dpif.c   |   10 ++++----
 tests/ofp-actions.at     |   18 ++++++++++++--
 utilities/ovs-ofctl.8.in |    4 +++
 6 files changed, 78 insertions(+), 26 deletions(-)

diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index bfcbe5c..d541ea9 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -902,6 +902,18 @@ ofpacts_pull_openflow11_actions(struct ofpbuf *openflow,
                                 ofpacts_from_openflow11);
 }
 
+static enum ofperr
+ofpacts_pull_openflow11_inst_actions(const struct ofp11_instruction *inst,
+                                     struct ofpbuf *ofpacts)
+
+{
+    const union ofp_action *actions;
+    size_t n_actions;
+
+    get_actions_from_instruction(inst, &actions, &n_actions);
+    return ofpacts_from_openflow11(actions, n_actions, ofpacts);
+}
+
 enum ofperr
 ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow,
                                      unsigned int instructions_len,
@@ -940,17 +952,14 @@ ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow,
 
     if (insts[OVSINST_OFPIT11_APPLY_ACTIONS]) {
         const struct ofp11_instruction_actions *oia;
-        const union ofp_action *actions;
-        size_t n_actions;
 
         oia = instruction_get_OFPIT11_APPLY_ACTIONS(
             insts[OVSINST_OFPIT11_APPLY_ACTIONS]);
         if (!is_all_zeros(oia->pad, sizeof oia->pad)) {
             return OFPERR_OFPBAC_BAD_ARGUMENT;
         }
-        get_actions_from_instruction(insts[OVSINST_OFPIT11_APPLY_ACTIONS],
-                                     &actions, &n_actions);
-        error = ofpacts_from_openflow11(actions, n_actions, ofpacts);
+        error = ofpacts_pull_openflow11_inst_actions(
+            insts[OVSINST_OFPIT11_APPLY_ACTIONS], ofpacts);
         if (error) {
             goto exit;
         }
@@ -965,7 +974,21 @@ ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow,
         }
         ofpact_put_CLEAR_ACTIONS(ofpacts);
     }
-    /* TODO:XXX Write-Actions */
+    if (insts[OVSINST_OFPIT11_WRITE_ACTIONS]) {
+        const struct ofp11_instruction_actions *oia;
+
+        oia = instruction_get_OFPIT11_WRITE_ACTIONS(
+            insts[OVSINST_OFPIT11_WRITE_ACTIONS]);
+        if (!is_all_zeros(oia->pad, sizeof oia->pad)) {
+            return OFPERR_OFPBAC_BAD_ARGUMENT;
+        }
+        ofpact_put_WRITE_ACTIONS(ofpacts);
+        error = ofpacts_pull_openflow11_inst_actions(
+            insts[OVSINST_OFPIT11_WRITE_ACTIONS], ofpacts);
+        if (error) {
+            goto exit;
+        }
+    }
     /* TODO:XXX Write-Metadata */
     if (insts[OVSINST_OFPIT11_GOTO_TABLE]) {
         const struct ofp11_instruction_goto_table *oigt;
@@ -980,8 +1003,7 @@ ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow,
         ogt->table_id = oigt->table_id;
     }
 
-    if (insts[OVSINST_OFPIT11_WRITE_METADATA] ||
-        insts[OVSINST_OFPIT11_WRITE_ACTIONS]) {
+    if (insts[OVSINST_OFPIT11_WRITE_METADATA]) {
         error = OFPERR_OFPBIC_UNSUP_INST;
         goto exit;
     }
@@ -1060,6 +1082,7 @@ ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports)
         return 0;
 
     case OFPACT_CLEAR_ACTIONS:
+    case OFPACT_WRITE_ACTIONS:
     case OFPACT_GOTO_TABLE:
         return 0;
 
@@ -1279,6 +1302,7 @@ ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out)
     case OFPACT_SET_L4_SRC_PORT:
     case OFPACT_SET_L4_DST_PORT:
     case OFPACT_CLEAR_ACTIONS:
+    case OFPACT_WRITE_ACTIONS:
     case OFPACT_GOTO_TABLE:
         NOT_REACHED();
     }
@@ -1370,6 +1394,7 @@ ofpact_to_openflow10(const struct ofpact *a, struct ofpbuf *out)
         break;
 
     case OFPACT_CLEAR_ACTIONS:
+    case OFPACT_WRITE_ACTIONS:
     case OFPACT_GOTO_TABLE:
         /* TODO:XXX */
         break;
@@ -1483,6 +1508,7 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out)
         break;
 
     case OFPACT_CLEAR_ACTIONS:
+    case OFPACT_WRITE_ACTIONS:
     case OFPACT_GOTO_TABLE:
         NOT_REACHED();
 
@@ -1556,12 +1582,15 @@ ofpacts_put_openflow11_instructions(const struct ofpact ofpacts[],
             ofs = 0;
         }
 
-        /* TODO:XXX Write-Actions */
         /* TODO:XXX Write-Metadata */
         if (a->type == OFPACT_CLEAR_ACTIONS) {
             struct ofp11_instruction *oi;
             oi = instruction_put_OFPIT11_CLEAR_ACTIONS(openflow);
             memset(oi->pad, 0, sizeof oi->pad);
+        } else if (a->type == OFPACT_WRITE_ACTIONS) {
+            in_instruction = true;
+            ofs = openflow->size;
+            instruction_put_OFPIT11_WRITE_ACTIONS(openflow);
         } else if (a->type == OFPACT_GOTO_TABLE) {
             struct ofp11_instruction_goto_table *oigt;
             oigt = instruction_put_OFPIT11_GOTO_TABLE(openflow);
@@ -1619,6 +1648,7 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, uint16_t port)
     case OFPACT_NOTE:
     case OFPACT_EXIT:
     case OFPACT_CLEAR_ACTIONS:
+    case OFPACT_WRITE_ACTIONS:
     case OFPACT_GOTO_TABLE:
     default:
         return false;
@@ -1885,6 +1915,7 @@ ofpact_format(const struct ofpact *a, struct ds *s)
         break;
 
     case OFPACT_CLEAR_ACTIONS:
+    case OFPACT_WRITE_ACTIONS:
     case OFPACT_GOTO_TABLE:
         NOT_REACHED();
     }
@@ -1939,11 +1970,15 @@ ofpacts_format(const struct ofpact *ofpacts, size_t ofpacts_len,
             n_actions = 0;
         }
 
-        /* TODO:XXX write-actions */
         /* TODO:XXX write-metadata */
         if (a->type == OFPACT_CLEAR_ACTIONS) {
             ds_put_format(string, "%s", ofpact_instruction_name_from_type(
                               OVSINST_OFPIT11_CLEAR_ACTIONS));
+        } else if (a->type == OFPACT_WRITE_ACTIONS) {
+            ds_put_format(string, "%s(", ofpact_instruction_name_from_type(
+                              OVSINST_OFPIT11_WRITE_ACTIONS));
+            in_instruction = true;
+            n_actions = 0;
         } else if (a->type == OFPACT_GOTO_TABLE) {
             ds_put_format(string, "%s:%"PRIu8,
                           ofpact_instruction_name_from_type(
diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h
index c899868..e5cb019 100644
--- a/lib/ofp-actions.h
+++ b/lib/ofp-actions.h
@@ -90,8 +90,9 @@
     DEFINE_OFPACT(EXIT,            ofpact_null,          ofpact)    \
                                                                     \
     /* Instructions */                                              \
-    /* TODO:XXX Write-Actions, Write-Metadata */                    \
+    /* TODO:XXX Write-Metadata */                                   \
     DEFINE_OFPACT(CLEAR_ACTIONS,   ofpact_null,          ofpact)    \
+    DEFINE_OFPACT(WRITE_ACTIONS,   ofpact_null,          ofpact)    \
     DEFINE_OFPACT(GOTO_TABLE,      ofpact_goto_table,    ofpact)
 
 /* enum ofpact_type, with a member OFPACT_<ENUM> for each action. */
@@ -150,10 +151,11 @@ ofpact_end(const struct ofpact *ofpacts, size_t ofpacts_len)
 
 /* Action structure for each OFPACT_*. */
 
-/* OFPACT_STRIP_VLAN, OFPACT_POP_QUEUE, OFPACT_EXIT, OFPACT_CLEAR_ACTIONS.
+/* OFPACT_STRIP_VLAN, OFPACT_POP_QUEUE, OFPACT_EXIT, OFPACT_CLEAR_ACTIONS,
+ * OFPACT_WRITE_ACTIONS.
  *
  * Used for OFPAT10_STRIP_VLAN, NXAST_DEC_TTL, NXAST_POP_QUEUE, NXAST_EXIT,
- * OFPIT11_CLEAR_ACTIONS.
+ * OFPIT11_CLEAR_ACTIONS, OFPIT11_WRITE_ACTIONS.
  *
  * Action structure for actions that do not have any extra data beyond the
  * action type. */
@@ -559,8 +561,9 @@ enum {
 static inline bool
 ofpact_is_instruction(const struct ofpact *a)
 {
-    /* TODO:XXX Write-Actions, Write-Metadata */
+    /* TODO:XXX Write-Metadata */
     return a->type == OFPACT_CLEAR_ACTIONS
+        || a->type == OFPACT_WRITE_ACTIONS
         || a->type == OFPACT_GOTO_TABLE;
 }
 
diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index 50925c9..4b7dc37 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -518,7 +518,8 @@ parse_named_instruction(enum ovs_instruction_type type,
         break;
 
     case OVSINST_OFPIT11_WRITE_ACTIONS:
-        NOT_REACHED();  /* TODO:XXX */
+        ofpact_put_WRITE_ACTIONS(ofpacts);
+        str_to_ofpacts(flow, arg, ofpacts);
         break;
 
     case OVSINST_OFPIT11_CLEAR_ACTIONS:
@@ -572,9 +573,6 @@ str_to_inst_ofpacts(const struct flow *flow, char *str, struct ofpbuf *ofpacts)
     }
 
     /* TODO:XXX */
-    if (inst_args[OVSINST_OFPIT11_WRITE_ACTIONS]) {
-        ovs_fatal(0, "instruction write-actions is not supported yet");
-    }
     if (inst_args[OVSINST_OFPIT11_WRITE_METADATA]) {
         ovs_fatal(0, "instruction write-metadata is not supported yet");
     }
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index d35a0bd..1964837 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -5603,11 +5603,11 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
             break;
 
         case OFPACT_CLEAR_ACTIONS:
-            /* TODO:XXX
-             * Nothing to do because writa-actions is not supported for now.
-             * When writa-actions is supported, clear-actions also must
-             * be supported at the same time.
-             */
+            NOT_REACHED(); /* TODO:XXX */
+            break;
+
+        case OFPACT_WRITE_ACTIONS:
+            NOT_REACHED(); /* TODO:XXX */
             break;
 
         case OFPACT_GOTO_TABLE: {
diff --git a/tests/ofp-actions.at b/tests/ofp-actions.at
index 0e77893..7469859 100644
--- a/tests/ofp-actions.at
+++ b/tests/ofp-actions.at
@@ -295,9 +295,21 @@ dnl Write-Metadata too long.
 # bad OF1.1 instructions: OFPBIC_BAD_LEN
 0002 0020 00000000 fedcba9876543210 ffffffffffffffff 0000000000000000
 
-dnl Write-Actions not supported yet.
-# bad OF1.1 instructions: OFPBIC_UNSUP_INST
-0003 0008 01 000000
+dnl Write-Actions non-zero padding
+# bad OF1.1 instructions: OFPBAC_BAD_ARGUMENT
+0003 0008 00000001
+
+dnl Write-Actions
+# instructions=write_actions(drop)
+#  0: 00 -> (none)
+#  1: 03 -> (none)
+#  2: 00 -> (none)
+#  3: 08 -> (none)
+#  4: 00 -> (none)
+#  5: 00 -> (none)
+#  6: 00 -> (none)
+#  7: 00 -> (none)
+0003 0008 00000000
 
 dnl Clear-Actions too-long
 # bad OF1.1 instructions: OFPBIC_BAD_LEN
diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in
index f72c0b1..64c9c32 100644
--- a/utilities/ovs-ofctl.8.in
+++ b/utilities/ovs-ofctl.8.in
@@ -1139,6 +1139,10 @@ to \fBactions=\fR field.
 .IP \fBclear_actions\fR
 Clears all the actions in the action set immediately.
 .
+.IP \fBwrite_actions(\fR[\fIaction\fR][\fB,\fIaction\fR...]\fB)
+Merges the specified actions(s) into the current actions set.
+The syntax of actions are same to \fBactions=\fR field.
+.
 .IP \fBgoto_table\fR:\fItable\fR
 Indicates the next table in the process pipeline.
 .RE
-- 
1.7.1.1




More information about the dev mailing list