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