Signed-off-by: Isaku Yamahata <[email protected]>
---
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
[email protected]
http://openvswitch.org/mailman/listinfo/dev