Signed-off-by: Isaku Yamahata <yamah...@valinux.co.jp>
---
v2
- changed for ofp_instruction
---
 lib/ofp-actions.c |   22 ++++++++++
 lib/ofp-actions.h |    2 +
 lib/ofp-parse.c   |  121 +++++++++++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 136 insertions(+), 9 deletions(-)

diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index d5422ec..6a9633f 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -692,6 +692,28 @@ ofpacts_from_openflow11(const union ofp_action *in, size_t 
n_in,
 OVS_INSTRUCTIONS
 #undef DEFINE_INST
 
+int
+ofpact_instruction_type_from_name(const char *name)
+{
+    struct type_info {
+        enum ovs_instruction_type type;
+        const char *name;
+    };
+    static const struct type_info info[N_OVS_INSTRUCTIONS] = {
+#define DEFINE_INST(ENUM, STRUCT, EXTENSIBLE, NAME)    {ENUM, NAME},
+OVS_INSTRUCTIONS
+#undef DEFINE_INST
+    };
+    const struct type_info *p;
+
+    for (p = info; p < &info[ARRAY_SIZE(info)]; p++) {
+        if (!strcasecmp(name, p->name)) {
+            return p->type;
+        }
+    }
+    return -1;
+}
+
 static inline struct ofp11_instruction *
 instruction_next(const struct ofp11_instruction *inst)
 {
diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h
index d742590..1611aa7 100644
--- a/lib/ofp-actions.h
+++ b/lib/ofp-actions.h
@@ -549,4 +549,6 @@ ofpact_put_instruction(struct ofpbuf *ofpacts, enum 
ovs_instruction_type type)
     return inst;
 }
 
+int ofpact_instruction_type_from_name(const char *name);
+
 #endif /* ofp-actions.h */
diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index 32d3836..762357d 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -471,6 +471,86 @@ str_to_ofpacts(const struct flow *flow, char *str, struct 
ofpbuf *ofpacts)
     ofpact_pad(ofpacts);
 }
 
+static void
+parse_named_instruction(enum ovs_instruction_type type,
+                        const struct flow *flow,
+                        char *arg, struct ofpbuf *ofpacts)
+{
+    ofpact_put_instruction(ofpacts, type);
+
+    switch (type) {
+    case OVSINST_OFPIT11_APPLY_ACTIONS:
+    case OVSINST_OFPIT11_WRITE_ACTIONS:
+        str_to_ofpacts(flow, arg, ofpacts);
+        break;
+
+    case OVSINST_OFPIT11_CLEAR_ACTIONS:
+        /* nothing */
+        break;
+
+    case OVSINST_OFPIT11_WRITE_METADATA:
+        NOT_REACHED();  /* TODO:XXX */
+        break;
+
+    case OVSINST_OFPIT11_GOTO_TABLE: {
+        struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(ofpacts);
+        char *table_s = strsep(&arg, ",");
+        resubmit->table_id = table_s && table_s[0] ? str_to_u32(table_s) : 255;
+        resubmit->in_port = OFPP_IN_PORT;
+        resubmit->ofpact.compat = -1; /* TODO:XXX use symbolic constant */
+        break;
+    }
+    }
+}
+
+static void
+str_to_inst_ofpacts(const struct flow *flow, char *str, struct ofpbuf *ofpacts)
+{
+    char *pos, *inst, *arg;
+    char *inst_args[N_OVS_INSTRUCTIONS];
+    int i;
+
+    memset(inst_args, 0, sizeof inst_args);
+    pos = str;
+    while (ofputil_parse_key_value(&pos, &inst, &arg)) {
+        int type;
+
+        type = ofputil_action_code_from_name(inst);
+        if (type < 0) {
+            ovs_fatal(0, "Unknown instruction: %s", inst);
+        }
+        if (inst_args[type]) {
+            ovs_fatal(0, "Instruction %s can be specified only once", inst);
+        }
+        inst_args[type] = arg;
+    }
+
+    if (inst_args[OVSINST_OFPIT11_CLEAR_ACTIONS] ||
+        inst_args[OVSINST_OFPIT11_WRITE_ACTIONS] ||
+        inst_args[OVSINST_OFPIT11_WRITE_METADATA] ||
+        inst_args[OVSINST_OFPIT11_GOTO_TABLE]) {
+        static const enum ovs_instruction_type types[] = {
+            OVSINST_OFPIT11_APPLY_ACTIONS,
+            OVSINST_OFPIT11_CLEAR_ACTIONS,
+            OVSINST_OFPIT11_WRITE_ACTIONS,
+            OVSINST_OFPIT11_WRITE_METADATA,
+            OVSINST_OFPIT11_GOTO_TABLE,
+        };
+        for (i = 0; i < ARRAY_SIZE(types); i++) {
+            if (inst_args[types[i]]) {
+                parse_named_instruction(types[i], flow, inst_args[types[i]],
+                                        ofpacts);
+            }
+        }
+
+    } else if (inst_args[OVSINST_OFPIT11_APPLY_ACTIONS]) {
+        str_to_ofpacts(flow, inst_args[OVSINST_OFPIT11_APPLY_ACTIONS],
+                       ofpacts);
+    }
+
+    ofpact_pad(ofpacts);
+}
+
 struct protocol {
     const char *name;
     uint16_t dl_type;
@@ -552,6 +632,7 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, 
const char *str_,
     } fields;
     char *string = xstrdup(str_);
     char *save_ptr = NULL;
+    char *inst_str = NULL;
     char *act_str = NULL;
     char *name;
 
@@ -602,17 +683,35 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, 
const char *str_,
     fm->flags = 0;
     if (fields & F_ACTIONS) {
         act_str = strstr(string, "action");
-        if (!act_str) {
-            ofp_fatal(str_, verbose, "must specify an action");
-        }
-        *act_str = '\0';
+        if (act_str) {
+            *act_str = '\0';
 
-        act_str = strchr(act_str + 1, '=');
-        if (!act_str) {
-            ofp_fatal(str_, verbose, "must specify an action");
+            act_str = strchr(act_str + 1, '=');
+            if (!act_str) {
+                ofp_fatal(str_, verbose, "must specify an action");
+            }
+
+            act_str++;
         }
 
-        act_str++;
+        inst_str = strstr(string, "instruction");
+        if (inst_str) {
+            *inst_str = '\0';
+
+            inst_str = strchr(inst_str + 1, '=');
+            if (!inst_str) {
+                ofp_fatal(str_, verbose, "must specify an instruction");
+            }
+
+            inst_str++;
+        }
+    }
+    if (fields & F_ACTIONS && act_str == NULL && inst_str == NULL) {
+        ofp_fatal(str_, verbose, "must specify an action or an instruction");
+    }
+    if (act_str && inst_str) {
+        ofp_fatal(str_, verbose,
+                  "must not specify both action and instruction.");
     }
     for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name;
          name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
@@ -689,7 +788,11 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, 
const char *str_,
         struct ofpbuf ofpacts;
 
         ofpbuf_init(&ofpacts, 32);
-        str_to_ofpacts(&fm->cr.flow, act_str, &ofpacts);
+        if (act_str) {
+            str_to_ofpacts(&fm->cr.flow, act_str, &ofpacts);
+        } else {
+            str_to_inst_ofpacts(&fm->cr.flow, inst_str, &ofpacts);
+        }
         fm->ofpacts_len = ofpacts.size;
         fm->ofpacts = ofpbuf_steal_data(&ofpacts);
     } else {
-- 
1.7.1.1

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to