[ovs-dev] [PATCH v3 08/12] ofp-parser: instruction parser
Isaku Yamahata
yamahata at valinux.co.jp
Mon Jul 23 08:08:47 UTC 2012
Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
---
v3
- change for OFPACT_{CLEAR_ACTIONS, WRITE_ACTIONS, GOTO_TABLE}
v2
- changed for ofp_instruction
---
lib/ofp-actions.c | 22 ++++++++++
lib/ofp-actions.h | 2 +
lib/ofp-parse.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++----
3 files changed, 127 insertions(+), 9 deletions(-)
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index 77250a8..165b131 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 5734da9..2ab2e94 100644
--- a/lib/ofp-actions.h
+++ b/lib/ofp-actions.h
@@ -553,4 +553,6 @@ ofpact_is_instruction(const struct ofpact *a)
|| a->type == OFPACT_GOTO_TABLE;
}
+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..b33979e 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -471,6 +471,77 @@ 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)
+{
+ switch (type) {
+ case OVSINST_OFPIT11_APPLY_ACTIONS:
+ str_to_ofpacts(flow, arg, ofpacts);
+ break;
+
+ case OVSINST_OFPIT11_WRITE_ACTIONS:
+ ofpact_put_WRITE_ACTIONS(ofpacts);
+ str_to_ofpacts(flow, arg, ofpacts);
+ break;
+
+ case OVSINST_OFPIT11_CLEAR_ACTIONS:
+ ofpact_put_CLEAR_ACTIONS(ofpacts);
+ break;
+
+ case OVSINST_OFPIT11_WRITE_METADATA:
+ NOT_REACHED(); /* TODO:XXX */
+ break;
+
+ case OVSINST_OFPIT11_GOTO_TABLE: {
+ struct ofpact_goto_table *ogt = ofpact_put_GOTO_TABLE(ofpacts);
+ char *table_s = strsep(&arg, ",");
+ ogt->table_id = table_s && table_s[0] ? str_to_u32(table_s) : 255;
+ 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 type;
+ const char *prev_inst = NULL;
+ int prev_type = -1;
+
+ memset(inst_args, 0, sizeof inst_args);
+ pos = str;
+ while (ofputil_parse_key_value(&pos, &inst, &arg)) {
+ type = ofpact_instruction_type_from_name(inst);
+ if (type < 0) {
+ ovs_fatal(0, "Unknown instruction: %s", inst);
+ }
+ if (type == prev_type) {
+ ovs_fatal(0, "instruction can be specified at most once: %s",
+ inst);
+ }
+ if (type <= prev_type) {
+ ovs_fatal(0, "Instruction %s must be specified before %s",
+ inst, prev_inst);
+ }
+ inst_args[type] = arg;
+
+ prev_inst = inst;
+ prev_type = type;
+ }
+
+ for (type = 0; type < N_OVS_INSTRUCTIONS; type++) {
+ if (inst_args[type]) {
+ parse_named_instruction(type, flow, inst_args[type], ofpacts);
+ }
+ }
+
+ ofpact_pad(ofpacts);
+}
+
struct protocol {
const char *name;
uint16_t dl_type;
@@ -552,6 +623,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 +674,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 +779,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
More information about the dev
mailing list