From: Andrew Evans Date: Fri, 17 Jun 2011 19:24:54 +0000 (-0700) Subject: ovs-ofctl: Print the offending flow on parse error when reading from a file. X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=ec610b7bf4f4890f50c2c7d2fbfe6120ad9312f1;p=ovs.git ovs-ofctl: Print the offending flow on parse error when reading from a file. When an error is encountered while parsing flows from a file, ovs-ofctl doesn't print the erroneous flow, so it's not always obvious which flow is causing the error. Print the flow before the error message to make it clear. --- diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index a4679a3ac..25fd2b965 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -614,6 +614,19 @@ struct field { flow_wildcards_t wildcard; /* FWW_* bit. */ }; +static void +ofp_fatal(const char *flow, bool verbose, const char *format, ...) +{ + va_list args; + + if (verbose) { + fprintf(stderr, "%s:\n", flow); + } + + va_start(args, format); + ovs_fatal_valist(0, format, args); +} + static bool parse_field_name(const char *name, const struct field **f_out) { @@ -777,12 +790,14 @@ parse_reg_value(struct cls_rule *rule, int reg_idx, const char *value) } } -/* Convert 'string' (as described in the Flow Syntax section of the ovs-ofctl - * man page) into 'pf'. If 'actions' is specified, an action must be in +/* Convert 'str_' (as described in the Flow Syntax section of the ovs-ofctl + * man page) into 'fm'. If 'actions' is specified, an action must be in * 'string' and may be expanded or reallocated. */ void -parse_ofp_str(struct flow_mod *fm, struct ofpbuf *actions, char *string) +parse_ofp_str(struct flow_mod *fm, struct ofpbuf *actions, const char *str_, + bool verbose) { + char *string = xstrdup(str_); char *save_ptr = NULL; char *name; @@ -798,13 +813,13 @@ parse_ofp_str(struct flow_mod *fm, struct ofpbuf *actions, char *string) if (actions) { char *act_str = strstr(string, "action"); if (!act_str) { - ovs_fatal(0, "must specify an action"); + ofp_fatal(str_, verbose, "must specify an action"); } *act_str = '\0'; act_str = strchr(act_str + 1, '='); if (!act_str) { - ovs_fatal(0, "must specify an action"); + ofp_fatal(str_, verbose, "must specify an action"); } act_str++; @@ -831,7 +846,7 @@ parse_ofp_str(struct flow_mod *fm, struct ofpbuf *actions, char *string) value = strtok_r(NULL, ", \t\r\n", &save_ptr); if (!value) { - ovs_fatal(0, "field %s missing value", name); + ofp_fatal(str_, verbose, "field %s missing value", name); } if (!strcmp(name, "table")) { @@ -875,7 +890,10 @@ parse_ofp_str(struct flow_mod *fm, struct ofpbuf *actions, char *string) && isdigit((unsigned char) name[3])) { unsigned int reg_idx = atoi(name + 3); if (reg_idx >= FLOW_N_REGS) { - ovs_fatal(0, "only %d registers supported", FLOW_N_REGS); + if (verbose) { + fprintf(stderr, "%s:\n", str_); + } + ofp_fatal(str_, verbose, "only %d registers supported", FLOW_N_REGS); } parse_reg_value(&fm->cr, reg_idx, value); } else if (!strcmp(name, "duration") @@ -885,10 +903,12 @@ parse_ofp_str(struct flow_mod *fm, struct ofpbuf *actions, char *string) * "ovs-ofctl dump-flows" back into commands that parse * flows. */ } else { - ovs_fatal(0, "unknown keyword %s", name); + ofp_fatal(str_, verbose, "unknown keyword %s", name); } } } + + free(string); } /* Parses 'string' as an OFPT_FLOW_MOD or NXT_FLOW_MOD with command 'command' @@ -899,7 +919,8 @@ parse_ofp_str(struct flow_mod *fm, struct ofpbuf *actions, char *string) * flow. */ void parse_ofp_flow_mod_str(struct list *packets, enum nx_flow_format *cur_format, - bool *flow_mod_table_id, char *string, uint16_t command) + bool *flow_mod_table_id, char *string, uint16_t command, + bool verbose) { bool is_del = command == OFPFC_DELETE || command == OFPFC_DELETE_STRICT; enum nx_flow_format min_format, next_format; @@ -909,7 +930,7 @@ parse_ofp_flow_mod_str(struct list *packets, enum nx_flow_format *cur_format, struct flow_mod fm; ofpbuf_init(&actions, 64); - parse_ofp_str(&fm, is_del ? NULL : &actions, string); + parse_ofp_str(&fm, is_del ? NULL : &actions, string, verbose); fm.command = command; min_format = ofputil_min_flow_format(&fm.cr); @@ -953,7 +974,7 @@ parse_ofp_flow_mod_file(struct list *packets, ok = ds_get_preprocessed_line(&s, stream) == 0; if (ok) { parse_ofp_flow_mod_str(packets, cur, flow_mod_table_id, - ds_cstr(&s), command); + ds_cstr(&s), command, true); } ds_destroy(&s); @@ -966,7 +987,7 @@ parse_ofp_flow_stats_request_str(struct flow_stats_request *fsr, { struct flow_mod fm; - parse_ofp_str(&fm, NULL, string); + parse_ofp_str(&fm, NULL, string, false); fsr->aggregate = aggregate; fsr->match = fm.cr; fsr->out_port = fm.out_port; diff --git a/lib/ofp-parse.h b/lib/ofp-parse.h index 820929829..d55159aa6 100644 --- a/lib/ofp-parse.h +++ b/lib/ofp-parse.h @@ -29,11 +29,12 @@ struct flow_stats_request; struct list; struct ofpbuf; -void parse_ofp_str(struct flow_mod *, struct ofpbuf *actions, char *string); +void parse_ofp_str(struct flow_mod *, struct ofpbuf *actions, const char *str_, + bool verbose); void parse_ofp_flow_mod_str(struct list *packets, enum nx_flow_format *cur, bool *flow_mod_table_id, - char *string, uint16_t command); + char *string, uint16_t command, bool verbose); bool parse_ofp_flow_mod_file(struct list *packets, enum nx_flow_format *cur, bool *flow_mod_table_id, FILE *, uint16_t command); diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 6c7e3ac10..7d3b7fbee 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -658,7 +658,7 @@ do_flow_mod__(int argc, char *argv[], uint16_t command) flow_mod_table_id = false; parse_ofp_flow_mod_str(&requests, &flow_format, &flow_mod_table_id, - argc > 2 ? argv[2] : "", command); + argc > 2 ? argv[2] : "", command, false); check_final_format_for_flow_mod(flow_format); open_vconn(argv[1], &vconn); @@ -1035,7 +1035,7 @@ read_flows_from_file(const char *filename, struct classifier *cls, int index) struct flow_mod fm; ofpbuf_init(&actions, 64); - parse_ofp_str(&fm, &actions, ds_cstr(&s)); + parse_ofp_str(&fm, &actions, ds_cstr(&s), true); version = xmalloc(sizeof *version); version->cookie = fm.cookie; @@ -1308,7 +1308,7 @@ do_parse_flow(int argc OVS_UNUSED, char *argv[]) list_init(&packets); parse_ofp_flow_mod_str(&packets, &flow_format, &flow_mod_table_id, - argv[1], OFPFC_ADD); + argv[1], OFPFC_ADD, false); print_packet_list(&packets); }