diff options
author | Ben Pfaff <blp@ovn.org> | 2017-05-31 16:06:12 -0700 |
---|---|---|
committer | Ben Pfaff <blp@ovn.org> | 2017-05-31 16:06:12 -0700 |
commit | 50f96b10e1c87db9fbe4df297f9b2fea13436bc0 (patch) | |
tree | 9122b84ecb6d90d0ba343f1f7b451b2db057870f /lib | |
parent | 52182c5f50198d0f985b10677e47a9ac49ee709b (diff) | |
download | openvswitch-50f96b10e1c87db9fbe4df297f9b2fea13436bc0.tar.gz |
Support accepting and displaying port names in OVS tools.
Until now, most ovs-ofctl commands have not accepted names for ports, only
numbers, and have not been able to display port names either. It's a lot
easier for users if they can use and see meaningful names instead of
arbitrary numbers. This commit adds that support.
For backward compatibility, only interactive ovs-ofctl commands by default
display port names; to display them in scripts, use the new --names
option.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Tested-by: Aaron Conole <aconole@redhat.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/bundle.c | 27 | ||||
-rw-r--r-- | lib/bundle.h | 12 | ||||
-rw-r--r-- | lib/classifier.c | 6 | ||||
-rw-r--r-- | lib/classifier.h | 4 | ||||
-rw-r--r-- | lib/dpctl.c | 17 | ||||
-rw-r--r-- | lib/flow.c | 15 | ||||
-rw-r--r-- | lib/flow.h | 8 | ||||
-rw-r--r-- | lib/learn.c | 22 | ||||
-rw-r--r-- | lib/learn.h | 10 | ||||
-rw-r--r-- | lib/learning-switch.c | 4 | ||||
-rw-r--r-- | lib/match.c | 43 | ||||
-rw-r--r-- | lib/meta-flow.c | 25 | ||||
-rw-r--r-- | lib/nx-match.c | 2 | ||||
-rw-r--r-- | lib/ofp-actions.c | 599 | ||||
-rw-r--r-- | lib/ofp-parse.c | 129 | ||||
-rw-r--r-- | lib/ofp-print.c | 217 | ||||
-rw-r--r-- | lib/ofp-util.c | 243 | ||||
-rw-r--r-- | lib/vconn.c | 10 |
18 files changed, 954 insertions, 439 deletions
diff --git a/lib/bundle.c b/lib/bundle.c index 1bacb3779..e6705a085 100644 --- a/lib/bundle.c +++ b/lib/bundle.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc. +/* Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -145,7 +145,8 @@ bundle_check(const struct ofpact_bundle *bundle, ofp_port_t max_ports, * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string.*/ static char * OVS_WARN_UNUSED_RESULT -bundle_parse__(const char *s, char **save_ptr, +bundle_parse__(const char *s, const struct ofputil_port_map *port_map, + char **save_ptr, const char *fields, const char *basis, const char *algorithm, const char *slave_type, const char *dst, const char *slave_delim, struct ofpbuf *ofpacts) @@ -172,7 +173,7 @@ bundle_parse__(const char *s, char **save_ptr, break; } - if (!ofputil_port_from_string(slave, &slave_port)) { + if (!ofputil_port_from_string(slave, port_map, &slave_port)) { return xasprintf("%s: bad port number", slave); } ofpbuf_put(ofpacts, &slave_port, sizeof slave_port); @@ -232,7 +233,8 @@ bundle_parse__(const char *s, char **save_ptr, * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ char * OVS_WARN_UNUSED_RESULT -bundle_parse(const char *s, struct ofpbuf *ofpacts) +bundle_parse(const char *s, const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts) { char *fields, *basis, *algorithm, *slave_type, *slave_delim; char *tokstr, *save_ptr; @@ -246,7 +248,8 @@ bundle_parse(const char *s, struct ofpbuf *ofpacts) slave_type = strtok_r(NULL, ", ", &save_ptr); slave_delim = strtok_r(NULL, ": ", &save_ptr); - error = bundle_parse__(s, &save_ptr, fields, basis, algorithm, slave_type, + error = bundle_parse__(s, port_map, + &save_ptr, fields, basis, algorithm, slave_type, NULL, slave_delim, ofpacts); free(tokstr); @@ -259,7 +262,8 @@ bundle_parse(const char *s, struct ofpbuf *ofpacts) * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string.*/ char * OVS_WARN_UNUSED_RESULT -bundle_parse_load(const char *s, struct ofpbuf *ofpacts) +bundle_parse_load(const char *s, const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts) { char *fields, *basis, *algorithm, *slave_type, *dst, *slave_delim; char *tokstr, *save_ptr; @@ -274,7 +278,8 @@ bundle_parse_load(const char *s, struct ofpbuf *ofpacts) dst = strtok_r(NULL, ", ", &save_ptr); slave_delim = strtok_r(NULL, ": ", &save_ptr); - error = bundle_parse__(s, &save_ptr, fields, basis, algorithm, slave_type, + error = bundle_parse__(s, port_map, + &save_ptr, fields, basis, algorithm, slave_type, dst, slave_delim, ofpacts); free(tokstr); @@ -282,9 +287,11 @@ bundle_parse_load(const char *s, struct ofpbuf *ofpacts) return error; } -/* Appends a human-readable representation of 'nab' to 's'. */ +/* Appends a human-readable representation of 'nab' to 's'. If 'port_map' is + * nonnull, uses it to translate port numbers to names in output. */ void -bundle_format(const struct ofpact_bundle *bundle, struct ds *s) +bundle_format(const struct ofpact_bundle *bundle, + const struct ofputil_port_map *port_map, struct ds *s) { const char *action, *fields, *algorithm; size_t i; @@ -318,7 +325,7 @@ bundle_format(const struct ofpact_bundle *bundle, struct ds *s) ds_put_char(s, ','); } - ofputil_format_port(bundle->slaves[i], s); + ofputil_format_port(bundle->slaves[i], port_map, s); } ds_put_format(s, "%s)%s", colors.paren, colors.end); diff --git a/lib/bundle.h b/lib/bundle.h index 48b9b7959..21f353f67 100644 --- a/lib/bundle.h +++ b/lib/bundle.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011, 2012, 2013, 2014 Nicira, Inc. +/* Copyright (c) 2011, 2012, 2013, 2014, 2017 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,6 +32,7 @@ struct flow_wildcards; struct match; struct ofpact_bundle; struct ofpbuf; +struct ofputil_port_map; /* NXAST_BUNDLE helper functions. * @@ -45,9 +46,12 @@ ofp_port_t bundle_execute(const struct ofpact_bundle *, const struct flow *, void *aux); enum ofperr bundle_check(const struct ofpact_bundle *, ofp_port_t max_ports, const struct match *); -char *bundle_parse(const char *, struct ofpbuf *ofpacts) OVS_WARN_UNUSED_RESULT; -char *bundle_parse_load(const char *, struct ofpbuf *ofpacts) +char *bundle_parse(const char *, const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts) OVS_WARN_UNUSED_RESULT; +char *bundle_parse_load(const char *, const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts) OVS_WARN_UNUSED_RESULT; -void bundle_format(const struct ofpact_bundle *, struct ds *); +void bundle_format(const struct ofpact_bundle *, + const struct ofputil_port_map *, struct ds *); #endif /* bundle.h */ diff --git a/lib/classifier.c b/lib/classifier.c index 782ef071e..1b652df8d 100644 --- a/lib/classifier.c +++ b/lib/classifier.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc. + * Copyright (c) 2009-2017 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -269,9 +269,9 @@ cls_rule_equal(const struct cls_rule *a, const struct cls_rule *b) /* Appends a string describing 'rule' to 's'. */ void cls_rule_format(const struct cls_rule *rule, const struct tun_table *tun_table, - struct ds *s) + const struct ofputil_port_map *port_map, struct ds *s) { - minimatch_format(&rule->match, tun_table, s, rule->priority); + minimatch_format(&rule->match, tun_table, port_map, s, rule->priority); } /* Returns true if 'rule' matches every packet, false otherwise. */ diff --git a/lib/classifier.h b/lib/classifier.h index c57fa6fc4..f0ea5a9cb 100644 --- a/lib/classifier.h +++ b/lib/classifier.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc. + * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2017 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -413,7 +413,7 @@ int classifier_count(const struct classifier *); * concurrently with modifiers and each other. */ bool cls_rule_equal(const struct cls_rule *, const struct cls_rule *); void cls_rule_format(const struct cls_rule *, const struct tun_table *, - struct ds *); + const struct ofputil_port_map *, struct ds *); bool cls_rule_is_catchall(const struct cls_rule *); bool cls_rule_is_loose_match(const struct cls_rule *rule, const struct minimatch *criteria); diff --git a/lib/dpctl.c b/lib/dpctl.c index 71bd38320..ae239134e 100644 --- a/lib/dpctl.c +++ b/lib/dpctl.c @@ -768,7 +768,6 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p) struct dpif_port_dump port_dump; struct dpif_port dpif_port; struct hmap portno_names; - struct simap names_portno; struct dpif_flow_dump_thread *flow_dump_thread; struct dpif_flow_dump *flow_dump; @@ -794,16 +793,21 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p) hmap_init(&portno_names); - simap_init(&names_portno); DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, dpif) { odp_portno_names_set(&portno_names, dpif_port.port_no, dpif_port.name); - simap_put(&names_portno, dpif_port.name, - odp_to_u32(dpif_port.port_no)); } if (filter) { - char *err = parse_ofp_exact_flow(&flow_filter, &wc_filter, NULL, filter, - &names_portno); + struct ofputil_port_map port_map; + ofputil_port_map_init(&port_map); + DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, dpif) { + ofputil_port_map_put(&port_map, + u16_to_ofp(odp_to_u32(dpif_port.port_no)), + dpif_port.name); + } + char *err = parse_ofp_exact_flow(&flow_filter, &wc_filter, NULL, + filter, &port_map); + ofputil_port_map_destroy(&port_map); if (err) { dpctl_error(dpctl_p, 0, "Failed to parse filter (%s)", err); free(err); @@ -868,7 +872,6 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p) out_dpifclose: odp_portno_names_destroy(&portno_names); - simap_destroy(&names_portno); hmap_destroy(&portno_names); dpif_close(dpif); out_freefilter: diff --git a/lib/flow.c b/lib/flow.c index 7f98a46ae..779bb54d5 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -1066,10 +1066,11 @@ flow_clear_conntrack(struct flow *flow) } char * -flow_to_string(const struct flow *flow) +flow_to_string(const struct flow *flow, + const struct ofputil_port_map *port_map) { struct ds ds = DS_EMPTY_INITIALIZER; - flow_format(&ds, flow); + flow_format(&ds, flow, port_map); return ds_cstr(&ds); } @@ -1309,7 +1310,8 @@ unknown: } void -flow_format(struct ds *ds, const struct flow *flow) +flow_format(struct ds *ds, + const struct flow *flow, const struct ofputil_port_map *port_map) { struct match match; struct flow_wildcards *wc = &match.wc; @@ -1371,13 +1373,14 @@ flow_format(struct ds *ds, const struct flow *flow) WC_UNMASK_FIELD(wc, metadata); } - match_format(&match, ds, OFP_DEFAULT_PRIORITY); + match_format(&match, port_map, ds, OFP_DEFAULT_PRIORITY); } void -flow_print(FILE *stream, const struct flow *flow) +flow_print(FILE *stream, + const struct flow *flow, const struct ofputil_port_map *port_map) { - char *s = flow_to_string(flow); + char *s = flow_to_string(flow, port_map); fputs(s, stream); free(s); } diff --git a/lib/flow.h b/lib/flow.h index 94c8a0c4e..68bd4f3c5 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -37,6 +37,7 @@ struct ds; struct flow_wildcards; struct minimask; struct dp_packet; +struct ofputil_port_map; struct pkt_metadata; struct match; @@ -76,7 +77,7 @@ const char *ct_state_to_string(uint32_t state); uint32_t ct_state_from_string(const char *); void flow_clear_conntrack(struct flow *); -char *flow_to_string(const struct flow *); +char *flow_to_string(const struct flow *, const struct ofputil_port_map *); void format_flags(struct ds *ds, const char *(*bit_to_string)(uint32_t), uint32_t flags, char del); void format_flags_masked(struct ds *ds, const char *name, @@ -86,8 +87,9 @@ int parse_flags(const char *s, const char *(*bit_to_string)(uint32_t), char end, const char *field_name, char **res_string, uint32_t *res_flags, uint32_t allowed, uint32_t *res_mask); -void flow_format(struct ds *, const struct flow *); -void flow_print(FILE *, const struct flow *); +void flow_format(struct ds *, const struct flow *, + const struct ofputil_port_map *); +void flow_print(FILE *, const struct flow *, const struct ofputil_port_map *); static inline int flow_compare_3way(const struct flow *, const struct flow *); static inline bool flow_equal(const struct flow *, const struct flow *); static inline size_t flow_hash(const struct flow *, uint32_t basis); diff --git a/lib/learn.c b/lib/learn.c index f8f872143..bc5a6eb2d 100644 --- a/lib/learn.c +++ b/lib/learn.c @@ -232,6 +232,7 @@ learn_parse_load_immediate(union mf_subvalue *imm, const char *s, * error. The caller is responsible for freeing the returned string. */ static char * OVS_WARN_UNUSED_RESULT learn_parse_spec(const char *orig, char *name, char *value, + const struct ofputil_port_map *port_map, struct ofpact_learn_spec *spec, struct ofpbuf *ofpacts, struct match *match) { @@ -262,7 +263,8 @@ learn_parse_spec(const char *orig, char *name, char *value, /* Try an immediate value. */ if (dst.ofs == 0 && dst.n_bits == dst.field->n_bits) { /* Full field value. */ - imm_error = mf_parse_value(dst.field, value, &imm); + imm_error = mf_parse_value(dst.field, value, port_map, + &imm); } else { char *tail; /* Partial field value. */ @@ -279,7 +281,7 @@ learn_parse_spec(const char *orig, char *name, char *value, struct ds ds; ds_init(&ds); - mf_format(dst.field, &imm, NULL, &ds); + mf_format(dst.field, &imm, NULL, NULL, &ds); imm_error = xasprintf("%s: value %s does not fit into %d bits", orig, ds_cstr(&ds), dst.n_bits); ds_destroy(&ds); @@ -378,7 +380,8 @@ learn_parse_spec(const char *orig, char *name, char *value, /* Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ static char * OVS_WARN_UNUSED_RESULT -learn_parse__(char *orig, char *arg, struct ofpbuf *ofpacts) +learn_parse__(char *orig, char *arg, const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts) { struct ofpact_learn *learn; struct match match; @@ -435,7 +438,8 @@ learn_parse__(char *orig, char *arg, struct ofpbuf *ofpacts) char *error; spec = ofpbuf_put_zeros(ofpacts, sizeof *spec); - error = learn_parse_spec(orig, name, value, spec, ofpacts, &match); + error = learn_parse_spec(orig, name, value, port_map, + spec, ofpacts, &match); if (error) { return error; } @@ -460,10 +464,11 @@ learn_parse__(char *orig, char *arg, struct ofpbuf *ofpacts) * * Modifies 'arg'. */ char * OVS_WARN_UNUSED_RESULT -learn_parse(char *arg, struct ofpbuf *ofpacts) +learn_parse(char *arg, const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts) { char *orig = xstrdup(arg); - char *error = learn_parse__(orig, arg, ofpacts); + char *error = learn_parse__(orig, arg, port_map, ofpacts); free(orig); return error; } @@ -471,7 +476,8 @@ learn_parse(char *arg, struct ofpbuf *ofpacts) /* Appends a description of 'learn' to 's', in the format that ovs-ofctl(8) * describes. */ void -learn_format(const struct ofpact_learn *learn, struct ds *s) +learn_format(const struct ofpact_learn *learn, + const struct ofputil_port_map *port_map, struct ds *s) { const struct ofpact_learn_spec *spec; struct match match; @@ -535,7 +541,7 @@ learn_format(const struct ofpact_learn *learn, struct ds *s) ofpact_learn_spec_imm(spec), n_bytes); ds_put_format(s, "%s%s=%s", colors.param, spec->dst.field->name, colors.end); - mf_format(spec->dst.field, &value, NULL, s); + mf_format(spec->dst.field, &value, NULL, port_map, s); } else { ds_put_format(s, "%s", colors.param); mf_format_subfield(&spec->dst, s); diff --git a/lib/learn.h b/lib/learn.h index 9dd41d379..31d3a14e8 100644 --- a/lib/learn.h +++ b/lib/learn.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, 2013, 2014 Nicira, Inc. + * Copyright (c) 2011, 2012, 2013, 2014, 2017 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,7 @@ struct match; struct ofpbuf; struct ofpact_learn; struct ofputil_flow_mod; +struct ofputil_port_map; struct nx_action_learn; /* NXAST_LEARN helper functions. @@ -39,7 +40,10 @@ void learn_execute(const struct ofpact_learn *, const struct flow *, struct ofputil_flow_mod *, struct ofpbuf *ofpacts); void learn_mask(const struct ofpact_learn *, struct flow_wildcards *); -char *learn_parse(char *, struct ofpbuf *ofpacts) OVS_WARN_UNUSED_RESULT; -void learn_format(const struct ofpact_learn *, struct ds *); +char *learn_parse(char *, const struct ofputil_port_map *, + struct ofpbuf *ofpacts) + OVS_WARN_UNUSED_RESULT; +void learn_format(const struct ofpact_learn *, + const struct ofputil_port_map *, struct ds *); #endif /* learn.h */ diff --git a/lib/learning-switch.c b/lib/learning-switch.c index 4ff4e0db3..a9cb95a57 100644 --- a/lib/learning-switch.c +++ b/lib/learning-switch.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc. + * Copyright (c) 2008-2017 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -368,7 +368,7 @@ lswitch_process_packet(struct lswitch *sw, const struct ofpbuf *msg) } else if (type == OFPTYPE_FLOW_REMOVED) { /* Nothing to do. */ } else if (VLOG_IS_DBG_ENABLED()) { - char *s = ofp_to_string(msg->data, msg->size, 2); + char *s = ofp_to_string(msg->data, msg->size, NULL, 2); VLOG_DBG_RL(&rl, "%016llx: OpenFlow packet ignored: %s", sw->datapath_id, s); free(s); diff --git a/lib/match.c b/lib/match.c index 96b1850b8..f3612c0c8 100644 --- a/lib/match.c +++ b/lib/match.c @@ -1156,9 +1156,12 @@ format_ct_label_masked(struct ds *s, const ovs_u128 *key, const ovs_u128 *mask) } /* Appends a string representation of 'match' to 's'. If 'priority' is - * different from OFP_DEFAULT_PRIORITY, includes it in 's'. */ + * different from OFP_DEFAULT_PRIORITY, includes it in 's'. If 'port_map' is + * nonnull, uses it to translate port numbers to names in output. */ void -match_format(const struct match *match, struct ds *s, int priority) +match_format(const struct match *match, + const struct ofputil_port_map *port_map, + struct ds *s, int priority) { const struct flow_wildcards *wc = &match->wc; size_t start_len = s->length; @@ -1200,7 +1203,7 @@ match_format(const struct match *match, struct ds *s, int priority) if (wc->masks.actset_output) { ds_put_format(s, "%sactset_output=%s", colors.param, colors.end); - ofputil_format_port(f->actset_output, s); + ofputil_format_port(f->actset_output, port_map, s); ds_put_char(s, ','); } @@ -1313,7 +1316,7 @@ match_format(const struct match *match, struct ds *s, int priority) if (wc->masks.in_port.ofp_port) { ds_put_format(s, "%sin_port=%s", colors.param, colors.end); - ofputil_format_port(f->in_port.ofp_port, s); + ofputil_format_port(f->in_port.ofp_port, port_map, s); ds_put_char(s, ','); } for (i = 0; i < FLOW_MAX_VLAN_HEADERS; i++) { @@ -1482,20 +1485,23 @@ match_format(const struct match *match, struct ds *s, int priority) } /* Converts 'match' to a string and returns the string. If 'priority' is - * different from OFP_DEFAULT_PRIORITY, includes it in the string. The caller - * must free the string (with free()). */ + * different from OFP_DEFAULT_PRIORITY, includes it in the string. If + * 'port_map' is nonnull, uses it to translate port numbers to names in + * output. The caller must free the string (with free()). */ char * -match_to_string(const struct match *match, int priority) +match_to_string(const struct match *match, + const struct ofputil_port_map *port_map, int priority) { struct ds s = DS_EMPTY_INITIALIZER; - match_format(match, &s, priority); + match_format(match, port_map, &s, priority); return ds_steal_cstr(&s); } void -match_print(const struct match *match) +match_print(const struct match *match, + const struct ofputil_port_map *port_map) { - char *s = match_to_string(match, OFP_DEFAULT_PRIORITY); + char *s = match_to_string(match, port_map, OFP_DEFAULT_PRIORITY); puts(s); free(s); } @@ -1586,27 +1592,32 @@ minimatch_matches_flow(const struct minimatch *match, } /* Appends a string representation of 'match' to 's'. If 'priority' is - * different from OFP_DEFAULT_PRIORITY, includes it in 's'. */ + * different from OFP_DEFAULT_PRIORITY, includes it in 's'. If 'port_map' is + * nonnull, uses it to translate port numbers to names in output. */ void minimatch_format(const struct minimatch *match, - const struct tun_table *tun_table,struct ds *s, int priority) + const struct tun_table *tun_table, + const struct ofputil_port_map *port_map, + struct ds *s, int priority) { struct match megamatch; minimatch_expand(match, &megamatch); megamatch.flow.tunnel.metadata.tab = tun_table; - match_format(&megamatch, s, priority); + match_format(&megamatch, port_map, s, priority); } /* Converts 'match' to a string and returns the string. If 'priority' is * different from OFP_DEFAULT_PRIORITY, includes it in the string. The caller - * must free the string (with free()). */ + * must free the string (with free()). If 'port_map' is nonnull, uses it to + * translate port numbers to names in output. */ char * -minimatch_to_string(const struct minimatch *match, int priority) +minimatch_to_string(const struct minimatch *match, + const struct ofputil_port_map *port_map, int priority) { struct match megamatch; minimatch_expand(match, &megamatch); - return match_to_string(&megamatch, priority); + return match_to_string(&megamatch, port_map, priority); } diff --git a/lib/meta-flow.c b/lib/meta-flow.c index b520e11c5..1c2a00874 100644 --- a/lib/meta-flow.c +++ b/lib/meta-flow.c @@ -2426,28 +2426,30 @@ mf_from_ipv6_string(const struct mf_field *mf, const char *s, static char * mf_from_ofp_port_string(const struct mf_field *mf, const char *s, + const struct ofputil_port_map *port_map, ovs_be16 *valuep, ovs_be16 *maskp) { ofp_port_t port; ovs_assert(mf->n_bytes == sizeof(ovs_be16)); - if (ofputil_port_from_string(s, &port)) { + if (ofputil_port_from_string(s, port_map, &port)) { *valuep = htons(ofp_to_u16(port)); *maskp = OVS_BE16_MAX; return NULL; } - return xasprintf("%s: port value out of range for %s", s, mf->name); + return xasprintf("%s: invalid or unknown port for %s", s, mf->name); } static char * mf_from_ofp_port_string32(const struct mf_field *mf, const char *s, + const struct ofputil_port_map *port_map, ovs_be32 *valuep, ovs_be32 *maskp) { ofp_port_t port; ovs_assert(mf->n_bytes == sizeof(ovs_be32)); - if (ofputil_port_from_string(s, &port)) { + if (ofputil_port_from_string(s, port_map, &port)) { *valuep = ofputil_port_to_ofp11(port); *maskp = OVS_BE32_MAX; return NULL; @@ -2560,6 +2562,7 @@ mf_from_ct_state_string(const char *s, ovs_be32 *flagsp, ovs_be32 *maskp) * NULL if successful, otherwise a malloc()'d string describing the error. */ char * mf_parse(const struct mf_field *mf, const char *s, + const struct ofputil_port_map *port_map, union mf_value *value, union mf_value *mask) { char *error; @@ -2595,11 +2598,13 @@ mf_parse(const struct mf_field *mf, const char *s, break; case MFS_OFP_PORT: - error = mf_from_ofp_port_string(mf, s, &value->be16, &mask->be16); + error = mf_from_ofp_port_string(mf, s, port_map, + &value->be16, &mask->be16); break; case MFS_OFP_PORT_OXM: - error = mf_from_ofp_port_string32(mf, s, &value->be32, &mask->be32); + error = mf_from_ofp_port_string32(mf, s, port_map, + &value->be32, &mask->be32); break; case MFS_FRAG: @@ -2629,12 +2634,13 @@ mf_parse(const struct mf_field *mf, const char *s, /* Parses 's', a string value for field 'mf', into 'value'. Returns NULL if * successful, otherwise a malloc()'d string describing the error. */ char * -mf_parse_value(const struct mf_field *mf, const char *s, union mf_value *value) +mf_parse_value(const struct mf_field *mf, const char *s, + const struct ofputil_port_map *port_map, union mf_value *value) { union mf_value mask; char *error; - error = mf_parse(mf, s, value, &mask); + error = mf_parse(mf, s, port_map, value, &mask); if (error) { return error; } @@ -2714,6 +2720,7 @@ mf_format_ct_state_string(ovs_be32 value, ovs_be32 mask, struct ds *s) void mf_format(const struct mf_field *mf, const union mf_value *value, const union mf_value *mask, + const struct ofputil_port_map *port_map, struct ds *s) { if (mask) { @@ -2730,13 +2737,13 @@ mf_format(const struct mf_field *mf, if (!mask) { ofp_port_t port; ofputil_port_from_ofp11(value->be32, &port); - ofputil_format_port(port, s); + ofputil_format_port(port, port_map, s); break; } /* fall through */ case MFS_OFP_PORT: if (!mask) { - ofputil_format_port(u16_to_ofp(ntohs(value->be16)), s); + ofputil_format_port(u16_to_ofp(ntohs(value->be16)), port_map, s); break; } /* fall through */ diff --git a/lib/nx-match.c b/lib/nx-match.c index 5d8aac571..490270a29 100644 --- a/lib/nx-match.c +++ b/lib/nx-match.c @@ -1260,7 +1260,7 @@ nx_format_mask_tlv(struct ds *ds, enum mf_field_id id, if (!is_all_ones(mask, mf->n_bytes)) { ds_put_char(ds, '='); - mf_format(mf, mask, NULL, ds); + mf_format(mf, mask, NULL, NULL, ds); } ds_put_char(ds, ','); diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index af52f147d..f3d3999ec 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -403,7 +403,8 @@ static void *ofpact_put_raw(struct ofpbuf *, enum ofp_version, enum ofp_raw_action_type, uint64_t arg); static char *OVS_WARN_UNUSED_RESULT ofpacts_parse( - char *str, struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols, + char *str, const struct ofputil_port_map *, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols, bool allow_instructions, enum ofpact_type outer_action); static enum ofperr ofpacts_pull_openflow_actions__( struct ofpbuf *openflow, unsigned int actions_len, @@ -411,7 +412,7 @@ static enum ofperr ofpacts_pull_openflow_actions__( struct ofpbuf *ofpacts, enum ofpact_type outer_action, const struct vl_mff_map *vl_mff_map, uint64_t *ofpacts_tlv_bitmap); static char * OVS_WARN_UNUSED_RESULT ofpacts_parse_copy( - const char *s_, struct ofpbuf *ofpacts, + const char *s_, const struct ofputil_port_map *, struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols, bool allow_instructions, enum ofpact_type outer_action); @@ -589,14 +590,16 @@ encode_OUTPUT(const struct ofpact_output *output, static char * OVS_WARN_UNUSED_RESULT parse_truncate_subfield(struct ofpact_output_trunc *output_trunc, - const char *arg_) + const char *arg_, + const struct ofputil_port_map *port_map) { char *key, *value; char *arg = CONST_CAST(char *, arg_); while (ofputil_parse_key_value(&arg, &key, &value)) { if (!strcmp(key, "port")) { - if (!ofputil_port_from_string(value, &output_trunc->port)) { + if (!ofputil_port_from_string(value, port_map, + &output_trunc->port)) { return xasprintf("output to unknown truncate port: %s", value); } @@ -622,14 +625,16 @@ parse_truncate_subfield(struct ofpact_output_trunc *output_trunc, } static char * OVS_WARN_UNUSED_RESULT -parse_OUTPUT(const char *arg, struct ofpbuf *ofpacts, +parse_OUTPUT(const char *arg, + const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { if (strstr(arg, "port") && strstr(arg, "max_len")) { struct ofpact_output_trunc *output_trunc; output_trunc = ofpact_put_OUTPUT_TRUNC(ofpacts); - return parse_truncate_subfield(output_trunc, arg); + return parse_truncate_subfield(output_trunc, arg, port_map); } else { struct mf_subfield src; char *error = mf_parse_subfield(&src, arg); @@ -644,7 +649,7 @@ parse_OUTPUT(const char *arg, struct ofpbuf *ofpacts, struct ofpact_output *output; output = ofpact_put_OUTPUT(ofpacts); - if (!ofputil_port_from_string(arg, &output->port)) { + if (!ofputil_port_from_string(arg, port_map, &output->port)) { return xasprintf("%s: output to unknown port", arg); } output->max_len = output->port == OFPP_CONTROLLER ? UINT16_MAX : 0; @@ -654,16 +659,15 @@ parse_OUTPUT(const char *arg, struct ofpbuf *ofpacts, } static void -format_OUTPUT(const struct ofpact_output *a, struct ds *s) +format_OUTPUT(const struct ofpact_output *a, + const struct ofputil_port_map *port_map, struct ds *s) { if (ofp_to_u16(a->port) < ofp_to_u16(OFPP_MAX)) { - ds_put_format(s, "%soutput:%s%"PRIu32, - colors.special, colors.end, a->port); - } else { - ofputil_format_port(a->port, s); - if (a->port == OFPP_CONTROLLER) { - ds_put_format(s, ":%"PRIu16, a->max_len); - } + ds_put_format(s, "%soutput:%s", colors.special, colors.end); + } + ofputil_format_port(a->port, port_map, s); + if (a->port == OFPP_CONTROLLER) { + ds_put_format(s, ":%"PRIu16, a->max_len); } } @@ -686,14 +690,18 @@ encode_GROUP(const struct ofpact_group *group, } static char * OVS_WARN_UNUSED_RESULT -parse_GROUP(char *arg, struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_GROUP(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, + enum ofputil_protocol *usable_protocols OVS_UNUSED) { return str_to_u32(arg, &ofpact_put_GROUP(ofpacts)->group_id); } static void -format_GROUP(const struct ofpact_group *a, struct ds *s) +format_GROUP(const struct ofpact_group *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%sgroup:%s%"PRIu32, colors.special, colors.end, a->group_id); @@ -863,8 +871,10 @@ encode_CONTROLLER(const struct ofpact_controller *controller, } static char * OVS_WARN_UNUSED_RESULT -parse_CONTROLLER(char *arg, struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_CONTROLLER(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, + enum ofputil_protocol *usable_protocols OVS_UNUSED) { enum ofp_packet_in_reason reason = OFPR_ACTION; uint16_t controller_id = 0; @@ -952,7 +962,9 @@ format_hex_arg(struct ds *s, const uint8_t *data, size_t len) } static void -format_CONTROLLER(const struct ofpact_controller *a, struct ds *s) +format_CONTROLLER(const struct ofpact_controller *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { if (a->reason == OFPR_ACTION && !a->controller_id && !a->userdata_len && !a->pause) { @@ -1042,7 +1054,9 @@ encode_ENQUEUE(const struct ofpact_enqueue *enqueue, } static char * OVS_WARN_UNUSED_RESULT -parse_ENQUEUE(char *arg, struct ofpbuf *ofpacts, +parse_ENQUEUE(char *arg, + const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { char *sp = NULL; @@ -1056,17 +1070,18 @@ parse_ENQUEUE(char *arg, struct ofpbuf *ofpacts, } enqueue = ofpact_put_ENQUEUE(ofpacts); - if (!ofputil_port_from_string(port, &enqueue->port)) { + if (!ofputil_port_from_string(port, port_map, &enqueue->port)) { return xasprintf("%s: enqueue to unknown port", port); } return str_to_u32(queue, &enqueue->queue); } static void -format_ENQUEUE(const struct ofpact_enqueue *a, struct ds *s) +format_ENQUEUE(const struct ofpact_enqueue *a, + const struct ofputil_port_map *port_map, struct ds *s) { ds_put_format(s, "%senqueue:%s", colors.param, colors.end); - ofputil_format_port(a->port, s); + ofputil_format_port(a->port, port_map, s); ds_put_format(s, ":%"PRIu32, a->queue); } @@ -1210,14 +1225,18 @@ encode_OUTPUT_REG(const struct ofpact_output_reg *output_reg, } static char * OVS_WARN_UNUSED_RESULT -parse_OUTPUT_REG(const char *arg, struct ofpbuf *ofpacts, +parse_OUTPUT_REG(const char *arg, + const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { - return parse_OUTPUT(arg, ofpacts, usable_protocols); + return parse_OUTPUT(arg, port_map, ofpacts, usable_protocols); } static void -format_OUTPUT_REG(const struct ofpact_output_reg *a, struct ds *s) +format_OUTPUT_REG(const struct ofpact_output_reg *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%soutput:%s", colors.special, colors.end); mf_format_subfield(&a->src, s); @@ -1423,22 +1442,25 @@ encode_BUNDLE(const struct ofpact_bundle *bundle, } static char * OVS_WARN_UNUSED_RESULT -parse_BUNDLE(const char *arg, struct ofpbuf *ofpacts, +parse_BUNDLE(const char *arg, const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { - return bundle_parse(arg, ofpacts); + return bundle_parse(arg, port_map, ofpacts); } static char * OVS_WARN_UNUSED_RESULT -parse_bundle_load(const char *arg, struct ofpbuf *ofpacts) +parse_bundle_load(const char *arg, const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts) { - return bundle_parse_load(arg, ofpacts); + return bundle_parse_load(arg, port_map, ofpacts); } static void -format_BUNDLE(const struct ofpact_bundle *a, struct ds *s) +format_BUNDLE(const struct ofpact_bundle *a, + const struct ofputil_port_map *port_map, struct ds *s) { - bundle_format(a, s); + bundle_format(a, port_map, s); } /* Set VLAN actions. */ @@ -1496,7 +1518,8 @@ encode_SET_VLAN_VID(const struct ofpact_vlan_vid *vlan_vid, } static char * OVS_WARN_UNUSED_RESULT -parse_set_vlan_vid(char *arg, struct ofpbuf *ofpacts, bool push_vlan_if_needed) +parse_set_vlan_vid(char *arg, + struct ofpbuf *ofpacts, bool push_vlan_if_needed) { struct ofpact_vlan_vid *vlan_vid; uint16_t vid; @@ -1517,14 +1540,18 @@ parse_set_vlan_vid(char *arg, struct ofpbuf *ofpacts, bool push_vlan_if_needed) } static char * OVS_WARN_UNUSED_RESULT -parse_SET_VLAN_VID(char *arg, struct ofpbuf *ofpacts, +parse_SET_VLAN_VID(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { return parse_set_vlan_vid(arg, ofpacts, false); } static void -format_SET_VLAN_VID(const struct ofpact_vlan_vid *a, struct ds *s) +format_SET_VLAN_VID(const struct ofpact_vlan_vid *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%s%s:%s%"PRIu16, colors.param, a->push_vlan_if_needed ? "mod_vlan_vid" : "set_vlan_vid", @@ -1586,7 +1613,8 @@ encode_SET_VLAN_PCP(const struct ofpact_vlan_pcp *vlan_pcp, } static char * OVS_WARN_UNUSED_RESULT -parse_set_vlan_pcp(char *arg, struct ofpbuf *ofpacts, bool push_vlan_if_needed) +parse_set_vlan_pcp(char *arg, + struct ofpbuf *ofpacts, bool push_vlan_if_needed) { struct ofpact_vlan_pcp *vlan_pcp; uint8_t pcp; @@ -1607,14 +1635,18 @@ parse_set_vlan_pcp(char *arg, struct ofpbuf *ofpacts, bool push_vlan_if_needed) } static char * OVS_WARN_UNUSED_RESULT -parse_SET_VLAN_PCP(char *arg, struct ofpbuf *ofpacts, +parse_SET_VLAN_PCP(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { return parse_set_vlan_pcp(arg, ofpacts, false); } static void -format_SET_VLAN_PCP(const struct ofpact_vlan_pcp *a, struct ds *s) +format_SET_VLAN_PCP(const struct ofpact_vlan_pcp *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%s%s:%s%"PRIu8, colors.param, a->push_vlan_if_needed ? "mod_vlan_pcp" : "set_vlan_pcp", @@ -1649,7 +1681,9 @@ encode_STRIP_VLAN(const struct ofpact_null *null OVS_UNUSED, } static char * OVS_WARN_UNUSED_RESULT -parse_STRIP_VLAN(char *arg OVS_UNUSED, struct ofpbuf *ofpacts, +parse_STRIP_VLAN(char *arg OVS_UNUSED, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { ofpact_put_STRIP_VLAN(ofpacts)->ofpact.raw = OFPAT_RAW10_STRIP_VLAN; @@ -1664,7 +1698,9 @@ parse_pop_vlan(struct ofpbuf *ofpacts) } static void -format_STRIP_VLAN(const struct ofpact_null *a, struct ds *s) +format_STRIP_VLAN(const struct ofpact_null *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, (a->ofpact.raw == OFPAT_RAW11_POP_VLAN ? "%spop_vlan%s" @@ -1701,7 +1737,9 @@ encode_PUSH_VLAN(const struct ofpact_push_vlan *push_vlan, } static char * OVS_WARN_UNUSED_RESULT -parse_PUSH_VLAN(char *arg, struct ofpbuf *ofpacts, +parse_PUSH_VLAN(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { struct ofpact_push_vlan *push_vlan; @@ -1723,7 +1761,9 @@ parse_PUSH_VLAN(char *arg, struct ofpbuf *ofpacts, } static void -format_PUSH_VLAN(const struct ofpact_push_vlan *push_vlan, struct ds *s) +format_PUSH_VLAN(const struct ofpact_push_vlan *push_vlan, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%spush_vlan:%s%#"PRIx16, colors.param, colors.end, ntohs(push_vlan->ethertype)); @@ -1791,28 +1831,36 @@ encode_SET_ETH_DST(const struct ofpact_mac *mac, } static char * OVS_WARN_UNUSED_RESULT -parse_SET_ETH_SRC(char *arg, struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_SET_ETH_SRC(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, + enum ofputil_protocol *usable_protocols OVS_UNUSED) { return str_to_mac(arg, &ofpact_put_SET_ETH_SRC(ofpacts)->mac); } static char * OVS_WARN_UNUSED_RESULT -parse_SET_ETH_DST(char *arg, struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_SET_ETH_DST(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, + enum ofputil_protocol *usable_protocols OVS_UNUSED) { return str_to_mac(arg, &ofpact_put_SET_ETH_DST(ofpacts)->mac); } static void -format_SET_ETH_SRC(const struct ofpact_mac *a, struct ds *s) +format_SET_ETH_SRC(const struct ofpact_mac *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%smod_dl_src:%s"ETH_ADDR_FMT, colors.param, colors.end, ETH_ADDR_ARGS(a->mac)); } static void -format_SET_ETH_DST(const struct ofpact_mac *a, struct ds *s) +format_SET_ETH_DST(const struct ofpact_mac *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%smod_dl_dst:%s"ETH_ADDR_FMT, colors.param, colors.end, ETH_ADDR_ARGS(a->mac)); @@ -1869,28 +1917,36 @@ encode_SET_IPV4_DST(const struct ofpact_ipv4 *ipv4, } static char * OVS_WARN_UNUSED_RESULT -parse_SET_IPV4_SRC(char *arg, struct ofpbuf *ofpacts, +parse_SET_IPV4_SRC(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { return str_to_ip(arg, &ofpact_put_SET_IPV4_SRC(ofpacts)->ipv4); } static char * OVS_WARN_UNUSED_RESULT -parse_SET_IPV4_DST(char *arg, struct ofpbuf *ofpacts, +parse_SET_IPV4_DST(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { return str_to_ip(arg, &ofpact_put_SET_IPV4_DST(ofpacts)->ipv4); } static void -format_SET_IPV4_SRC(const struct ofpact_ipv4 *a, struct ds *s) +format_SET_IPV4_SRC(const struct ofpact_ipv4 *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%smod_nw_src:%s"IP_FMT, colors.param, colors.end, IP_ARGS(a->ipv4)); } static void -format_SET_IPV4_DST(const struct ofpact_ipv4 *a, struct ds *s) +format_SET_IPV4_DST(const struct ofpact_ipv4 *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%smod_nw_dst:%s"IP_FMT, colors.param, colors.end, IP_ARGS(a->ipv4)); @@ -1923,8 +1979,10 @@ encode_SET_IP_DSCP(const struct ofpact_dscp *dscp, } static char * OVS_WARN_UNUSED_RESULT -parse_SET_IP_DSCP(char *arg, struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_SET_IP_DSCP(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, + enum ofputil_protocol *usable_protocols OVS_UNUSED) { uint8_t tos; char *error; @@ -1942,7 +2000,9 @@ parse_SET_IP_DSCP(char *arg, struct ofpbuf *ofpacts, } static void -format_SET_IP_DSCP(const struct ofpact_dscp *a, struct ds *s) +format_SET_IP_DSCP(const struct ofpact_dscp *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%smod_nw_tos:%s%d", colors.param, colors.end, a->dscp); } @@ -1979,7 +2039,9 @@ encode_SET_IP_ECN(const struct ofpact_ecn *ip_ecn, } static char * OVS_WARN_UNUSED_RESULT -parse_SET_IP_ECN(char *arg, struct ofpbuf *ofpacts, +parse_SET_IP_ECN(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { uint8_t ecn; @@ -1998,7 +2060,9 @@ parse_SET_IP_ECN(char *arg, struct ofpbuf *ofpacts, } static void -format_SET_IP_ECN(const struct ofpact_ecn *a, struct ds *s) +format_SET_IP_ECN(const struct ofpact_ecn *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%smod_nw_ecn:%s%d", colors.param, colors.end, a->ecn); @@ -2029,8 +2093,10 @@ encode_SET_IP_TTL(const struct ofpact_ip_ttl *ttl, } static char * OVS_WARN_UNUSED_RESULT -parse_SET_IP_TTL(char *arg, struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_SET_IP_TTL(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, + enum ofputil_protocol *usable_protocols OVS_UNUSED) { uint8_t ttl; char *error; @@ -2045,7 +2111,9 @@ parse_SET_IP_TTL(char *arg, struct ofpbuf *ofpacts, } static void -format_SET_IP_TTL(const struct ofpact_ip_ttl *a, struct ds *s) +format_SET_IP_TTL(const struct ofpact_ip_ttl *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%smod_nw_ttl:%s%d", colors.param, colors.end, a->ttl); } @@ -2112,7 +2180,9 @@ encode_SET_L4_DST_PORT(const struct ofpact_l4_port *l4_port, } static char * OVS_WARN_UNUSED_RESULT -parse_SET_L4_SRC_PORT(char *arg, struct ofpbuf *ofpacts, +parse_SET_L4_SRC_PORT(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { return str_to_u16(arg, "source port", @@ -2120,7 +2190,9 @@ parse_SET_L4_SRC_PORT(char *arg, struct ofpbuf *ofpacts, } static char * OVS_WARN_UNUSED_RESULT -parse_SET_L4_DST_PORT(char *arg, struct ofpbuf *ofpacts, +parse_SET_L4_DST_PORT(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { return str_to_u16(arg, "destination port", @@ -2128,13 +2200,17 @@ parse_SET_L4_DST_PORT(char *arg, struct ofpbuf *ofpacts, } static void -format_SET_L4_SRC_PORT(const struct ofpact_l4_port *a, struct ds *s) +format_SET_L4_SRC_PORT(const struct ofpact_l4_port *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%smod_tp_src:%s%d", colors.param, colors.end, a->port); } static void -format_SET_L4_DST_PORT(const struct ofpact_l4_port *a, struct ds *s) +format_SET_L4_DST_PORT(const struct ofpact_l4_port *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%smod_tp_dst:%s%d", colors.param, colors.end, a->port); } @@ -2424,7 +2500,9 @@ encode_REG_MOVE(const struct ofpact_reg_move *move, } static char * OVS_WARN_UNUSED_RESULT -parse_REG_MOVE(const char *arg, struct ofpbuf *ofpacts, +parse_REG_MOVE(const char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { struct ofpact_reg_move *move = ofpact_put_REG_MOVE(ofpacts); @@ -2432,7 +2510,9 @@ parse_REG_MOVE(const char *arg, struct ofpbuf *ofpacts, } static void -format_REG_MOVE(const struct ofpact_reg_move *a, struct ds *s) +format_REG_MOVE(const struct ofpact_reg_move *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { nxm_format_reg_move(a, s); } @@ -2544,7 +2624,7 @@ decode_ofpat_set_field(const struct ofp12_action_set_field *oasf, && (!(mask.be16 & htons(OFPVID12_PRESENT)) || !(value.be16 & htons(OFPVID12_PRESENT))))) { struct ds ds = DS_EMPTY_INITIALIZER; - mf_format(field, &value, NULL, &ds); + mf_format(field, &value, NULL, NULL, &ds); VLOG_WARN_RL(&rl, "Invalid value for set field %s: %s", field->name, ds_cstr(&ds)); ds_destroy(&ds); @@ -2932,7 +3012,8 @@ set_field_split_str(char *arg, char **key, char **value, char **delim) * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ static char * OVS_WARN_UNUSED_RESULT -set_field_parse__(char *arg, struct ofpbuf *ofpacts, +set_field_parse__(char *arg, const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols) { char *value; @@ -2956,7 +3037,7 @@ set_field_parse__(char *arg, struct ofpbuf *ofpacts, } delim[0] = '\0'; - error = mf_parse(mf, value, &sf_value, &sf_mask); + error = mf_parse(mf, value, port_map, &sf_value, &sf_mask); if (error) { return error; } @@ -2977,11 +3058,12 @@ set_field_parse__(char *arg, struct ofpbuf *ofpacts, * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ static char * OVS_WARN_UNUSED_RESULT -parse_SET_FIELD(const char *arg, struct ofpbuf *ofpacts, +parse_SET_FIELD(const char *arg, const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols) { char *copy = xstrdup(arg); - char *error = set_field_parse__(copy, ofpacts, usable_protocols); + char *error = set_field_parse__(copy, port_map, ofpacts, usable_protocols); free(copy); return error; } @@ -3014,7 +3096,7 @@ parse_reg_load(char *arg, struct ofpbuf *ofpacts) struct ds ds; ds_init(&ds); - mf_format(dst.field, &value, NULL, &ds); + mf_format(dst.field, &value, NULL, NULL, &ds); error = xasprintf("%s: value %s does not fit into %d bits", arg, ds_cstr(&ds), dst.n_bits); ds_destroy(&ds); @@ -3032,7 +3114,9 @@ parse_reg_load(char *arg, struct ofpbuf *ofpacts) } static void -format_SET_FIELD(const struct ofpact_set_field *a, struct ds *s) +format_SET_FIELD(const struct ofpact_set_field *a, + const struct ofputil_port_map *port_map, + struct ds *s) { if (a->ofpact.raw == NXAST_RAW_REG_LOAD) { struct mf_subfield dst; @@ -3049,7 +3133,7 @@ format_SET_FIELD(const struct ofpact_set_field *a, struct ds *s) ds_chomp(s, ','); } else { ds_put_format(s, "%sset_field:%s", colors.special, colors.end); - mf_format(a->field, a->value, ofpact_set_field_mask(a), s); + mf_format(a->field, a->value, ofpact_set_field_mask(a), port_map, s); ds_put_format(s, "%s->%s%s", colors.special, colors.end, a->field->name); } @@ -3215,27 +3299,35 @@ encode_STACK_POP(const struct ofpact_stack *stack, } static char * OVS_WARN_UNUSED_RESULT -parse_STACK_PUSH(char *arg, struct ofpbuf *ofpacts, +parse_STACK_PUSH(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { return nxm_parse_stack_action(ofpact_put_STACK_PUSH(ofpacts), arg); } static char * OVS_WARN_UNUSED_RESULT -parse_STACK_POP(char *arg, struct ofpbuf *ofpacts, +parse_STACK_POP(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { return nxm_parse_stack_action(ofpact_put_STACK_POP(ofpacts), arg); } static void -format_STACK_PUSH(const struct ofpact_stack *a, struct ds *s) +format_STACK_PUSH(const struct ofpact_stack *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { nxm_format_stack_push(a, s); } static void -format_STACK_POP(const struct ofpact_stack *a, struct ds *s) +format_STACK_POP(const struct ofpact_stack *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { nxm_format_stack_pop(a, s); } @@ -3358,7 +3450,9 @@ parse_noargs_dec_ttl(struct ofpbuf *ofpacts) } static char * OVS_WARN_UNUSED_RESULT -parse_DEC_TTL(char *arg, struct ofpbuf *ofpacts, +parse_DEC_TTL(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { if (*arg == '\0') { @@ -3387,7 +3481,9 @@ parse_DEC_TTL(char *arg, struct ofpbuf *ofpacts, } static void -format_DEC_TTL(const struct ofpact_cnt_ids *a, struct ds *s) +format_DEC_TTL(const struct ofpact_cnt_ids *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { size_t i; @@ -3428,7 +3524,9 @@ encode_SET_MPLS_LABEL(const struct ofpact_mpls_label *label, } static char * OVS_WARN_UNUSED_RESULT -parse_SET_MPLS_LABEL(char *arg, struct ofpbuf *ofpacts, +parse_SET_MPLS_LABEL(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { struct ofpact_mpls_label *mpls_label = ofpact_put_SET_MPLS_LABEL(ofpacts); @@ -3441,7 +3539,9 @@ parse_SET_MPLS_LABEL(char *arg, struct ofpbuf *ofpacts, } static void -format_SET_MPLS_LABEL(const struct ofpact_mpls_label *a, struct ds *s) +format_SET_MPLS_LABEL(const struct ofpact_mpls_label *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%sset_mpls_label(%s%"PRIu32"%s)%s", colors.paren, colors.end, ntohl(a->label), @@ -3471,7 +3571,9 @@ encode_SET_MPLS_TC(const struct ofpact_mpls_tc *tc, } static char * OVS_WARN_UNUSED_RESULT -parse_SET_MPLS_TC(char *arg, struct ofpbuf *ofpacts, +parse_SET_MPLS_TC(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { struct ofpact_mpls_tc *mpls_tc = ofpact_put_SET_MPLS_TC(ofpacts); @@ -3485,7 +3587,9 @@ parse_SET_MPLS_TC(char *arg, struct ofpbuf *ofpacts, } static void -format_SET_MPLS_TC(const struct ofpact_mpls_tc *a, struct ds *s) +format_SET_MPLS_TC(const struct ofpact_mpls_tc *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%sset_mpls_ttl(%s%"PRIu8"%s)%s", colors.paren, colors.end, a->tc, @@ -3516,7 +3620,9 @@ encode_SET_MPLS_TTL(const struct ofpact_mpls_ttl *ttl, * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ static char * OVS_WARN_UNUSED_RESULT -parse_SET_MPLS_TTL(char *arg, struct ofpbuf *ofpacts, +parse_SET_MPLS_TTL(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { struct ofpact_mpls_ttl *mpls_ttl = ofpact_put_SET_MPLS_TTL(ofpacts); @@ -3530,7 +3636,9 @@ parse_SET_MPLS_TTL(char *arg, struct ofpbuf *ofpacts, } static void -format_SET_MPLS_TTL(const struct ofpact_mpls_ttl *a, struct ds *s) +format_SET_MPLS_TTL(const struct ofpact_mpls_ttl *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%sset_mpls_ttl(%s%"PRIu8"%s)%s", colors.paren, colors.end, a->ttl, @@ -3554,7 +3662,9 @@ encode_DEC_MPLS_TTL(const struct ofpact_null *null OVS_UNUSED, } static char * OVS_WARN_UNUSED_RESULT -parse_DEC_MPLS_TTL(char *arg OVS_UNUSED, struct ofpbuf *ofpacts, +parse_DEC_MPLS_TTL(char *arg OVS_UNUSED, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { ofpact_put_DEC_MPLS_TTL(ofpacts); @@ -3562,7 +3672,9 @@ parse_DEC_MPLS_TTL(char *arg OVS_UNUSED, struct ofpbuf *ofpacts, } static void -format_DEC_MPLS_TTL(const struct ofpact_null *a OVS_UNUSED, struct ds *s) +format_DEC_MPLS_TTL(const struct ofpact_null *a OVS_UNUSED, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%sdec_mpls_ttl%s", colors.value, colors.end); } @@ -3593,7 +3705,9 @@ encode_PUSH_MPLS(const struct ofpact_push_mpls *push_mpls, } static char * OVS_WARN_UNUSED_RESULT -parse_PUSH_MPLS(char *arg, struct ofpbuf *ofpacts, +parse_PUSH_MPLS(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { uint16_t ethertype; @@ -3607,7 +3721,9 @@ parse_PUSH_MPLS(char *arg, struct ofpbuf *ofpacts, } static void -format_PUSH_MPLS(const struct ofpact_push_mpls *a, struct ds *s) +format_PUSH_MPLS(const struct ofpact_push_mpls *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%spush_mpls:%s0x%04"PRIx16, colors.param, colors.end, ntohs(a->ethertype)); @@ -3632,8 +3748,10 @@ encode_POP_MPLS(const struct ofpact_pop_mpls *pop_mpls, } static char * OVS_WARN_UNUSED_RESULT -parse_POP_MPLS(char *arg, struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_POP_MPLS(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, + enum ofputil_protocol *usable_protocols OVS_UNUSED) { uint16_t ethertype; char *error; @@ -3646,7 +3764,9 @@ parse_POP_MPLS(char *arg, struct ofpbuf *ofpacts, } static void -format_POP_MPLS(const struct ofpact_pop_mpls *a, struct ds *s) +format_POP_MPLS(const struct ofpact_pop_mpls *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%spop_mpls:%s0x%04"PRIx16, colors.param, colors.end, ntohs(a->ethertype)); @@ -3706,14 +3826,18 @@ parse_set_tunnel(char *arg, struct ofpbuf *ofpacts, } static char * OVS_WARN_UNUSED_RESULT -parse_SET_TUNNEL(char *arg, struct ofpbuf *ofpacts, +parse_SET_TUNNEL(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { return parse_set_tunnel(arg, ofpacts, NXAST_RAW_SET_TUNNEL); } static void -format_SET_TUNNEL(const struct ofpact_tunnel *a, struct ds *s) +format_SET_TUNNEL(const struct ofpact_tunnel *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%sset_tunnel%s:%s%#"PRIx64, colors.param, (a->tun_id > UINT32_MAX @@ -3740,14 +3864,18 @@ encode_SET_QUEUE(const struct ofpact_queue *queue, } static char * OVS_WARN_UNUSED_RESULT -parse_SET_QUEUE(char *arg, struct ofpbuf *ofpacts, +parse_SET_QUEUE(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { return str_to_u32(arg, &ofpact_put_SET_QUEUE(ofpacts)->queue_id); } static void -format_SET_QUEUE(const struct ofpact_queue *a, struct ds *s) +format_SET_QUEUE(const struct ofpact_queue *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%sset_queue:%s%"PRIu32, colors.param, colors.end, a->queue_id); @@ -3770,7 +3898,9 @@ encode_POP_QUEUE(const struct ofpact_null *null OVS_UNUSED, } static char * OVS_WARN_UNUSED_RESULT -parse_POP_QUEUE(const char *arg OVS_UNUSED, struct ofpbuf *ofpacts, +parse_POP_QUEUE(const char *arg OVS_UNUSED, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { ofpact_put_POP_QUEUE(ofpacts); @@ -3778,7 +3908,9 @@ parse_POP_QUEUE(const char *arg OVS_UNUSED, struct ofpbuf *ofpacts, } static void -format_POP_QUEUE(const struct ofpact_null *a OVS_UNUSED, struct ds *s) +format_POP_QUEUE(const struct ofpact_null *a OVS_UNUSED, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%spop_queue%s", colors.value, colors.end); } @@ -3841,7 +3973,9 @@ encode_FIN_TIMEOUT(const struct ofpact_fin_timeout *fin_timeout, } static char * OVS_WARN_UNUSED_RESULT -parse_FIN_TIMEOUT(char *arg, struct ofpbuf *ofpacts, +parse_FIN_TIMEOUT(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { struct ofpact_fin_timeout *oft = ofpact_put_FIN_TIMEOUT(ofpacts); @@ -3867,7 +4001,9 @@ parse_FIN_TIMEOUT(char *arg, struct ofpbuf *ofpacts, } static void -format_FIN_TIMEOUT(const struct ofpact_fin_timeout *a, struct ds *s) +format_FIN_TIMEOUT(const struct ofpact_fin_timeout *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%sfin_timeout(%s", colors.paren, colors.end); if (a->fin_idle_timeout) { @@ -4025,7 +4161,9 @@ encode_RESUBMIT(const struct ofpact_resubmit *resubmit, } static char * OVS_WARN_UNUSED_RESULT -parse_RESUBMIT(char *arg, struct ofpbuf *ofpacts, +parse_RESUBMIT(char *arg, + const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { struct ofpact_resubmit *resubmit; @@ -4035,7 +4173,8 @@ parse_RESUBMIT(char *arg, struct ofpbuf *ofpacts, in_port_s = strsep(&arg, ","); if (in_port_s && in_port_s[0]) { - if (!ofputil_port_from_string(in_port_s, &resubmit->in_port)) { + if (!ofputil_port_from_string(in_port_s, port_map, + &resubmit->in_port)) { return xasprintf("%s: resubmit to unknown port", in_port_s); } } else { @@ -4074,15 +4213,16 @@ parse_RESUBMIT(char *arg, struct ofpbuf *ofpacts, } static void -format_RESUBMIT(const struct ofpact_resubmit *a, struct ds *s) +format_RESUBMIT(const struct ofpact_resubmit *a, + const struct ofputil_port_map *port_map, struct ds *s) { if (a->in_port != OFPP_IN_PORT && a->table_id == 255) { ds_put_format(s, "%sresubmit:%s", colors.special, colors.end); - ofputil_format_port(a->in_port, s); + ofputil_format_port(a->in_port, port_map, s); } else { ds_put_format(s, "%sresubmit(%s", colors.paren, colors.end); if (a->in_port != OFPP_IN_PORT) { - ofputil_format_port(a->in_port, s); + ofputil_format_port(a->in_port, port_map, s); } ds_put_char(s, ','); if (a->table_id != 255) { @@ -4665,16 +4805,18 @@ encode_LEARN(const struct ofpact_learn *learn, } static char * OVS_WARN_UNUSED_RESULT -parse_LEARN(char *arg, struct ofpbuf *ofpacts, +parse_LEARN(char *arg, const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { - return learn_parse(arg, ofpacts); + return learn_parse(arg, port_map, ofpacts); } static void -format_LEARN(const struct ofpact_learn *a, struct ds *s) +format_LEARN(const struct ofpact_learn *a, + const struct ofputil_port_map *port_map, struct ds *s) { - learn_format(a, s); + learn_format(a, port_map, s); } /* Action structure for NXAST_CONJUNCTION. */ @@ -4726,7 +4868,9 @@ encode_CONJUNCTION(const struct ofpact_conjunction *oc, } static void -format_CONJUNCTION(const struct ofpact_conjunction *oc, struct ds *s) +format_CONJUNCTION(const struct ofpact_conjunction *oc, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%sconjunction(%s%"PRIu32",%d/%"PRIu8"%s)%s", colors.paren, colors.end, @@ -4735,7 +4879,9 @@ format_CONJUNCTION(const struct ofpact_conjunction *oc, struct ds *s) } static char * OVS_WARN_UNUSED_RESULT -parse_CONJUNCTION(const char *arg, struct ofpbuf *ofpacts, +parse_CONJUNCTION(const char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { uint8_t n_clauses; @@ -4878,14 +5024,18 @@ encode_MULTIPATH(const struct ofpact_multipath *mp, } static char * OVS_WARN_UNUSED_RESULT -parse_MULTIPATH(const char *arg, struct ofpbuf *ofpacts, +parse_MULTIPATH(const char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { return multipath_parse(ofpact_put_MULTIPATH(ofpacts), arg); } static void -format_MULTIPATH(const struct ofpact_multipath *a, struct ds *s) +format_MULTIPATH(const struct ofpact_multipath *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { multipath_format(a, s); } @@ -4941,7 +5091,9 @@ encode_NOTE(const struct ofpact_note *note, } static char * OVS_WARN_UNUSED_RESULT -parse_NOTE(const char *arg, struct ofpbuf *ofpacts, +parse_NOTE(const char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { size_t start_ofs = ofpacts->size; @@ -4958,7 +5110,8 @@ parse_NOTE(const char *arg, struct ofpbuf *ofpacts, } static void -format_NOTE(const struct ofpact_note *a, struct ds *s) +format_NOTE(const struct ofpact_note *a, + const struct ofputil_port_map *port_map OVS_UNUSED, struct ds *s) { ds_put_format(s, "%snote:%s", colors.param, colors.end); format_hex_arg(s, a->data, a->length); @@ -4981,7 +5134,9 @@ encode_EXIT(const struct ofpact_null *null OVS_UNUSED, } static char * OVS_WARN_UNUSED_RESULT -parse_EXIT(char *arg OVS_UNUSED, struct ofpbuf *ofpacts, +parse_EXIT(char *arg OVS_UNUSED, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { ofpact_put_EXIT(ofpacts); @@ -4989,7 +5144,8 @@ parse_EXIT(char *arg OVS_UNUSED, struct ofpbuf *ofpacts, } static void -format_EXIT(const struct ofpact_null *a OVS_UNUSED, struct ds *s) +format_EXIT(const struct ofpact_null *a OVS_UNUSED, + const struct ofputil_port_map *port_map OVS_UNUSED, struct ds *s) { ds_put_format(s, "%sexit%s", colors.special, colors.end); } @@ -5005,7 +5161,9 @@ encode_UNROLL_XLATE(const struct ofpact_unroll_xlate *unroll OVS_UNUSED, } static char * OVS_WARN_UNUSED_RESULT -parse_UNROLL_XLATE(char *arg OVS_UNUSED, struct ofpbuf *ofpacts OVS_UNUSED, +parse_UNROLL_XLATE(char *arg OVS_UNUSED, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts OVS_UNUSED, enum ofputil_protocol *usable_protocols OVS_UNUSED) { OVS_NOT_REACHED(); @@ -5013,7 +5171,9 @@ parse_UNROLL_XLATE(char *arg OVS_UNUSED, struct ofpbuf *ofpacts OVS_UNUSED, } static void -format_UNROLL_XLATE(const struct ofpact_unroll_xlate *a, struct ds *s) +format_UNROLL_XLATE(const struct ofpact_unroll_xlate *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%sunroll_xlate(%s%stable=%s%"PRIu8 ", %scookie=%s%"PRIu64"%s)%s", @@ -5070,15 +5230,17 @@ encode_CLONE(const struct ofpact_nest *clone, } static char * OVS_WARN_UNUSED_RESULT -parse_CLONE(char *arg, struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols) +parse_CLONE(char *arg, const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts, + enum ofputil_protocol *usable_protocols) { const size_t clone_offset = ofpacts_pull(ofpacts); struct ofpact_nest *clone = ofpact_put_CLONE(ofpacts); char *error; ofpbuf_pull(ofpacts, sizeof *clone); - error = ofpacts_parse_copy(arg, ofpacts, usable_protocols, false, 0); + error = ofpacts_parse_copy(arg, port_map, ofpacts, + usable_protocols, false, 0); /* header points to the action list */ ofpacts->header = ofpbuf_push_uninit(ofpacts, sizeof *clone); clone = ofpacts->header; @@ -5089,10 +5251,11 @@ parse_CLONE(char *arg, struct ofpbuf *ofpacts, } static void -format_CLONE(const struct ofpact_nest *a, struct ds *s) +format_CLONE(const struct ofpact_nest *a, + const struct ofputil_port_map *port_map, struct ds *s) { ds_put_format(s, "%sclone(%s", colors.paren, colors.end); - ofpacts_format(a->actions, ofpact_nest_get_action_len(a), s); + ofpacts_format(a->actions, ofpact_nest_get_action_len(a), port_map, s); ds_put_format(s, "%s)%s", colors.paren, colors.end); } @@ -5251,7 +5414,8 @@ encode_SAMPLE(const struct ofpact_sample *sample, * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ static char * OVS_WARN_UNUSED_RESULT -parse_SAMPLE(char *arg, struct ofpbuf *ofpacts, +parse_SAMPLE(char *arg, const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { struct ofpact_sample *os = ofpact_put_SAMPLE(ofpacts); @@ -5274,7 +5438,8 @@ parse_SAMPLE(char *arg, struct ofpbuf *ofpacts, } else if (!strcmp(key, "obs_point_id")) { error = str_to_u32(value, &os->obs_point_id); } else if (!strcmp(key, "sampling_port")) { - if (!ofputil_port_from_string(value, &os->sampling_port)) { + if (!ofputil_port_from_string(value, port_map, + &os->sampling_port)) { error = xasprintf("%s: unknown port", value); } } else if (!strcmp(key, "ingress")) { @@ -5297,7 +5462,8 @@ parse_SAMPLE(char *arg, struct ofpbuf *ofpacts, } static void -format_SAMPLE(const struct ofpact_sample *a, struct ds *s) +format_SAMPLE(const struct ofpact_sample *a, + const struct ofputil_port_map *port_map, struct ds *s) { ds_put_format(s, "%ssample(%s%sprobability=%s%"PRIu16 ",%scollector_set_id=%s%"PRIu32 @@ -5309,8 +5475,8 @@ format_SAMPLE(const struct ofpact_sample *a, struct ds *s) colors.param, colors.end, a->obs_domain_id, colors.param, colors.end, a->obs_point_id); if (a->sampling_port != OFPP_NONE) { - ds_put_format(s, ",%ssampling_port=%s%"PRIu32, - colors.param, colors.end, a->sampling_port); + ds_put_format(s, ",%ssampling_port=%s", colors.param, colors.end); + ofputil_format_port(a->sampling_port, port_map, s); } if (a->direction == NX_ACTION_SAMPLE_INGRESS) { ds_put_format(s, ",%singress%s", colors.param, colors.end); @@ -5350,7 +5516,9 @@ encode_DEBUG_RECIRC(const struct ofpact_null *n OVS_UNUSED, } static char * OVS_WARN_UNUSED_RESULT -parse_DEBUG_RECIRC(char *arg OVS_UNUSED, struct ofpbuf *ofpacts, +parse_DEBUG_RECIRC(char *arg OVS_UNUSED, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { ofpact_put_DEBUG_RECIRC(ofpacts); @@ -5358,7 +5526,9 @@ parse_DEBUG_RECIRC(char *arg OVS_UNUSED, struct ofpbuf *ofpacts, } static void -format_DEBUG_RECIRC(const struct ofpact_null *a OVS_UNUSED, struct ds *s) +format_DEBUG_RECIRC(const struct ofpact_null *a OVS_UNUSED, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%sdebug_recirc%s", colors.value, colors.end); } @@ -5623,8 +5793,9 @@ encode_CT(const struct ofpact_conntrack *conntrack, nac->len = htons(len); } -static char * OVS_WARN_UNUSED_RESULT parse_NAT(char *arg, struct ofpbuf *, - enum ofputil_protocol * OVS_UNUSED); +static char *OVS_WARN_UNUSED_RESULT +parse_NAT(char *arg, const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *, enum ofputil_protocol * OVS_UNUSED); /* Parses 'arg' as the argument to a "ct" action, and appends such an * action to 'ofpacts'. @@ -5632,7 +5803,8 @@ static char * OVS_WARN_UNUSED_RESULT parse_NAT(char *arg, struct ofpbuf *, * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ static char * OVS_WARN_UNUSED_RESULT -parse_CT(char *arg, struct ofpbuf *ofpacts, +parse_CT(char *arg, const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols) { const size_t ct_offset = ofpacts_pull(ofpacts); @@ -5668,7 +5840,7 @@ parse_CT(char *arg, struct ofpbuf *ofpacts, } else if (!strcmp(key, "nat")) { const size_t nat_offset = ofpacts_pull(ofpacts); - error = parse_NAT(value, ofpacts, usable_protocols); + error = parse_NAT(value, port_map, ofpacts, usable_protocols); /* Update CT action pointer and length. */ ofpacts->header = ofpbuf_push_uninit(ofpacts, nat_offset); oc = ofpacts->header; @@ -5681,8 +5853,8 @@ parse_CT(char *arg, struct ofpbuf *ofpacts, /* Initializes 'usable_protocol2', fold it back to * '*usable_protocols' afterwards, so that we do not lose * restrictions already in there. */ - error = ofpacts_parse_copy(value, ofpacts, &usable_protocols2, - false, OFPACT_CT); + error = ofpacts_parse_copy(value, port_map, ofpacts, + &usable_protocols2, false, OFPACT_CT); *usable_protocols &= usable_protocols2; ofpacts->header = ofpbuf_push_uninit(ofpacts, exec_offset); oc = ofpacts->header; @@ -5720,10 +5892,14 @@ format_alg(int port, struct ds *s) } } -static void format_NAT(const struct ofpact_nat *a, struct ds *ds); +static void format_NAT(const struct ofpact_nat *, + const struct ofputil_port_map *port_map, + struct ds *ds); static void -format_CT(const struct ofpact_conntrack *a, struct ds *s) +format_CT(const struct ofpact_conntrack *a, + const struct ofputil_port_map *port_map, + struct ds *s) { ds_put_format(s, "%sct(%s", colors.paren, colors.end); if (a->flags & NX_CT_F_COMMIT) { @@ -5749,14 +5925,14 @@ format_CT(const struct ofpact_conntrack *a, struct ds *s) const struct ofpact *action = a->actions; size_t actions_len = ofpact_ct_get_action_len(a); if (actions_len && action->type == OFPACT_NAT) { - format_NAT(ofpact_get_NAT(action), s); + format_NAT(ofpact_get_NAT(action), port_map, s); ds_put_char(s, ','); actions_len -= OFPACT_ALIGN(action->len); action = ofpact_next(action); } if (actions_len) { ds_put_format(s, "%sexec(%s", colors.paren, colors.end); - ofpacts_format(action, actions_len, s); + ofpacts_format(action, actions_len, port_map, s); ds_put_format(s, "%s),%s", colors.paren, colors.end); } format_alg(a->alg, s); @@ -5782,7 +5958,9 @@ encode_CT_CLEAR(const struct ofpact_null *null OVS_UNUSED, } static char * OVS_WARN_UNUSED_RESULT -parse_CT_CLEAR(char *arg OVS_UNUSED, struct ofpbuf *ofpacts, +parse_CT_CLEAR(char *arg OVS_UNUSED, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { ofpact_put_CT_CLEAR(ofpacts); @@ -5790,10 +5968,13 @@ parse_CT_CLEAR(char *arg OVS_UNUSED, struct ofpbuf *ofpacts, } static void -format_CT_CLEAR(const struct ofpact_null *a OVS_UNUSED, struct ds *s) +format_CT_CLEAR(const struct ofpact_null *a OVS_UNUSED, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%sct_clear%s", colors.value, colors.end); -} +} + /* NAT action. */ /* Which optional fields are present? */ @@ -5973,7 +6154,9 @@ decode_NXAST_RAW_NAT(const struct nx_action_nat *nan, } static void -format_NAT(const struct ofpact_nat *a, struct ds *ds) +format_NAT(const struct ofpact_nat *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *ds) { ds_put_format(ds, "%snat%s", colors.paren, colors.end); @@ -6097,7 +6280,9 @@ error: * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ static char * OVS_WARN_UNUSED_RESULT -parse_NAT(char *arg, struct ofpbuf *ofpacts, +parse_NAT(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { struct ofpact_nat *on = ofpact_put_NAT(ofpacts); @@ -6187,8 +6372,10 @@ encode_OUTPUT_TRUNC(const struct ofpact_output_trunc *output_trunc, } static char * OVS_WARN_UNUSED_RESULT -parse_OUTPUT_TRUNC(const char *arg, struct ofpbuf *ofpacts OVS_UNUSED, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_OUTPUT_TRUNC(const char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts OVS_UNUSED, + enum ofputil_protocol *usable_protocols OVS_UNUSED) { /* Disable output_trunc parsing. Expose as output(port=N,max_len=M) and * reuse parse_OUTPUT to parse output_trunc action. */ @@ -6196,10 +6383,12 @@ parse_OUTPUT_TRUNC(const char *arg, struct ofpbuf *ofpacts OVS_UNUSED, } static void -format_OUTPUT_TRUNC(const struct ofpact_output_trunc *a, struct ds *s) +format_OUTPUT_TRUNC(const struct ofpact_output_trunc *a, + const struct ofputil_port_map *port_map, struct ds *s) { - ds_put_format(s, "%soutput%s(port=%"PRIu32",max_len=%"PRIu32")", - colors.special, colors.end, a->port, a->max_len); + ds_put_format(s, "%soutput%s(port=", colors.special, colors.end); + ofputil_format_port(a->port, port_map, s); + ds_put_format(s, ",max_len=%"PRIu32")", a->max_len); } @@ -6215,7 +6404,9 @@ encode_METER(const struct ofpact_meter *meter, } static char * OVS_WARN_UNUSED_RESULT -parse_METER(char *arg, struct ofpbuf *ofpacts, +parse_METER(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols) { *usable_protocols &= OFPUTIL_P_OF13_UP; @@ -6223,7 +6414,9 @@ parse_METER(char *arg, struct ofpbuf *ofpacts, } static void -format_METER(const struct ofpact_meter *a, struct ds *s) +format_METER(const struct ofpact_meter *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%smeter:%s%"PRIu32, colors.param, colors.end, a->meter_id); @@ -6242,7 +6435,9 @@ encode_CLEAR_ACTIONS(const struct ofpact_null *null OVS_UNUSED, } static char * OVS_WARN_UNUSED_RESULT -parse_CLEAR_ACTIONS(char *arg OVS_UNUSED, struct ofpbuf *ofpacts, +parse_CLEAR_ACTIONS(char *arg OVS_UNUSED, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { ofpact_put_CLEAR_ACTIONS(ofpacts); @@ -6250,7 +6445,9 @@ parse_CLEAR_ACTIONS(char *arg OVS_UNUSED, struct ofpbuf *ofpacts, } static void -format_CLEAR_ACTIONS(const struct ofpact_null *a OVS_UNUSED, struct ds *s) +format_CLEAR_ACTIONS(const struct ofpact_null *a OVS_UNUSED, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%sclear_actions%s", colors.value, colors.end); } @@ -6273,7 +6470,8 @@ encode_WRITE_ACTIONS(const struct ofpact_nest *actions, } static char * OVS_WARN_UNUSED_RESULT -parse_WRITE_ACTIONS(char *arg, struct ofpbuf *ofpacts, +parse_WRITE_ACTIONS(char *arg, const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols) { size_t ofs = ofpacts_pull(ofpacts); @@ -6291,7 +6489,7 @@ parse_WRITE_ACTIONS(char *arg, struct ofpbuf *ofpacts, * that it doesn't actually include the nested actions. That means that * ofpacts_parse() would reject them as being part of an Apply-Actions that * follows a Write-Actions, which is an invalid order. */ - error = ofpacts_parse(arg, ofpacts, usable_protocols, false, + error = ofpacts_parse(arg, port_map, ofpacts, usable_protocols, false, OFPACT_WRITE_ACTIONS); /* Put the Write-Actions back on and update its length. */ @@ -6305,10 +6503,11 @@ parse_WRITE_ACTIONS(char *arg, struct ofpbuf *ofpacts, } static void -format_WRITE_ACTIONS(const struct ofpact_nest *a, struct ds *s) +format_WRITE_ACTIONS(const struct ofpact_nest *a, + const struct ofputil_port_map *port_map, struct ds *s) { ds_put_format(s, "%swrite_actions(%s", colors.paren, colors.end); - ofpacts_format(a->actions, ofpact_nest_get_action_len(a), s); + ofpacts_format(a->actions, ofpact_nest_get_action_len(a), port_map, s); ds_put_format(s, "%s)%s", colors.paren, colors.end); } @@ -6364,7 +6563,9 @@ encode_WRITE_METADATA(const struct ofpact_metadata *metadata, } static char * OVS_WARN_UNUSED_RESULT -parse_WRITE_METADATA(char *arg, struct ofpbuf *ofpacts, +parse_WRITE_METADATA(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols) { struct ofpact_metadata *om; @@ -6389,7 +6590,9 @@ parse_WRITE_METADATA(char *arg, struct ofpbuf *ofpacts, } static void -format_WRITE_METADATA(const struct ofpact_metadata *a, struct ds *s) +format_WRITE_METADATA(const struct ofpact_metadata *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%swrite_metadata:%s%#"PRIx64, colors.param, colors.end, ntohll(a->metadata)); @@ -6420,7 +6623,9 @@ encode_GOTO_TABLE(const struct ofpact_goto_table *goto_table, } static char * OVS_WARN_UNUSED_RESULT -parse_GOTO_TABLE(char *arg, struct ofpbuf *ofpacts, +parse_GOTO_TABLE(char *arg, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) { struct ofpact_goto_table *ogt = ofpact_put_GOTO_TABLE(ofpacts); @@ -6432,7 +6637,9 @@ parse_GOTO_TABLE(char *arg, struct ofpbuf *ofpacts, } static void -format_GOTO_TABLE(const struct ofpact_goto_table *a, struct ds *s) +format_GOTO_TABLE(const struct ofpact_goto_table *a, + const struct ofputil_port_map *port_map OVS_UNUSED, + struct ds *s) { ds_put_format(s, "%sgoto_table:%s%"PRIu8, colors.param, colors.end, a->table_id); @@ -8139,12 +8346,14 @@ ofpacts_get_meter(const struct ofpact ofpacts[], size_t ofpacts_len) /* Formatting ofpacts. */ static void -ofpact_format(const struct ofpact *a, struct ds *s) +ofpact_format(const struct ofpact *a, + const struct ofputil_port_map *port_map, struct ds *s) { switch (a->type) { #define OFPACT(ENUM, STRUCT, MEMBER, NAME) \ case OFPACT_##ENUM: \ - format_##ENUM(ALIGNED_CAST(const struct STRUCT *, a), s); \ + format_##ENUM(ALIGNED_CAST(const struct STRUCT *, a), \ + port_map, s); \ break; OFPACTS #undef OFPACT @@ -8154,10 +8363,11 @@ ofpact_format(const struct ofpact *a, struct ds *s) } /* Appends a string representing the 'ofpacts_len' bytes of ofpacts in - * 'ofpacts' to 'string'. */ + * 'ofpacts' to 'string'. If 'port_map' is nonnull, uses it to translate + * port numbers to names in output. */ void ofpacts_format(const struct ofpact *ofpacts, size_t ofpacts_len, - struct ds *string) + const struct ofputil_port_map *port_map, struct ds *string) { if (!ofpacts_len) { ds_put_format(string, "%sdrop%s", colors.drop, colors.end); @@ -8169,7 +8379,7 @@ ofpacts_format(const struct ofpact *ofpacts, size_t ofpacts_len, ds_put_char(string, ','); } - ofpact_format(a, string); + ofpact_format(a, port_map, string); } } } @@ -8222,13 +8432,14 @@ ofpact_finish(struct ofpbuf *ofpacts, struct ofpact *ofpact) } static char * OVS_WARN_UNUSED_RESULT -ofpact_parse(enum ofpact_type type, char *value, struct ofpbuf *ofpacts, +ofpact_parse(enum ofpact_type type, char *value, + const struct ofputil_port_map *port_map, struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols) { switch (type) { -#define OFPACT(ENUM, STRUCT, MEMBER, NAME) \ +#define OFPACT(ENUM, STRUCT, MEMBER, NAME) \ case OFPACT_##ENUM: \ - return parse_##ENUM(value, ofpacts, usable_protocols); + return parse_##ENUM(value, port_map, ofpacts, usable_protocols); OFPACTS #undef OFPACT default: @@ -8258,7 +8469,8 @@ ofpact_type_from_name(const char *name, enum ofpact_type *type) * If 'outer_action' is specified, indicates that the actions being parsed * are nested within another action of the type specified in 'outer_action'. */ static char * OVS_WARN_UNUSED_RESULT -ofpacts_parse__(char *str, struct ofpbuf *ofpacts, +ofpacts_parse__(char *str, const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols, bool allow_instructions, enum ofpact_type outer_action) { @@ -8276,14 +8488,16 @@ ofpacts_parse__(char *str, struct ofpbuf *ofpacts, ofp_port_t port; if (ofpact_type_from_name(key, &type)) { - error = ofpact_parse(type, value, ofpacts, usable_protocols); + error = ofpact_parse(type, value, port_map, + ofpacts, usable_protocols); inst = ovs_instruction_type_from_ofpact_type(type); } else if (!strcasecmp(key, "mod_vlan_vid")) { error = parse_set_vlan_vid(value, ofpacts, true); } else if (!strcasecmp(key, "mod_vlan_pcp")) { error = parse_set_vlan_pcp(value, ofpacts, true); } else if (!strcasecmp(key, "set_nw_ttl")) { - error = parse_SET_IP_TTL(value, ofpacts, usable_protocols); + error = parse_SET_IP_TTL(value, port_map, + ofpacts, usable_protocols); } else if (!strcasecmp(key, "pop_vlan")) { error = parse_pop_vlan(ofpacts); } else if (!strcasecmp(key, "set_tunnel64")) { @@ -8292,12 +8506,12 @@ ofpacts_parse__(char *str, struct ofpbuf *ofpacts, } else if (!strcasecmp(key, "load")) { error = parse_reg_load(value, ofpacts); } else if (!strcasecmp(key, "bundle_load")) { - error = parse_bundle_load(value, ofpacts); + error = parse_bundle_load(value, port_map, ofpacts); } else if (!strcasecmp(key, "drop")) { drop = true; } else if (!strcasecmp(key, "apply_actions")) { return xstrdup("apply_actions is the default instruction"); - } else if (ofputil_port_from_string(key, &port)) { + } else if (ofputil_port_from_string(key, port_map, &port)) { ofpact_put_OUTPUT(ofpacts)->port = port; } else { return xasprintf("unknown action %s", key); @@ -8343,12 +8557,12 @@ ofpacts_parse__(char *str, struct ofpbuf *ofpacts, } static char * OVS_WARN_UNUSED_RESULT -ofpacts_parse(char *str, struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols, bool allow_instructions, - enum ofpact_type outer_action) +ofpacts_parse(char *str, const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols, + bool allow_instructions, enum ofpact_type outer_action) { uint32_t orig_size = ofpacts->size; - char *error = ofpacts_parse__(str, ofpacts, usable_protocols, + char *error = ofpacts_parse__(str, port_map, ofpacts, usable_protocols, allow_instructions, outer_action); if (error) { ofpacts->size = orig_size; @@ -8357,7 +8571,8 @@ ofpacts_parse(char *str, struct ofpbuf *ofpacts, } static char * OVS_WARN_UNUSED_RESULT -ofpacts_parse_copy(const char *s_, struct ofpbuf *ofpacts, +ofpacts_parse_copy(const char *s_, const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols, bool allow_instructions, enum ofpact_type outer_action) { @@ -8366,8 +8581,8 @@ ofpacts_parse_copy(const char *s_, struct ofpbuf *ofpacts, *usable_protocols = OFPUTIL_P_ANY; s = xstrdup(s_); - error = ofpacts_parse(s, ofpacts, usable_protocols, allow_instructions, - outer_action); + error = ofpacts_parse(s, port_map, ofpacts, usable_protocols, + allow_instructions, outer_action); free(s); return error; @@ -8380,10 +8595,12 @@ ofpacts_parse_copy(const char *s_, struct ofpbuf *ofpacts, * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ char * OVS_WARN_UNUSED_RESULT -ofpacts_parse_actions(const char *s, struct ofpbuf *ofpacts, +ofpacts_parse_actions(const char *s, const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols) { - return ofpacts_parse_copy(s, ofpacts, usable_protocols, false, 0); + return ofpacts_parse_copy(s, port_map, ofpacts, usable_protocols, + false, 0); } /* Parses 's' as a set of OpenFlow instructions and appends the instructions to @@ -8392,10 +8609,12 @@ ofpacts_parse_actions(const char *s, struct ofpbuf *ofpacts, * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ char * OVS_WARN_UNUSED_RESULT -ofpacts_parse_instructions(const char *s, struct ofpbuf *ofpacts, +ofpacts_parse_instructions(const char *s, + const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols) { - return ofpacts_parse_copy(s, ofpacts, usable_protocols, true, 0); + return ofpacts_parse_copy(s, port_map, ofpacts, usable_protocols, true, 0); } const char * diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index afb8b40cc..987b46397 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc. + * Copyright (c) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -235,7 +235,8 @@ parse_protocol(const char *name, const struct protocol **p_out) * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ static char * OVS_WARN_UNUSED_RESULT -parse_field(const struct mf_field *mf, const char *s, struct match *match, +parse_field(const struct mf_field *mf, const char *s, + const struct ofputil_port_map *port_map, struct match *match, enum ofputil_protocol *usable_protocols) { union mf_value value, mask; @@ -247,7 +248,7 @@ parse_field(const struct mf_field *mf, const char *s, struct match *match, s = "0/0"; } - error = mf_parse(mf, s, &value, &mask); + error = mf_parse(mf, s, port_map, &value, &mask); if (!error) { *usable_protocols &= mf_set(mf, &value, &mask, match, &error); } @@ -281,7 +282,7 @@ parse_subfield(const char *name, const char *str_value, struct match *match, struct ds ds; ds_init(&ds); - mf_format(sf.field, &val, NULL, &ds); + mf_format(sf.field, &val, NULL, NULL, &ds); error = xasprintf("%s: value %s does not fit into %d bits", name, ds_cstr(&ds), sf.n_bits); ds_destroy(&ds); @@ -316,6 +317,7 @@ extract_actions(char *s) static char * OVS_WARN_UNUSED_RESULT parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string, + const struct ofputil_port_map *port_map, enum ofputil_protocol *usable_protocols) { enum { @@ -431,7 +433,8 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string, || !strcmp(name, "allow_hidden_fields")) { /* ignore these fields. */ } else if ((mf = mf_from_name(name)) != NULL) { - error = parse_field(mf, value, &fm->match, usable_protocols); + error = parse_field(mf, value, port_map, + &fm->match, usable_protocols); } else if (strchr(name, '[')) { error = parse_subfield(name, value, &fm->match, usable_protocols); } else { @@ -445,7 +448,8 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string, *usable_protocols &= OFPUTIL_P_TID; } } else if (fields & F_OUT_PORT && !strcmp(name, "out_port")) { - if (!ofputil_port_from_string(value, &fm->out_port)) { + if (!ofputil_port_from_string(value, port_map, + &fm->out_port)) { error = xasprintf("%s is not a valid OpenFlow port", value); } @@ -540,7 +544,7 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string, char *error; ofpbuf_init(&ofpacts, 32); - error = ofpacts_parse_instructions(act_str, &ofpacts, + error = ofpacts_parse_instructions(act_str, port_map, &ofpacts, &action_usable_protocols); *usable_protocols &= action_usable_protocols; if (!error) { @@ -588,12 +592,13 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string, * error. The caller is responsible for freeing the returned string. */ char * OVS_WARN_UNUSED_RESULT parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_, + const struct ofputil_port_map *port_map, enum ofputil_protocol *usable_protocols) { char *string = xstrdup(str_); char *error; - error = parse_ofp_str__(fm, command, string, usable_protocols); + error = parse_ofp_str__(fm, command, string, port_map, usable_protocols); if (error) { fm->ofpacts = NULL; fm->ofpacts_len = 0; @@ -607,6 +612,7 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_, * both 'po->ofpacts' and 'po->packet' must be free()d by the caller. */ static char * OVS_WARN_UNUSED_RESULT parse_ofp_packet_out_str__(struct ofputil_packet_out *po, char *string, + const struct ofputil_port_map *port_map, enum ofputil_protocol *usable_protocols) { enum ofputil_protocol action_usable_protocols; @@ -635,7 +641,7 @@ parse_ofp_packet_out_str__(struct ofputil_packet_out *po, char *string, if (!strcmp(name, "in_port")) { ofp_port_t in_port; - if (!ofputil_port_from_string(value, &in_port)) { + if (!ofputil_port_from_string(value, port_map, &in_port)) { error = xasprintf("%s is not a valid OpenFlow port", value); goto out; } @@ -662,7 +668,7 @@ parse_ofp_packet_out_str__(struct ofputil_packet_out *po, char *string, goto out; } - error = parse_field(mf, value, &po->flow_metadata, + error = parse_field(mf, value, port_map, &po->flow_metadata, usable_protocols); if (error) { goto out; @@ -681,7 +687,7 @@ parse_ofp_packet_out_str__(struct ofputil_packet_out *po, char *string, } if (act_str) { - error = ofpacts_parse_actions(act_str, &ofpacts, + error = ofpacts_parse_actions(act_str, port_map, &ofpacts, &action_usable_protocols); *usable_protocols &= action_usable_protocols; if (error) { @@ -707,12 +713,13 @@ out: * error. The caller is responsible for freeing the returned string. */ char * OVS_WARN_UNUSED_RESULT parse_ofp_packet_out_str(struct ofputil_packet_out *po, const char *str_, + const struct ofputil_port_map *port_map, enum ofputil_protocol *usable_protocols) { char *string = xstrdup(str_); char *error; - error = parse_ofp_packet_out_str__(po, string, usable_protocols); + error = parse_ofp_packet_out_str__(po, string, port_map, usable_protocols); if (error) { po->ofpacts = NULL; po->ofpacts_len = 0; @@ -948,7 +955,9 @@ parse_ofp_meter_mod_str(struct ofputil_meter_mod *mm, const char *str_, static char * OVS_WARN_UNUSED_RESULT parse_flow_monitor_request__(struct ofputil_flow_monitor_request *fmr, - const char *str_, char *string, + const char *str_, + const struct ofputil_port_map *port_map, + char *string, enum ofputil_protocol *usable_protocols) { static atomic_count id = ATOMIC_COUNT_INIT(0); @@ -984,8 +993,8 @@ parse_flow_monitor_request__(struct ofputil_flow_monitor_request *fmr, match_set_nw_proto(&fmr->match, p->nw_proto); } } else if (mf_from_name(name)) { - error = parse_field(mf_from_name(name), value, &fmr->match, - usable_protocols); + error = parse_field(mf_from_name(name), value, port_map, + &fmr->match, usable_protocols); } else { if (!*value) { return xasprintf("%s: field %s missing value", str_, name); @@ -1015,10 +1024,11 @@ parse_flow_monitor_request__(struct ofputil_flow_monitor_request *fmr, char * OVS_WARN_UNUSED_RESULT parse_flow_monitor_request(struct ofputil_flow_monitor_request *fmr, const char *str_, + const struct ofputil_port_map *port_map, enum ofputil_protocol *usable_protocols) { char *string = xstrdup(str_); - char *error = parse_flow_monitor_request__(fmr, str_, string, + char *error = parse_flow_monitor_request__(fmr, str_, port_map, string, usable_protocols); free(string); return error; @@ -1035,10 +1045,11 @@ parse_flow_monitor_request(struct ofputil_flow_monitor_request *fmr, * error. The caller is responsible for freeing the returned string. */ char * OVS_WARN_UNUSED_RESULT parse_ofp_flow_mod_str(struct ofputil_flow_mod *fm, const char *string, - int command, + const struct ofputil_port_map *port_map, int command, enum ofputil_protocol *usable_protocols) { - char *error = parse_ofp_str(fm, command, string, usable_protocols); + char *error = parse_ofp_str(fm, command, string, port_map, + usable_protocols); if (!error) { /* Normalize a copy of the match. This ensures that non-normalized @@ -1189,7 +1200,8 @@ parse_ofp_table_mod(struct ofputil_table_mod *tm, const char *table_id, * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ char * OVS_WARN_UNUSED_RESULT -parse_ofp_flow_mod_file(const char *file_name, int command, +parse_ofp_flow_mod_file(const char *file_name, + const struct ofputil_port_map *port_map, int command, struct ofputil_flow_mod **fms, size_t *n_fms, enum ofputil_protocol *usable_protocols) { @@ -1219,8 +1231,8 @@ parse_ofp_flow_mod_file(const char *file_name, int command, if (*n_fms >= allocated_fms) { *fms = x2nrealloc(*fms, &allocated_fms, sizeof **fms); } - error = parse_ofp_flow_mod_str(&(*fms)[*n_fms], ds_cstr(&s), command, - &usable); + error = parse_ofp_flow_mod_str(&(*fms)[*n_fms], ds_cstr(&s), port_map, + command, &usable); if (error) { char *err_msg; size_t i; @@ -1255,12 +1267,13 @@ parse_ofp_flow_mod_file(const char *file_name, int command, char * OVS_WARN_UNUSED_RESULT parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *fsr, bool aggregate, const char *string, + const struct ofputil_port_map *port_map, enum ofputil_protocol *usable_protocols) { struct ofputil_flow_mod fm; char *error; - error = parse_ofp_str(&fm, -1, string, usable_protocols); + error = parse_ofp_str(&fm, -1, string, port_map, usable_protocols); if (error) { return error; } @@ -1295,7 +1308,7 @@ parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *fsr, char * parse_ofp_exact_flow(struct flow *flow, struct flow_wildcards *wc, const struct tun_table *tun_table, const char *s, - const struct simap *portno_names) + const struct ofputil_port_map *port_map) { char *pos, *key, *value_s; char *error = NULL; @@ -1353,28 +1366,17 @@ parse_ofp_exact_flow(struct flow *flow, struct flow_wildcards *wc, goto exit; } - if (!strcmp(key, "in_port") - && portno_names - && simap_contains(portno_names, value_s)) { - flow->in_port.ofp_port = u16_to_ofp( - simap_get(portno_names, value_s)); - if (wc) { - wc->masks.in_port.ofp_port - = u16_to_ofp(ntohs(OVS_BE16_MAX)); - } - } else { - field_error = mf_parse_value(mf, value_s, &value); - if (field_error) { - error = xasprintf("%s: bad value for %s (%s)", - s, key, field_error); - free(field_error); - goto exit; - } + field_error = mf_parse_value(mf, value_s, port_map, &value); + if (field_error) { + error = xasprintf("%s: bad value for %s (%s)", + s, key, field_error); + free(field_error); + goto exit; + } - mf_set_flow_value(mf, &value, flow); - if (wc) { - mf_mask_field(mf, wc); - } + mf_set_flow_value(mf, &value, flow); + if (wc) { + mf_mask_field(mf, wc); } } } @@ -1396,8 +1398,9 @@ exit: } static char * OVS_WARN_UNUSED_RESULT -parse_bucket_str(struct ofputil_bucket *bucket, char *str_, uint8_t group_type, - enum ofputil_protocol *usable_protocols) +parse_bucket_str(struct ofputil_bucket *bucket, char *str_, + const struct ofputil_port_map *port_map, uint8_t group_type, + enum ofputil_protocol *usable_protocols) { char *pos, *key, *value; struct ofpbuf ofpacts; @@ -1417,7 +1420,7 @@ parse_bucket_str(struct ofputil_bucket *bucket, char *str_, uint8_t group_type, if (!strcasecmp(key, "weight")) { error = str_to_u16(value, "weight", &bucket->weight); } else if (!strcasecmp(key, "watch_port")) { - if (!ofputil_port_from_string(value, &bucket->watch_port) + if (!ofputil_port_from_string(value, port_map, &bucket->watch_port) || (ofp_to_u16(bucket->watch_port) >= ofp_to_u16(OFPP_MAX) && bucket->watch_port != OFPP_ANY)) { error = xasprintf("%s: invalid watch_port", value); @@ -1453,7 +1456,7 @@ parse_bucket_str(struct ofputil_bucket *bucket, char *str_, uint8_t group_type, ds_chomp(&actions, ','); ofpbuf_init(&ofpacts, 0); - error = ofpacts_parse_actions(ds_cstr(&actions), &ofpacts, + error = ofpacts_parse_actions(ds_cstr(&actions), port_map, &ofpacts, usable_protocols); ds_destroy(&actions); if (error) { @@ -1467,7 +1470,8 @@ parse_bucket_str(struct ofputil_bucket *bucket, char *str_, uint8_t group_type, } static char * OVS_WARN_UNUSED_RESULT -parse_select_group_field(char *s, struct field_array *fa, +parse_select_group_field(char *s, const struct ofputil_port_map *port_map, + struct field_array *fa, enum ofputil_protocol *usable_protocols) { char *name, *value_str; @@ -1484,7 +1488,7 @@ parse_select_group_field(char *s, struct field_array *fa, } if (*value_str) { - error = mf_parse_value(mf, value_str, &value); + error = mf_parse_value(mf, value_str, port_map, &value); if (error) { return error; } @@ -1527,6 +1531,7 @@ parse_select_group_field(char *s, struct field_array *fa, static char * OVS_WARN_UNUSED_RESULT parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, int command, char *string, + const struct ofputil_port_map *port_map, enum ofputil_protocol *usable_protocols) { enum { @@ -1720,7 +1725,8 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, int command, error = xstrdup("fields are not needed"); goto out; } - error = parse_select_group_field(value, &gm->props.fields, + error = parse_select_group_field(value, port_map, + &gm->props.fields, usable_protocols); if (error) { goto out; @@ -1779,7 +1785,8 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, int command, } bucket = xzalloc(sizeof(struct ofputil_bucket)); - error = parse_bucket_str(bucket, bkt_str, gm->type, usable_protocols); + error = parse_bucket_str(bucket, bkt_str, port_map, + gm->type, usable_protocols); if (error) { free(bucket); goto out; @@ -1811,11 +1818,12 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, int command, char * OVS_WARN_UNUSED_RESULT parse_ofp_group_mod_str(struct ofputil_group_mod *gm, int command, const char *str_, + const struct ofputil_port_map *port_map, enum ofputil_protocol *usable_protocols) { char *string = xstrdup(str_); char *error = parse_ofp_group_mod_str__(gm, command, string, - usable_protocols); + port_map, usable_protocols); free(string); return error; } @@ -1825,7 +1833,9 @@ parse_ofp_group_mod_str(struct ofputil_group_mod *gm, int command, * missing command name is treated as "add". */ char * OVS_WARN_UNUSED_RESULT -parse_ofp_group_mod_file(const char *file_name, int command, +parse_ofp_group_mod_file(const char *file_name, + const struct ofputil_port_map *port_map, + int command, struct ofputil_group_mod **gms, size_t *n_gms, enum ofputil_protocol *usable_protocols) { @@ -1862,7 +1872,7 @@ parse_ofp_group_mod_file(const char *file_name, int command, *gms = new_gms; } error = parse_ofp_group_mod_str(&(*gms)[*n_gms], command, ds_cstr(&s), - &usable); + port_map, &usable); if (error) { size_t i; @@ -1900,6 +1910,7 @@ parse_ofp_group_mod_file(const char *file_name, int command, * error. The caller is responsible for freeing the returned string. */ char * OVS_WARN_UNUSED_RESULT parse_ofp_bundle_file(const char *file_name, + const struct ofputil_port_map *port_map, struct ofputil_bundle_msg **bms, size_t *n_bms, enum ofputil_protocol *usable_protocols) { @@ -1946,7 +1957,8 @@ parse_ofp_bundle_file(const char *file_name, if (!strncmp(s, "flow", len)) { s += len; - error = parse_ofp_flow_mod_str(&(*bms)[*n_bms].fm, s, -2, &usable); + error = parse_ofp_flow_mod_str(&(*bms)[*n_bms].fm, s, port_map, + -2, &usable); if (error) { break; } @@ -1954,14 +1966,15 @@ parse_ofp_bundle_file(const char *file_name, } else if (!strncmp(s, "group", len)) { s += len; error = parse_ofp_group_mod_str(&(*bms)[*n_bms].gm, -2, s, - &usable); + port_map, &usable); if (error) { break; } (*bms)[*n_bms].type = OFPTYPE_GROUP_MOD; } else if (!strncmp(s, "packet-out", len)) { s += len; - error = parse_ofp_packet_out_str(&(*bms)[*n_bms].po, s, &usable); + error = parse_ofp_packet_out_str(&(*bms)[*n_bms].po, s, port_map, + &usable); if (error) { break; } diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 6d656b0e9..58cbecab2 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -68,7 +68,7 @@ ofp_packet_to_string(const void *data, size_t len, ovs_be32 packet_type) dp_packet_use_const(&buf, data, len); buf.packet_type = packet_type; flow_extract(&buf, &flow); - flow_format(&ds, &flow); + flow_format(&ds, &flow, NULL); l4_size = dp_packet_l4_size(&buf); @@ -118,7 +118,7 @@ format_hex_arg(struct ds *s, const uint8_t *data, size_t len) static void ofp_print_packet_in(struct ds *string, const struct ofp_header *oh, - int verbosity) + const struct ofputil_port_map *port_map, int verbosity) { char reasonbuf[OFPUTIL_PACKET_IN_REASON_BUFSIZE]; struct ofputil_packet_in_private pin; @@ -144,7 +144,8 @@ ofp_print_packet_in(struct ds *string, const struct ofp_header *oh, ds_put_format(string, " total_len=%"PRIuSIZE" ", total_len); - match_format(&public->flow_metadata, string, OFP_DEFAULT_PRIORITY); + match_format(&public->flow_metadata, port_map, + string, OFP_DEFAULT_PRIORITY); ds_put_format(string, " (via %s)", ofputil_packet_in_reason_to_string(public->reason, @@ -206,13 +207,13 @@ ofp_print_packet_in(struct ds *string, const struct ofp_header *oh, if (pin.actions_len) { ds_put_cstr(string, " continuation.actions="); - ofpacts_format(pin.actions, pin.actions_len, string); + ofpacts_format(pin.actions, pin.actions_len, port_map, string); ds_put_char(string, '\n'); } if (pin.action_set_len) { ds_put_cstr(string, " continuation.action_set="); - ofpacts_format(pin.action_set, pin.action_set_len, string); + ofpacts_format(pin.action_set, pin.action_set_len, port_map, string); ds_put_char(string, '\n'); } @@ -233,7 +234,7 @@ ofp_print_packet_in(struct ds *string, const struct ofp_header *oh, static void ofp_print_packet_out(struct ds *string, const struct ofp_header *oh, - int verbosity) + const struct ofputil_port_map *port_map, int verbosity) { struct ofputil_packet_out po; struct ofpbuf ofpacts; @@ -248,10 +249,10 @@ ofp_print_packet_out(struct ds *string, const struct ofp_header *oh, } ds_put_char(string, ' '); - match_format(&po.flow_metadata, string, OFP_DEFAULT_PRIORITY); + match_format(&po.flow_metadata, port_map, string, OFP_DEFAULT_PRIORITY); ds_put_cstr(string, " actions="); - ofpacts_format(po.ofpacts, po.ofpacts_len, string); + ofpacts_format(po.ofpacts, po.ofpacts_len, port_map, string); if (po.buffer_id == UINT32_MAX) { ds_put_format(string, " data_len=%"PRIuSIZE, po.packet_len); @@ -445,7 +446,7 @@ ofp_print_phy_port(struct ds *string, const struct ofputil_phy_port *port) name[j] = '\0'; ds_put_char(string, ' '); - ofputil_format_port(port->port_no, string); + ofputil_format_port(port->port_no, NULL, string); ds_put_format(string, "(%s): addr:"ETH_ADDR_FMT"\n", name, ETH_ADDR_ARGS(port->hw_addr)); @@ -647,14 +648,15 @@ static void print_wild(struct ds *string, const char *leader, int is_wild, static void print_wild_port(struct ds *string, const char *leader, int is_wild, - int verbosity, ofp_port_t port) + int verbosity, ofp_port_t port, + const struct ofputil_port_map *port_map) { if (is_wild && verbosity < 2) { return; } ds_put_cstr(string, leader); if (!is_wild) { - ofputil_format_port(port, string); + ofputil_format_port(port, port_map, string); } else { ds_put_char(string, '*'); } @@ -681,15 +683,17 @@ print_ip_netmask(struct ds *string, const char *leader, ovs_be32 ip, } void -ofp10_match_print(struct ds *f, const struct ofp10_match *om, int verbosity) +ofp10_match_print(struct ds *f, const struct ofp10_match *om, + const struct ofputil_port_map *port_map, int verbosity) { - char *s = ofp10_match_to_string(om, verbosity); + char *s = ofp10_match_to_string(om, port_map, verbosity); ds_put_cstr(f, s); free(s); } char * -ofp10_match_to_string(const struct ofp10_match *om, int verbosity) +ofp10_match_to_string(const struct ofp10_match *om, + const struct ofputil_port_map *port_map, int verbosity) { struct ds f = DS_EMPTY_INITIALIZER; uint32_t w = ntohl(om->wildcards); @@ -729,7 +733,7 @@ ofp10_match_to_string(const struct ofp10_match *om, int verbosity) } } print_wild_port(&f, "in_port=", w & OFPFW10_IN_PORT, verbosity, - u16_to_ofp(ntohs(om->in_port))); + u16_to_ofp(ntohs(om->in_port)), port_map); print_wild(&f, "dl_vlan=", w & OFPFW10_DL_VLAN, verbosity, "%d", ntohs(om->dl_vlan)); print_wild(&f, "dl_vlan_pcp=", w & OFPFW10_DL_VLAN_PCP, verbosity, @@ -802,7 +806,8 @@ ofp_print_flow_flags(struct ds *s, enum ofputil_flow_mod_flags flags) } static void -ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh, int verbosity) +ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh, + const struct ofputil_port_map *port_map, int verbosity) { struct ofputil_flow_mod fm; struct ofpbuf ofpacts; @@ -851,7 +856,7 @@ ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh, int verbosity) ofpraw_decode(&raw, oh); if (verbosity >= 3 && raw == OFPRAW_OFPT10_FLOW_MOD) { const struct ofp10_flow_mod *ofm = ofpmsg_body(oh); - ofp10_match_print(s, &ofm->match, verbosity); + ofp10_match_print(s, &ofm->match, port_map, verbosity); /* ofp_print_match() doesn't print priority. */ need_priority = true; @@ -867,7 +872,7 @@ ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh, int verbosity) /* nx_match_to_string() doesn't print priority. */ need_priority = true; } else { - match_format(&fm.match, s, fm.priority); + match_format(&fm.match, port_map, s, fm.priority); /* match_format() does print priority. */ need_priority = false; @@ -900,7 +905,7 @@ ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh, int verbosity) } if (fm.out_port != OFPP_ANY) { ds_put_format(s, "out_port:"); - ofputil_format_port(fm.out_port, s); + ofputil_format_port(fm.out_port, port_map, s); ds_put_char(s, ' '); } @@ -913,7 +918,7 @@ ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh, int verbosity) ofp_print_flow_flags(s, fm.flags); ds_put_cstr(s, "actions="); - ofpacts_format(fm.ofpacts, fm.ofpacts_len, s); + ofpacts_format(fm.ofpacts, fm.ofpacts_len, port_map, s); ofpbuf_uninit(&ofpacts); } @@ -975,7 +980,8 @@ ofp_flow_removed_reason_to_string(enum ofp_flow_removed_reason reason, } static void -ofp_print_flow_removed(struct ds *string, const struct ofp_header *oh) +ofp_print_flow_removed(struct ds *string, const struct ofp_header *oh, + const struct ofputil_port_map *port_map) { char reasonbuf[OFP_FLOW_REMOVED_REASON_BUFSIZE]; struct ofputil_flow_removed fr; @@ -988,7 +994,7 @@ ofp_print_flow_removed(struct ds *string, const struct ofp_header *oh) } ds_put_char(string, ' '); - match_format(&fr.match, string, fr.priority); + match_format(&fr.match, port_map, string, fr.priority); ds_put_format(string, " reason=%s", ofp_flow_removed_reason_to_string(fr.reason, reasonbuf, @@ -1014,7 +1020,8 @@ ofp_print_flow_removed(struct ds *string, const struct ofp_header *oh) } static void -ofp_print_port_mod(struct ds *string, const struct ofp_header *oh) +ofp_print_port_mod(struct ds *string, const struct ofp_header *oh, + const struct ofputil_port_map *port_map) { struct ofputil_port_mod pm; enum ofperr error; @@ -1026,7 +1033,7 @@ ofp_print_port_mod(struct ds *string, const struct ofp_header *oh) } ds_put_cstr(string, " port: "); - ofputil_format_port(pm.port_no, string); + ofputil_format_port(pm.port_no, port_map, string); ds_put_format(string, ": addr:"ETH_ADDR_FMT"\n", ETH_ADDR_ARGS(pm.hw_addr)); if (!eth_addr64_is_zero(pm.hw_addr64)) { @@ -1199,7 +1206,8 @@ ofp_print_table_status_message(struct ds *string, const struct ofp_header *oh) static void ofp_print_queue_get_config_request(struct ds *string, - const struct ofp_header *oh) + const struct ofp_header *oh, + const struct ofputil_port_map *port_map) { enum ofperr error; ofp_port_t port; @@ -1212,7 +1220,7 @@ ofp_print_queue_get_config_request(struct ds *string, } ds_put_cstr(string, " port="); - ofputil_format_port(port, string); + ofputil_format_port(port, port_map, string); if (queue != OFPQ_ALL) { ds_put_cstr(string, " queue="); @@ -1250,7 +1258,8 @@ compare_queues(const void *a_, const void *b_) static void ofp_print_queue_get_config_reply(struct ds *string, - const struct ofp_header *oh) + const struct ofp_header *oh, + const struct ofputil_port_map *port_map) { struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); @@ -1280,7 +1289,7 @@ ofp_print_queue_get_config_reply(struct ds *string, port = q->port; ds_put_cstr(string, "port="); - ofputil_format_port(port, string); + ofputil_format_port(port, port_map, string); ds_put_char(string, '\n'); } @@ -1579,7 +1588,8 @@ ofp_print_hello(struct ds *string, const struct ofp_header *oh) } static void -ofp_print_error_msg(struct ds *string, const struct ofp_header *oh) +ofp_print_error_msg(struct ds *string, const struct ofp_header *oh, + const struct ofputil_port_map *port_map) { size_t len = ntohs(oh->length); struct ofpbuf payload; @@ -1598,7 +1608,7 @@ ofp_print_error_msg(struct ds *string, const struct ofp_header *oh) if (error == OFPERR_OFPHFC_INCOMPATIBLE || error == OFPERR_OFPHFC_EPERM) { ds_put_printable(string, payload.data, payload.size); } else { - s = ofp_to_string(payload.data, payload.size, 1); + s = ofp_to_string(payload.data, payload.size, port_map, 1); ds_put_cstr(string, s); free(s); } @@ -1647,7 +1657,8 @@ ofp_print_ofpst_desc_reply(struct ds *string, const struct ofp_header *oh) } static void -ofp_print_flow_stats_request(struct ds *string, const struct ofp_header *oh) +ofp_print_flow_stats_request(struct ds *string, const struct ofp_header *oh, + const struct ofputil_port_map *port_map) { struct ofputil_flow_stats_request fsr; enum ofperr error; @@ -1664,15 +1675,16 @@ ofp_print_flow_stats_request(struct ds *string, const struct ofp_header *oh) if (fsr.out_port != OFPP_ANY) { ds_put_cstr(string, " out_port="); - ofputil_format_port(fsr.out_port, string); + ofputil_format_port(fsr.out_port, port_map, string); } ds_put_char(string, ' '); - match_format(&fsr.match, string, OFP_DEFAULT_PRIORITY); + match_format(&fsr.match, port_map, string, OFP_DEFAULT_PRIORITY); } void -ofp_print_flow_stats(struct ds *string, const struct ofputil_flow_stats *fs) +ofp_print_flow_stats(struct ds *string, const struct ofputil_flow_stats *fs, + const struct ofputil_port_map *port_map) { ds_put_format(string, " %scookie=%s0x%"PRIx64", %sduration=%s", colors.param, colors.end, ntohll(fs->cookie), @@ -1709,17 +1721,18 @@ ofp_print_flow_stats(struct ds *string, const struct ofputil_flow_stats *fs) colors.param, colors.end, fs->hard_age); } - match_format(&fs->match, string, fs->priority); + match_format(&fs->match, port_map, string, fs->priority); if (string->string[string->length - 1] != ' ') { ds_put_char(string, ' '); } ds_put_format(string, "%sactions=%s", colors.actions, colors.end); - ofpacts_format(fs->ofpacts, fs->ofpacts_len, string); + ofpacts_format(fs->ofpacts, fs->ofpacts_len, port_map, string); } static void -ofp_print_flow_stats_reply(struct ds *string, const struct ofp_header *oh) +ofp_print_flow_stats_reply(struct ds *string, const struct ofp_header *oh, + const struct ofputil_port_map *port_map) { struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); struct ofpbuf ofpacts; @@ -1737,7 +1750,7 @@ ofp_print_flow_stats_reply(struct ds *string, const struct ofp_header *oh) break; } ds_put_char(string, '\n'); - ofp_print_flow_stats(string, &fs); + ofp_print_flow_stats(string, &fs, port_map); } ofpbuf_uninit(&ofpacts); } @@ -1784,7 +1797,8 @@ print_port_stat_cond(struct ds *string, const char *leader, uint64_t stat) } static void -ofp_print_ofpst_port_request(struct ds *string, const struct ofp_header *oh) +ofp_print_ofpst_port_request(struct ds *string, const struct ofp_header *oh, + const struct ofputil_port_map *port_map) { ofp_port_t ofp10_port; enum ofperr error; @@ -1796,11 +1810,12 @@ ofp_print_ofpst_port_request(struct ds *string, const struct ofp_header *oh) } ds_put_cstr(string, " port_no="); - ofputil_format_port(ofp10_port, string); + ofputil_format_port(ofp10_port, port_map, string); } static void ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh, + const struct ofputil_port_map *port_map, int verbosity) { ds_put_format(string, " %"PRIuSIZE" ports\n", ofputil_count_port_stats(oh)); @@ -1825,7 +1840,7 @@ ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh, if (ofp_to_u16(ps.port_no) < 10) { ds_put_char(string, ' '); } - ofputil_format_port(ps.port_no, string); + ofputil_format_port(ps.port_no, port_map, string); ds_put_cstr(string, ": rx "); print_port_stat(string, "pkts=", ps.stats.rx_packets, 1); @@ -1959,7 +1974,8 @@ ofp_print_queue_name(struct ds *string, uint32_t queue_id) } static void -ofp_print_ofpst_queue_request(struct ds *string, const struct ofp_header *oh) +ofp_print_ofpst_queue_request(struct ds *string, const struct ofp_header *oh, + const struct ofputil_port_map *port_map) { struct ofputil_queue_stats_request oqsr; enum ofperr error; @@ -1971,7 +1987,7 @@ ofp_print_ofpst_queue_request(struct ds *string, const struct ofp_header *oh) } ds_put_cstr(string, " port="); - ofputil_format_port(oqsr.port_no, string); + ofputil_format_port(oqsr.port_no, port_map, string); ds_put_cstr(string, " queue="); ofp_print_queue_name(string, oqsr.queue_id); @@ -1979,6 +1995,7 @@ ofp_print_ofpst_queue_request(struct ds *string, const struct ofp_header *oh) static void ofp_print_ofpst_queue_reply(struct ds *string, const struct ofp_header *oh, + const struct ofputil_port_map *port_map, int verbosity) { ds_put_format(string, " %"PRIuSIZE" queues\n", ofputil_count_queue_stats(oh)); @@ -2000,7 +2017,7 @@ ofp_print_ofpst_queue_reply(struct ds *string, const struct ofp_header *oh, } ds_put_cstr(string, " port "); - ofputil_format_port(qs.port_no, string); + ofputil_format_port(qs.port_no, port_map, string); ds_put_cstr(string, " queue "); ofp_print_queue_name(string, qs.queue_id); ds_put_cstr(string, ": "); @@ -2021,7 +2038,8 @@ ofp_print_ofpst_queue_reply(struct ds *string, const struct ofp_header *oh, static void ofp_print_ofpst_port_desc_request(struct ds *string, - const struct ofp_header *oh) + const struct ofp_header *oh, + const struct ofputil_port_map *port_map) { enum ofperr error; ofp_port_t port; @@ -2033,7 +2051,7 @@ ofp_print_ofpst_port_desc_request(struct ds *string, } ds_put_cstr(string, " port="); - ofputil_format_port(port, string); + ofputil_format_port(port, port_map, string); } static void @@ -2384,7 +2402,8 @@ nx_flow_monitor_flags_to_name(uint32_t bit) static void ofp_print_nxst_flow_monitor_request(struct ds *string, - const struct ofp_header *oh) + const struct ofp_header *oh, + const struct ofputil_port_map *port_map) { struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); for (;;) { @@ -2405,7 +2424,7 @@ ofp_print_nxst_flow_monitor_request(struct ds *string, if (request.out_port != OFPP_NONE) { ds_put_cstr(string, " out_port="); - ofputil_format_port(request.out_port, string); + ofputil_format_port(request.out_port, port_map, string); } if (request.table_id != 0xff) { @@ -2413,14 +2432,15 @@ ofp_print_nxst_flow_monitor_request(struct ds *string, } ds_put_char(string, ' '); - match_format(&request.match, string, OFP_DEFAULT_PRIORITY); + match_format(&request.match, port_map, string, OFP_DEFAULT_PRIORITY); ds_chomp(string, ' '); } } static void ofp_print_nxst_flow_monitor_reply(struct ds *string, - const struct ofp_header *oh) + const struct ofp_header *oh, + const struct ofputil_port_map *port_map) { uint64_t ofpacts_stub[1024 / 8]; struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub); @@ -2474,14 +2494,15 @@ ofp_print_nxst_flow_monitor_reply(struct ds *string, ds_put_format(string, " cookie=%#"PRIx64, ntohll(update.cookie)); ds_put_char(string, ' '); - match_format(&update.match, string, OFP_DEFAULT_PRIORITY); + match_format(&update.match, port_map, string, OFP_DEFAULT_PRIORITY); if (update.ofpacts_len) { if (string->string[string->length - 1] != ' ') { ds_put_char(string, ' '); } ds_put_cstr(string, "actions="); - ofpacts_format(update.ofpacts, update.ofpacts_len, string); + ofpacts_format(update.ofpacts, update.ofpacts_len, port_map, + string); } } } @@ -2558,7 +2579,8 @@ static void ofp_print_group(struct ds *s, uint32_t group_id, uint8_t type, const struct ovs_list *p_buckets, const struct ofputil_group_props *props, - enum ofp_version ofp_version, bool suppress_type) + enum ofp_version ofp_version, bool suppress_type, + const struct ofputil_port_map *port_map) { struct ofputil_bucket *bucket; @@ -2602,14 +2624,16 @@ ofp_print_group(struct ds *s, uint32_t group_id, uint8_t type, ds_put_format(s, "weight:%"PRIu16",", bucket->weight); } if (bucket->watch_port != OFPP_NONE) { - ds_put_format(s, "watch_port:%"PRIu32",", bucket->watch_port); + ds_put_cstr(s, "watch_port:"); + ofputil_format_port(bucket->watch_port, port_map, s); + ds_put_char(s, ','); } if (bucket->watch_group != OFPG_ANY) { ds_put_format(s, "watch_group:%"PRIu32",", bucket->watch_group); } ds_put_cstr(s, "actions="); - ofpacts_format(bucket->ofpacts, bucket->ofpacts_len, s); + ofpacts_format(bucket->ofpacts, bucket->ofpacts_len, port_map, s); ds_put_char(s, ','); } @@ -2626,7 +2650,8 @@ ofp_print_ofpst_group_desc_request(struct ds *string, } static void -ofp_print_group_desc(struct ds *s, const struct ofp_header *oh) +ofp_print_group_desc(struct ds *s, const struct ofp_header *oh, + const struct ofputil_port_map *port_map) { struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); for (;;) { @@ -2644,7 +2669,7 @@ ofp_print_group_desc(struct ds *s, const struct ofp_header *oh) ds_put_char(s, '\n'); ds_put_char(s, ' '); ofp_print_group(s, gd.group_id, gd.type, &gd.buckets, &gd.props, - oh->version, false); + oh->version, false, port_map); ofputil_uninit_group_desc(&gd); } } @@ -2746,7 +2771,8 @@ ofp_print_group_features(struct ds *string, const struct ofp_header *oh) static void ofp_print_group_mod__(struct ds *s, enum ofp_version ofp_version, - const struct ofputil_group_mod *gm) + const struct ofputil_group_mod *gm, + const struct ofputil_port_map *port_map) { bool bucket_command = false; @@ -2791,11 +2817,12 @@ ofp_print_group_mod__(struct ds *s, enum ofp_version ofp_version, } ofp_print_group(s, gm->group_id, gm->type, &gm->buckets, &gm->props, - ofp_version, bucket_command); + ofp_version, bucket_command, port_map); } static void -ofp_print_group_mod(struct ds *s, const struct ofp_header *oh) +ofp_print_group_mod(struct ds *s, const struct ofp_header *oh, + const struct ofputil_port_map *port_map) { struct ofputil_group_mod gm; int error; @@ -2805,7 +2832,7 @@ ofp_print_group_mod(struct ds *s, const struct ofp_header *oh) ofp_print_error(s, error); return; } - ofp_print_group_mod__(s, oh->version, &gm); + ofp_print_group_mod__(s, oh->version, &gm, port_map); ofputil_uninit_group_mod(&gm); } @@ -3169,7 +3196,8 @@ ofp_print_bundle_ctrl(struct ds *s, const struct ofp_header *oh) } static void -ofp_print_bundle_add(struct ds *s, const struct ofp_header *oh, int verbosity) +ofp_print_bundle_add(struct ds *s, const struct ofp_header *oh, + const struct ofputil_port_map *port_map, int verbosity) { int error; struct ofputil_bundle_add_msg badd; @@ -3186,7 +3214,8 @@ ofp_print_bundle_add(struct ds *s, const struct ofp_header *oh, int verbosity) ofp_print_bit_names(s, badd.flags, bundle_flags_to_name, ' '); ds_put_char(s, '\n'); - char *msg = ofp_to_string(badd.msg, ntohs(badd.msg->length), verbosity); + char *msg = ofp_to_string(badd.msg, ntohs(badd.msg->length), port_map, + verbosity); ds_put_and_free_cstr(s, msg); } @@ -3272,7 +3301,8 @@ ofp_print_tlv_table_reply(struct ds *s, const struct ofp_header *oh) /* This function will print the request forward message. The reason for * request forward is taken from rf.request.type */ static void -ofp_print_requestforward(struct ds *string, const struct ofp_header *oh) +ofp_print_requestforward(struct ds *string, const struct ofp_header *oh, + const struct ofputil_port_map *port_map) { struct ofputil_requestforward rf; enum ofperr error; @@ -3288,7 +3318,7 @@ ofp_print_requestforward(struct ds *string, const struct ofp_header *oh) switch (rf.reason) { case OFPRFR_GROUP_MOD: ds_put_cstr(string, "group_mod"); - ofp_print_group_mod__(string, oh->version, rf.group_mod); + ofp_print_group_mod__(string, oh->version, rf.group_mod, port_map); break; case OFPRFR_METER_MOD: @@ -3391,7 +3421,8 @@ ofp_print_nxt_ct_flush_zone(struct ds *string, const struct nx_zone_id *nzi) static void -ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, +ofp_to_string__(const struct ofp_header *oh, + const struct ofputil_port_map *port_map, enum ofpraw raw, struct ds *string, int verbosity) { const void *msg = oh; @@ -3415,7 +3446,7 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, break; case OFPTYPE_GROUP_DESC_STATS_REPLY: - ofp_print_group_desc(string, oh); + ofp_print_group_desc(string, oh, port_map); break; case OFPTYPE_GROUP_FEATURES_STATS_REQUEST: @@ -3427,7 +3458,7 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, break; case OFPTYPE_GROUP_MOD: - ofp_print_group_mod(string, oh); + ofp_print_group_mod(string, oh, port_map); break; case OFPTYPE_TABLE_FEATURES_STATS_REQUEST: @@ -3445,7 +3476,7 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, break; case OFPTYPE_ERROR: - ofp_print_error_msg(string, oh); + ofp_print_error_msg(string, oh, port_map); break; case OFPTYPE_ECHO_REQUEST: @@ -3472,11 +3503,11 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, break; case OFPTYPE_PACKET_IN: - ofp_print_packet_in(string, oh, verbosity); + ofp_print_packet_in(string, oh, port_map, verbosity); break; case OFPTYPE_FLOW_REMOVED: - ofp_print_flow_removed(string, oh); + ofp_print_flow_removed(string, oh, port_map); break; case OFPTYPE_PORT_STATUS: @@ -3484,15 +3515,15 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, break; case OFPTYPE_PACKET_OUT: - ofp_print_packet_out(string, oh, verbosity); + ofp_print_packet_out(string, oh, port_map, verbosity); break; case OFPTYPE_FLOW_MOD: - ofp_print_flow_mod(string, oh, verbosity); + ofp_print_flow_mod(string, oh, port_map, verbosity); break; case OFPTYPE_PORT_MOD: - ofp_print_port_mod(string, oh); + ofp_print_port_mod(string, oh, port_map); break; case OFPTYPE_TABLE_MOD: @@ -3508,11 +3539,11 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, break; case OFPTYPE_QUEUE_GET_CONFIG_REQUEST: - ofp_print_queue_get_config_request(string, oh); + ofp_print_queue_get_config_request(string, oh, port_map); break; case OFPTYPE_QUEUE_GET_CONFIG_REPLY: - ofp_print_queue_get_config_reply(string, oh); + ofp_print_queue_get_config_reply(string, oh, port_map); break; case OFPTYPE_ROLE_REQUEST: @@ -3524,7 +3555,7 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, break; case OFPTYPE_REQUESTFORWARD: - ofp_print_requestforward(string, oh); + ofp_print_requestforward(string, oh, port_map); break; case OFPTYPE_TABLE_STATUS: @@ -3560,7 +3591,7 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, case OFPTYPE_FLOW_STATS_REQUEST: case OFPTYPE_AGGREGATE_STATS_REQUEST: ofp_print_stats(string, oh); - ofp_print_flow_stats_request(string, oh); + ofp_print_flow_stats_request(string, oh, port_map); break; case OFPTYPE_TABLE_STATS_REQUEST: @@ -3569,12 +3600,12 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, case OFPTYPE_PORT_STATS_REQUEST: ofp_print_stats(string, oh); - ofp_print_ofpst_port_request(string, oh); + ofp_print_ofpst_port_request(string, oh, port_map); break; case OFPTYPE_QUEUE_STATS_REQUEST: ofp_print_stats(string, oh); - ofp_print_ofpst_queue_request(string, oh); + ofp_print_ofpst_queue_request(string, oh, port_map); break; case OFPTYPE_DESC_STATS_REPLY: @@ -3584,17 +3615,17 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, case OFPTYPE_FLOW_STATS_REPLY: ofp_print_stats(string, oh); - ofp_print_flow_stats_reply(string, oh); + ofp_print_flow_stats_reply(string, oh, port_map); break; case OFPTYPE_QUEUE_STATS_REPLY: ofp_print_stats(string, oh); - ofp_print_ofpst_queue_reply(string, oh, verbosity); + ofp_print_ofpst_queue_reply(string, oh, port_map, verbosity); break; case OFPTYPE_PORT_STATS_REPLY: ofp_print_stats(string, oh); - ofp_print_ofpst_port_reply(string, oh, verbosity); + ofp_print_ofpst_port_reply(string, oh, port_map, verbosity); break; case OFPTYPE_TABLE_STATS_REPLY: @@ -3609,7 +3640,7 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, case OFPTYPE_PORT_DESC_STATS_REQUEST: ofp_print_stats(string, oh); - ofp_print_ofpst_port_desc_request(string, oh); + ofp_print_ofpst_port_desc_request(string, oh, port_map); break; case OFPTYPE_PORT_DESC_STATS_REPLY: @@ -3651,11 +3682,11 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, break; case OFPTYPE_FLOW_MONITOR_STATS_REQUEST: - ofp_print_nxst_flow_monitor_request(string, msg); + ofp_print_nxst_flow_monitor_request(string, msg, port_map); break; case OFPTYPE_FLOW_MONITOR_STATS_REPLY: - ofp_print_nxst_flow_monitor_reply(string, msg); + ofp_print_nxst_flow_monitor_reply(string, msg, port_map); break; case OFPTYPE_BUNDLE_CONTROL: @@ -3663,7 +3694,7 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, break; case OFPTYPE_BUNDLE_ADD_MESSAGE: - ofp_print_bundle_add(string, msg, verbosity); + ofp_print_bundle_add(string, msg, port_map, verbosity); break; case OFPTYPE_NXT_TLV_TABLE_MOD: @@ -3678,7 +3709,7 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, break; case OFPTYPE_NXT_RESUME: - ofp_print_packet_in(string, msg, verbosity); + ofp_print_packet_in(string, msg, port_map, verbosity); break; case OFPTYPE_IPFIX_BRIDGE_STATS_REQUEST: break; @@ -3702,7 +3733,8 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw, * verbosity and higher numbers increase verbosity. The caller is responsible * for freeing the string. */ char * -ofp_to_string(const void *oh_, size_t len, int verbosity) +ofp_to_string(const void *oh_, size_t len, + const struct ofputil_port_map *port_map, int verbosity) { struct ds string = DS_EMPTY_INITIALIZER; const struct ofp_header *oh = oh_; @@ -3735,7 +3767,7 @@ ofp_to_string(const void *oh_, size_t len, int verbosity) error = ofpraw_decode(&raw, oh); if (!error) { - ofp_to_string__(oh, raw, &string, verbosity); + ofp_to_string__(oh, port_map, raw, &string, verbosity); if (verbosity >= 5) { if (ds_last(&string) != '\n') { ds_put_char(&string, '\n'); @@ -3765,9 +3797,10 @@ print_and_free(FILE *stream, char *string) * given 'verbosity' level. 0 is a minimal amount of verbosity and higher * numbers increase verbosity. */ void -ofp_print(FILE *stream, const void *oh, size_t len, int verbosity) +ofp_print(FILE *stream, const void *oh, size_t len, + const struct ofputil_port_map *port_map, int verbosity) { - print_and_free(stream, ofp_to_string(oh, len, verbosity)); + print_and_free(stream, ofp_to_string(oh, len, port_map, verbosity)); } /* Dumps the contents of the Ethernet frame in the 'len' bytes starting at diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 8f1c40227..157b66b93 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -33,6 +33,7 @@ #include "id-pool.h" #include "openflow/netronome-ext.h" #include "openvswitch/dynamic-string.h" +#include "openvswitch/json.h" #include "openvswitch/meta-flow.h" #include "openvswitch/ofp-actions.h" #include "openvswitch/ofp-errors.h" @@ -7270,7 +7271,8 @@ ofputil_port_to_ofp11(ofp_port_t ofp10_port) /* Stores the port number represented by 's' into '*portp'. 's' may be an * integer or, for reserved ports, the standard OpenFlow name for the port - * (e.g. "LOCAL"). + * (e.g. "LOCAL"). If 'port_map' is nonnull, also accepts names in it (quoted + * or unquoted). * * Returns true if successful, false if 's' is not a valid OpenFlow port number * or name. The caller should issue an error message in this case, because @@ -7282,7 +7284,9 @@ ofputil_port_to_ofp11(ofp_port_t ofp10_port) * of OpenFlow 1.1+ port numbers, mapping those port numbers into the 16-bit * range as described in include/openflow/openflow-1.1.h. */ bool -ofputil_port_from_string(const char *s, ofp_port_t *portp) +ofputil_port_from_string(const char *s, + const struct ofputil_port_map *port_map, + ofp_port_t *portp) { unsigned int port32; /* int is at least 32 bits wide. */ @@ -7301,7 +7305,8 @@ ofputil_port_from_string(const char *s, ofp_port_t *portp) } else if (port32 <= ofp_to_u16(OFPP_LAST_RESV)) { char name[OFP10_MAX_PORT_NAME_LEN]; - ofputil_port_to_string(u16_to_ofp(port32), name, sizeof name); + ofputil_port_to_string(u16_to_ofp(port32), NULL, + name, sizeof name); VLOG_WARN_ONCE("referring to port %s as %"PRIu32" is deprecated " "for compatibility with OpenFlow 1.1 and later", name, port32); @@ -7334,20 +7339,89 @@ ofputil_port_from_string(const char *s, ofp_port_t *portp) return true; } } + + ofp_port_t ofp_port = OFPP_NONE; + if (s[0] != '"') { + ofp_port = ofputil_port_map_get_number(port_map, s); + } else { + size_t length = strlen(s); + char *name = NULL; + if (length > 1 + && s[length - 1] == '"' + && json_string_unescape(s + 1, length - 2, &name)) { + ofp_port = ofputil_port_map_get_number(port_map, name); + } + free(name); + } + if (ofp_port != OFPP_NONE) { + *portp = ofp_port; + return true; + } + return false; } } +const char * +ofputil_port_get_reserved_name(ofp_port_t port) +{ + switch (port) { +#define OFPUTIL_NAMED_PORT(NAME) case OFPP_##NAME: return #NAME; + OFPUTIL_NAMED_PORTS +#undef OFPUTIL_NAMED_PORT + + default: + return NULL; + } +} + +/* A port name doesn't need to be quoted if it is alphanumeric and starts with + * a letter. */ +static bool +port_name_needs_quotes(const char *port_name) +{ + if (!isalpha((unsigned char) port_name[0])) { + return true; + } + + for (const char *p = port_name + 1; *p; p++) { + if (!isalnum((unsigned char) *p)) { + return true; + } + } + return false; +} + +static void +put_port_name(const char *port_name, struct ds *s) +{ + if (port_name_needs_quotes(port_name)) { + json_string_escape(port_name, s); + } else { + ds_put_cstr(s, port_name); + } +} + /* Appends to 's' a string representation of the OpenFlow port number 'port'. * Most ports' string representation is just the port number, but for special * ports, e.g. OFPP_LOCAL, it is the name, e.g. "LOCAL". */ void -ofputil_format_port(ofp_port_t port, struct ds *s) +ofputil_format_port(ofp_port_t port, const struct ofputil_port_map *port_map, + struct ds *s) { - char name[OFP10_MAX_PORT_NAME_LEN]; + const char *reserved_name = ofputil_port_get_reserved_name(port); + if (reserved_name) { + ds_put_cstr(s, reserved_name); + return; + } - ofputil_port_to_string(port, name, sizeof name); - ds_put_cstr(s, name); + const char *port_name = ofputil_port_map_get_name(port_map, port); + if (port_name) { + put_port_name(port_name, s); + return; + } + + ds_put_format(s, "%"PRIu32, port); } /* Puts in the 'bufsize' byte in 'namebuf' a null-terminated string @@ -7356,22 +7430,149 @@ ofputil_format_port(ofp_port_t port, struct ds *s) * by name, e.g. "LOCAL". */ void ofputil_port_to_string(ofp_port_t port, - char namebuf[OFP10_MAX_PORT_NAME_LEN], size_t bufsize) + const struct ofputil_port_map *port_map, + char *namebuf, size_t bufsize) { - switch (port) { -#define OFPUTIL_NAMED_PORT(NAME) \ - case OFPP_##NAME: \ - ovs_strlcpy(namebuf, #NAME, bufsize); \ - break; - OFPUTIL_NAMED_PORTS -#undef OFPUTIL_NAMED_PORT + const char *reserved_name = ofputil_port_get_reserved_name(port); + if (reserved_name) { + ovs_strlcpy(namebuf, reserved_name, bufsize); + return; + } - default: - snprintf(namebuf, bufsize, "%"PRIu32, port); - break; + const char *port_name = ofputil_port_map_get_name(port_map, port); + if (port_name) { + struct ds s = DS_EMPTY_INITIALIZER; + put_port_name(port_name, &s); + ovs_strlcpy(namebuf, ds_cstr(&s), bufsize); + ds_destroy(&s); + return; } + + snprintf(namebuf, bufsize, "%"PRIu32, port); } + +/* ofputil_port_map. */ +struct ofputil_port_map_node { + struct hmap_node name_node; + struct hmap_node number_node; + ofp_port_t ofp_port; /* Port number. */ + char *name; /* Port name. */ + + /* OpenFlow doesn't require port names to be unique, although that's the + * only sensible way. However, even in Open vSwitch it's possible for two + * ports to appear to have the same name if their names are longer than the + * maximum length supported by a given version of OpenFlow. So, we guard + * against duplicate names to avoid giving unexpected results in this + * corner case. + * + * OpenFlow does require port numbers to be unique. We check for duplicate + * ports numbers just in case a switch has a bug. */ + bool duplicate; +}; +void +ofputil_port_map_init(struct ofputil_port_map *map) +{ + hmap_init(&map->by_name); + hmap_init(&map->by_number); +} + +static struct ofputil_port_map_node * +ofputil_port_map_find_by_name(const struct ofputil_port_map *map, + const char *name) +{ + struct ofputil_port_map_node *node; + + HMAP_FOR_EACH_WITH_HASH (node, name_node, hash_string(name, 0), + &map->by_name) { + if (!strcmp(name, node->name)) { + return node; + } + } + return NULL; +} + +static struct ofputil_port_map_node * +ofputil_port_map_find_by_number(const struct ofputil_port_map *map, + ofp_port_t ofp_port) +{ + struct ofputil_port_map_node *node; + + HMAP_FOR_EACH_IN_BUCKET (node, number_node, hash_ofp_port(ofp_port), + &map->by_number) { + if (node->ofp_port == ofp_port) { + return node; + } + } + return NULL; +} + +void +ofputil_port_map_put(struct ofputil_port_map *map, + ofp_port_t ofp_port, const char *name) +{ + struct ofputil_port_map_node *node; + + /* Look for duplicate name. */ + node = ofputil_port_map_find_by_name(map, name); + if (node) { + if (node->ofp_port != ofp_port) { + node->duplicate = true; + } + return; + } + + /* Look for duplicate number. */ + node = ofputil_port_map_find_by_number(map, ofp_port); + if (node) { + node->duplicate = true; + return; + } + + /* Add new node. */ + node = xmalloc(sizeof *node); + hmap_insert(&map->by_number, &node->number_node, hash_ofp_port(ofp_port)); + hmap_insert(&map->by_name, &node->name_node, hash_string(name, 0)); + node->ofp_port = ofp_port; + node->name = xstrdup(name); + node->duplicate = false; +} + +const char * +ofputil_port_map_get_name(const struct ofputil_port_map *map, + ofp_port_t ofp_port) +{ + struct ofputil_port_map_node *node + = map ? ofputil_port_map_find_by_number(map, ofp_port) : NULL; + return node && !node->duplicate ? node->name : NULL; +} + +ofp_port_t +ofputil_port_map_get_number(const struct ofputil_port_map *map, + const char *name) +{ + struct ofputil_port_map_node *node + = map ? ofputil_port_map_find_by_name(map, name) : NULL; + return node && !node->duplicate ? node->ofp_port : OFPP_NONE; +} + +void +ofputil_port_map_destroy(struct ofputil_port_map *map) +{ + if (map) { + struct ofputil_port_map_node *node, *next; + + HMAP_FOR_EACH_SAFE (node, next, name_node, &map->by_name) { + hmap_remove(&map->by_name, &node->name_node); + hmap_remove(&map->by_number, &node->number_node); + free(node->name); + free(node); + } + hmap_destroy(&map->by_name); + hmap_destroy(&map->by_number); + } +} + /* Stores the group id represented by 's' into '*group_idp'. 's' may be an * integer or, for reserved group IDs, the standard OpenFlow name for the group * (either "ANY" or "ALL"). @@ -7547,13 +7748,15 @@ ofputil_normalize_match__(struct match *match, bool may_log) /* Log any changes. */ if (!flow_wildcards_equal(&wc, &match->wc)) { bool log = may_log && !VLOG_DROP_INFO(&bad_ofmsg_rl); - char *pre = log ? match_to_string(match, OFP_DEFAULT_PRIORITY) : NULL; + char *pre = (log + ? match_to_string(match, NULL, OFP_DEFAULT_PRIORITY) + : NULL); match->wc = wc; match_zero_wildcarded_fields(match); if (log) { - char *post = match_to_string(match, OFP_DEFAULT_PRIORITY); + char *post = match_to_string(match, NULL, OFP_DEFAULT_PRIORITY); VLOG_INFO("normalization changed ofp_match, details:"); VLOG_INFO(" pre: %s", pre); VLOG_INFO("post: %s", post); diff --git a/lib/vconn.c b/lib/vconn.c index 57e623a92..6997eaa96 100644 --- a/lib/vconn.c +++ b/lib/vconn.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2016 Nicira, Inc. + * Copyright (c) 2008-2017 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -495,7 +495,7 @@ vcs_recv_hello(struct vconn *vconn) ofpbuf_delete(b); return; } else { - char *s = ofp_to_string(b->data, b->size, 1); + char *s = ofp_to_string(b->data, b->size, NULL, 1); VLOG_WARN_RL(&bad_ofmsg_rl, "%s: received message while expecting hello: %s", vconn->name, s); @@ -641,7 +641,7 @@ do_recv(struct vconn *vconn, struct ofpbuf **msgp) if (!retval) { COVERAGE_INC(vconn_received); if (VLOG_IS_DBG_ENABLED()) { - char *s = ofp_to_string((*msgp)->data, (*msgp)->size, 1); + char *s = ofp_to_string((*msgp)->data, (*msgp)->size, NULL, 1); VLOG_DBG_RL(&ofmsg_rl, "%s: received: %s", vconn->name, s); free(s); } @@ -681,7 +681,7 @@ do_send(struct vconn *vconn, struct ofpbuf *msg) COVERAGE_INC(vconn_sent); retval = (vconn->vclass->send)(vconn, msg); } else { - char *s = ofp_to_string(msg->data, msg->size, 1); + char *s = ofp_to_string(msg->data, msg->size, NULL, 1); retval = (vconn->vclass->send)(vconn, msg); if (retval != EAGAIN) { VLOG_DBG_RL(&ofmsg_rl, "%s: sent (%s): %s", @@ -970,7 +970,7 @@ recv_flow_stats_reply(struct vconn *vconn, ovs_be32 send_xid, error = ofptype_decode(&type, reply->data); if (error || type != OFPTYPE_FLOW_STATS_REPLY) { VLOG_WARN_RL(&rl, "received bad reply: %s", - ofp_to_string(reply->data, reply->size, 1)); + ofp_to_string(reply->data, reply->size, NULL, 1)); return EPROTO; } } |