Post-v2.7.0
---------------------
+ - ovs-ofctl can now accept and display port names in place of numbers. By
+ default it always accepts names and in interactive use it displays them;
+ use --names or --no-names to override. See ovs-ofctl(8) for details.
- Tunnels:
* Added support to set packet mark for tunnel endpoint using
`egress_pkt_mark` OVSDB option.
/*
- * 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.
#include "openvswitch/tun-metadata.h"
struct ds;
+struct ofputil_port_map;
/* A flow classification match.
*
void match_init_hidden_fields(struct match *);
bool match_has_default_hidden_fields(const struct match *);
-void match_format(const struct match *, struct ds *, int priority);
-char *match_to_string(const struct match *, int priority);
-void match_print(const struct match *);
+void match_format(const struct match *, const struct ofputil_port_map *,
+ struct ds *, int priority);
+char *match_to_string(const struct match *, const struct ofputil_port_map *,
+ int priority);
+void match_print(const struct match *, const struct ofputil_port_map *);
\f
/* Compressed match. */
bool minimatch_matches_flow(const struct minimatch *, const struct flow *);
void minimatch_format(const struct minimatch *, const struct tun_table *,
+ const struct ofputil_port_map *,
struct ds *, int priority);
-char *minimatch_to_string(const struct minimatch *, int priority);
+char *minimatch_to_string(const struct minimatch *,
+ const struct ofputil_port_map *, int priority);
#endif /* match.h */
struct ds;
struct match;
+struct ofputil_port_map;
struct ofputil_tlv_table_mod;
/* Open vSwitch fields
/* Parsing and formatting. */
char *mf_parse(const struct mf_field *, const char *,
+ const struct ofputil_port_map *,
union mf_value *value, union mf_value *mask);
-char *mf_parse_value(const struct mf_field *, const char *, union mf_value *);
+char *mf_parse_value(const struct mf_field *, const char *,
+ const struct ofputil_port_map *, union mf_value *);
void mf_format(const struct mf_field *,
const union mf_value *value, const union mf_value *mask,
+ const struct ofputil_port_map *,
struct ds *);
void mf_format_subvalue(const union mf_subvalue *subvalue, struct ds *s);
uint32_t ofpacts_get_meter(const struct ofpact[], size_t ofpacts_len);
/* Formatting and parsing ofpacts. */
-void ofpacts_format(const struct ofpact[], size_t ofpacts_len, struct ds *);
-char *ofpacts_parse_actions(const char *, struct ofpbuf *ofpacts,
+void ofpacts_format(const struct ofpact[], size_t ofpacts_len,
+ const struct ofputil_port_map *, struct ds *);
+char *ofpacts_parse_actions(const char *, const struct ofputil_port_map *,
+ struct ofpbuf *ofpacts,
enum ofputil_protocol *usable_protocols)
OVS_WARN_UNUSED_RESULT;
-char *ofpacts_parse_instructions(const char *, struct ofpbuf *ofpacts,
+char *ofpacts_parse_instructions(const char *, const struct ofputil_port_map *,
+ struct ofpbuf *ofpacts,
enum ofputil_protocol *usable_protocols)
OVS_WARN_UNUSED_RESULT;
const char *ofpact_name(enum ofpact_type);
/*
- * 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.
enum ofputil_protocol;
char *parse_ofp_str(struct ofputil_flow_mod *, int command, const char *str_,
+ const struct ofputil_port_map *,
enum ofputil_protocol *usable_protocols)
OVS_WARN_UNUSED_RESULT;
char *parse_ofp_flow_mod_str(struct ofputil_flow_mod *, const char *string,
- int command,
+ const struct ofputil_port_map *, int command,
enum ofputil_protocol *usable_protocols)
OVS_WARN_UNUSED_RESULT;
char *parse_ofp_packet_out_str(struct ofputil_packet_out *po, const char *str_,
+ const struct ofputil_port_map *,
enum ofputil_protocol *usable_protocols)
OVS_WARN_UNUSED_RESULT;
uint32_t *usable_versions)
OVS_WARN_UNUSED_RESULT;
-char *parse_ofp_flow_mod_file(const char *file_name, int command,
+char *parse_ofp_flow_mod_file(const char *file_name,
+ const struct ofputil_port_map *, int command,
struct ofputil_flow_mod **fms, size_t *n_fms,
enum ofputil_protocol *usable_protocols)
OVS_WARN_UNUSED_RESULT;
char *parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *,
bool aggregate, const char *string,
+ const struct ofputil_port_map *,
enum ofputil_protocol *usable_protocols)
OVS_WARN_UNUSED_RESULT;
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 *parse_ofp_meter_mod_str(struct ofputil_meter_mod *, const char *string,
int command,
char *parse_flow_monitor_request(struct ofputil_flow_monitor_request *,
const char *,
+ const struct ofputil_port_map *port_map,
enum ofputil_protocol *usable_protocols)
OVS_WARN_UNUSED_RESULT;
-char *parse_ofp_group_mod_file(const char *file_name, int command,
+char *parse_ofp_group_mod_file(const char *file_name,
+ const struct ofputil_port_map *, int command,
struct ofputil_group_mod **gms, size_t *n_gms,
enum ofputil_protocol *usable_protocols)
OVS_WARN_UNUSED_RESULT;
char *parse_ofp_group_mod_str(struct ofputil_group_mod *, int command,
const char *string,
+ const struct ofputil_port_map *,
enum ofputil_protocol *usable_protocols)
OVS_WARN_UNUSED_RESULT;
char *parse_ofp_bundle_file(const char *file_name,
+ const struct ofputil_port_map *,
struct ofputil_bundle_msg **, size_t *n_bms,
enum ofputil_protocol *)
OVS_WARN_UNUSED_RESULT;
extern "C" {
#endif
-void ofp_print(FILE *, const void *, size_t, int verbosity);
+void ofp_print(FILE *, const void *, size_t, const struct ofputil_port_map *,
+ int verbosity);
void ofp_print_packet(FILE *stream, const void *data,
size_t len, ovs_be32 packet_type);
void ofp_print_dp_packet(FILE *stream, const struct dp_packet *packet);
-void ofp10_match_print(struct ds *, const struct ofp10_match *, int verbosity);
+void ofp10_match_print(struct ds *, const struct ofp10_match *,
+ const struct ofputil_port_map *, int verbosity);
-char *ofp_to_string(const void *, size_t, int verbosity);
-char *ofp10_match_to_string(const struct ofp10_match *, int verbosity);
+char *ofp_to_string(const void *, size_t, const struct ofputil_port_map *,
+ int verbosity);
+char *ofp10_match_to_string(const struct ofp10_match *,
+ const struct ofputil_port_map *, int verbosity);
char *ofp_packet_to_string(const void *data, size_t len, ovs_be32 packet_type);
char *ofp_dp_packet_to_string(const struct dp_packet *packet);
-void ofp_print_flow_stats(struct ds *, const struct ofputil_flow_stats *);
void ofp_print_version(const struct ofp_header *, struct ds *);
void ofp_print_table_features(
struct ds *, const struct ofputil_table_features *features,
const struct ofputil_table_features *prev_features,
const struct ofputil_table_stats *stats,
const struct ofputil_table_stats *prev_stats);
+\f
+void ofp_print_flow_stats(struct ds *, const struct ofputil_flow_stats *,
+ const struct ofputil_port_map *);
#ifdef __cplusplus
}
#include <stddef.h>
#include <stdint.h>
#include "openvswitch/flow.h"
+#include "openvswitch/hmap.h"
#include "openvswitch/list.h"
#include "openvswitch/match.h"
#include "openvswitch/meta-flow.h"
struct ofpact_set_field;
struct vl_mff_map;
+/* Mapping between port numbers and names. */
+struct ofputil_port_map {
+ struct hmap by_name;
+ struct hmap by_number;
+};
+
+#define OFPUTIL_PORT_MAP_INITIALIZER(MAP) \
+ { HMAP_INITIALIZER(&(MAP)->by_name), HMAP_INITIALIZER(&(MAP)->by_number) }
+
+void ofputil_port_map_init(struct ofputil_port_map *);
+const char *ofputil_port_map_get_name(const struct ofputil_port_map *,
+ ofp_port_t);
+ofp_port_t ofputil_port_map_get_number(const struct ofputil_port_map *,
+ const char *name);
+void ofputil_port_map_put(struct ofputil_port_map *,
+ ofp_port_t, const char *name);
+void ofputil_port_map_destroy(struct ofputil_port_map *);
+
/* Port numbers. */
enum ofperr ofputil_port_from_ofp11(ovs_be32 ofp11_port,
ofp_port_t *ofp10_port);
ovs_be32 ofputil_port_to_ofp11(ofp_port_t ofp10_port);
-bool ofputil_port_from_string(const char *, ofp_port_t *portp);
-void ofputil_format_port(ofp_port_t port, struct ds *);
-void ofputil_port_to_string(ofp_port_t, char namebuf[OFP10_MAX_PORT_NAME_LEN],
- size_t bufsize);
+bool ofputil_port_from_string(const char *, const struct ofputil_port_map *,
+ ofp_port_t *portp);
+const char *ofputil_port_get_reserved_name(ofp_port_t);
+void ofputil_format_port(ofp_port_t port, const struct ofputil_port_map *,
+ struct ds *);
+void ofputil_port_to_string(ofp_port_t, const struct ofputil_port_map *,
+ char *namebuf, size_t bufsize);
/* Group numbers. */
enum { MAX_GROUP_NAME_LEN = INT_STRLEN(uint32_t) };
-/* 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.
* 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)
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);
* 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;
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);
* 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;
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);
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;
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);
-/* 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.
struct match;
struct ofpact_bundle;
struct ofpbuf;
+struct ofputil_port_map;
/* NXAST_BUNDLE helper functions.
*
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 */
/*
- * 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.
/* 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. */
/*
- * 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.
* 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);
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;
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);
out_dpifclose:
odp_portno_names_destroy(&portno_names);
- simap_destroy(&names_portno);
hmap_destroy(&portno_names);
dpif_close(dpif);
out_freefilter:
}
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);
}
}
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;
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);
}
struct flow_wildcards;
struct minimask;
struct dp_packet;
+struct ofputil_port_map;
struct pkt_metadata;
struct match;
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,
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);
* 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)
{
/* 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. */
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);
/* 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;
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;
}
*
* 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;
}
/* 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;
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);
/*
- * 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.
struct ofpbuf;
struct ofpact_learn;
struct ofputil_flow_mod;
+struct ofputil_port_map;
struct nx_action_learn;
/* NXAST_LEARN helper functions.
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 */
/*
- * 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.
} 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);
}
/* 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;
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, ',');
}
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++) {
}
/* 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);
}
}
/* 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);
}
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;
* 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;
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:
/* 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;
}
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) {
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 */
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, ',');
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,
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);
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);
}
}
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);
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;
}
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);
}
}
\f
}
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);
}
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;
}
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) {
}
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;
}
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);
}
\f
}
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);
}
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);
}
\f
/* Set VLAN actions. */
}
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;
}
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",
}
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;
}
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",
}
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;
}
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"
}
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;
}
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));
}
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));
}
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));
}
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;
}
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);
}
}
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;
}
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);
}
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;
}
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);
}
}
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",
}
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",
}
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);
}
}
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);
}
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);
}
&& (!(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);
* 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;
}
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;
}
* 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;
}
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);
}
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;
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);
}
}
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);
}
}
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') {
}
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;
}
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);
}
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),
}
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);
}
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,
* 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);
}
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,
}
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);
}
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);
}
}
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;
}
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));
}
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;
}
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));
}
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
}
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);
}
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);
}
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);
}
}
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);
}
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) {
}
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;
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 {
}
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) {
}
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);
}
\f
/* Action structure for NXAST_CONJUNCTION. */
}
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,
}
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;
}
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);
}
}
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;
}
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);
}
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);
}
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);
}
}
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();
}
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",
}
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;
}
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);
}
\f
* 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);
} 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")) {
}
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
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);
}
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);
}
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);
}
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'.
* 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);
} 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;
/* 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;
}
}
-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) {
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);
}
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);
}
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);
-}\f
+}
+\f
/* NAT action. */
/* Which optional fields are present? */
}
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);
* 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);
}
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. */
}
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);
}
\f
}
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;
}
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);
}
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);
}
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);
}
}
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);
* 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. */
}
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);
}
\f
}
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;
}
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));
}
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);
}
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);
/* 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
}
/* 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);
ds_put_char(string, ',');
}
- ofpact_format(a, string);
+ ofpact_format(a, port_map, string);
}
}
}
}
\f
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:
* 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)
{
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")) {
} 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);
}
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;
}
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)
{
*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;
* 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
* 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 *
/*
- * 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.
* 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;
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);
}
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);
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 {
|| !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 {
*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);
}
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) {
* 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;
* 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;
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;
}
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;
}
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) {
* 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;
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);
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);
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;
* 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
* 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)
{
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;
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;
}
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;
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);
}
}
}
}
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;
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);
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) {
}
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;
}
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;
}
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 {
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;
}
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;
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;
}
* 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)
{
*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;
* 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)
{
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;
}
} 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;
}
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);
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;
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,
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');
}
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;
}
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);
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));
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, '*');
}
}
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);
}
}
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,
}
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;
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;
/* 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;
}
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, ' ');
}
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);
}
}
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;
}
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,
}
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;
}
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)) {
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;
}
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=");
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));
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');
}
}
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;
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);
}
}
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;
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),
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;
break;
}
ds_put_char(string, '\n');
- ofp_print_flow_stats(string, &fs);
+ ofp_print_flow_stats(string, &fs, port_map);
}
ofpbuf_uninit(&ofpacts);
}
}
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;
}
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));
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);
}
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;
}
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);
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));
}
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, ": ");
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;
}
ds_put_cstr(string, " port=");
- ofputil_format_port(port, string);
+ ofputil_format_port(port, port_map, string);
}
static void
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 (;;) {
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) {
}
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);
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);
}
}
}
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;
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, ',');
}
}
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 (;;) {
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);
}
}
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;
}
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;
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);
}
}
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;
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);
}
/* 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;
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:
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;
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:
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:
break;
case OFPTYPE_ERROR:
- ofp_print_error_msg(string, oh);
+ ofp_print_error_msg(string, oh, port_map);
break;
case OFPTYPE_ECHO_REQUEST:
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:
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:
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:
break;
case OFPTYPE_REQUESTFORWARD:
- ofp_print_requestforward(string, oh);
+ ofp_print_requestforward(string, oh, port_map);
break;
case OFPTYPE_TABLE_STATUS:
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:
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:
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:
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:
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:
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:
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;
* 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_;
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');
* 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
#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"
/* 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
* 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. */
} 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);
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
* 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);
}
+\f
+/* 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);
+ }
+}
+\f
/* 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").
/* 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);
/*
- * 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.
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);
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);
}
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",
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;
}
}
/*
- * 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.
RECIRC_RULE_PRIORITY, 0,
&ofpacts, pr_op->pr_rule);
if (error) {
- char *err_s = match_to_string(&pr_op->match,
+ char *err_s = match_to_string(&pr_op->match, NULL,
RECIRC_RULE_PRIORITY);
VLOG_ERR("failed to add post recirculation flow %s", err_s);
&pr_op->match,
RECIRC_RULE_PRIORITY);
if (error) {
- char *err_s = match_to_string(&pr_op->match,
+ char *err_s = match_to_string(&pr_op->match, NULL,
RECIRC_RULE_PRIORITY);
VLOG_ERR("failed to remove post recirculation flow %s", err_s);
goto exit;
}
+ struct ofputil_port_map map = OFPUTIL_PORT_MAP_INITIALIZER(&map);
+ const struct ofport *ofport;
+ HMAP_FOR_EACH (ofport, hmap_node, &(*ofprotop)->up.ports) {
+ ofputil_port_map_put(&map, ofport->ofp_port,
+ netdev_get_name(ofport->netdev));
+ }
err = parse_ofp_exact_flow(flow, NULL,
ofproto_get_tun_tab(&(*ofprotop)->up),
- argv[argc - 1], NULL);
+ argv[argc - 1], &map);
+ ofputil_port_map_destroy(&map);
if (err) {
m_err = xasprintf("Bad openflow flow syntax: %s", err);
free(err);
ofpbuf_init(&ofpacts, 0);
/* Parse actions. */
- error = ofpacts_parse_actions(argv[--argc], &ofpacts, &usable_protocols);
+ error = ofpacts_parse_actions(argv[--argc], NULL,
+ &ofpacts, &usable_protocols);
if (error) {
unixctl_command_reply_error(conn, error);
free(error);
* xlate_in_init() initializes actset_output to OFPP_UNSET. */
struct flow initial_flow = xin.flow;
ds_put_cstr(output, "Flow: ");
- flow_format(output, &initial_flow);
+ flow_format(output, &initial_flow, NULL);
ds_put_char(output, '\n');
struct xlate_out xout;
if (flow_equal(&initial_flow, &xin.flow)) {
ds_put_cstr(output, "unchanged");
} else {
- flow_format(output, &xin.flow);
+ flow_format(output, &xin.flow, NULL);
}
ds_put_char(output, '\n');
ds_put_cstr(output, "Megaflow: ");
struct match match;
match_init(&match, flow, &wc);
- match_format(&match, output, OFP_DEFAULT_PRIORITY);
+ match_format(&match, NULL, output, OFP_DEFAULT_PRIORITY);
ds_put_char(output, '\n');
ds_put_cstr(output, "Datapath actions: ");
oftrace_report(ctx->xin->trace, OFT_ERROR, ds_cstr(&s));
} else {
ds_put_cstr(&s, " while processing ");
- flow_format(&s, &ctx->base_flow);
+ flow_format(&s, &ctx->base_flow, NULL);
ds_put_format(&s, " on bridge %s", ctx->xbridge->name);
VLOG_WARN("%s", ds_cstr(&s));
}
if (OVS_UNLIKELY(ctx->xin->trace)) {
struct ds s = DS_EMPTY_INITIALIZER;
ds_put_format(&s, "%s: ", title);
- ofpacts_format(ofpacts, ofpacts_len, &s);
+ ofpacts_format(ofpacts, ofpacts_len, NULL, &s);
oftrace_report(ctx->xin->trace, type, ds_cstr(&s));
ds_destroy(&s);
}
ofpacts_execute_action_set(&action_list, &ctx->action_set);
if (action_list.size) {
struct ds s = DS_EMPTY_INITIALIZER;
- ofpacts_format(action_list.data, action_list.size, &s);
+ ofpacts_format(action_list.data, action_list.size, NULL, &s);
xlate_report(ctx, OFT_DETAIL, "action set %s: %s",
verb, ds_cstr(&s));
ds_destroy(&s);
} else {
minimatch_format(&rule->up.cr.match,
ofproto_get_tun_tab(&ctx->xin->ofproto->up),
- &s, OFP_DEFAULT_PRIORITY);
+ NULL, &s, OFP_DEFAULT_PRIORITY);
if (ds_last(&s) != ' ') {
ds_put_cstr(&s, ", ");
}
if (sf->ofs == 0 && sf->n_bits >= sf->field->n_bits) {
union mf_value value;
mf_get_value(sf->field, &ctx->xin->flow, &value);
- mf_format(sf->field, &value, NULL, &s);
+ mf_format(sf->field, &value, NULL, NULL, &s);
} else {
union mf_subvalue cst;
mf_read_subfield(sf, &ctx->xin->flow, &cst);
case OFPP_ALL:
case OFPP_CONTROLLER:
case OFPP_NONE:
- ofputil_port_to_string(port, name, sizeof name);
+ ofputil_port_to_string(port, NULL, name, sizeof name);
xlate_report(ctx, OFT_WARN,
"output_trunc does not support port: %s", name);
break;
/* Since truncate happens at its following output action, if
* the output port is a patch port, the behavior is somehow
* unpredictable. For simplicity, disallow this case. */
- ofputil_port_to_string(port, name, sizeof name);
+ ofputil_port_to_string(port, NULL, name, sizeof name);
xlate_report_error(ctx, "output_trunc does not support "
"patch port %s", name);
break;
if (OVS_UNLIKELY(ctx->xin->trace)) {
struct ds s = DS_EMPTY_INITIALIZER;
ds_put_format(&s, "table=%"PRIu8" ", fm.table_id);
- match_format(&fm.match, &s, OFP_DEFAULT_PRIORITY);
+ match_format(&fm.match, NULL, &s, OFP_DEFAULT_PRIORITY);
ds_chomp(&s, ' ');
ds_put_format(&s, " priority=%d", fm.priority);
if (fm.new_cookie) {
ds_put_cstr(&s, " send_flow_rem");
}
ds_put_cstr(&s, " actions=");
- ofpacts_format(fm.ofpacts, fm.ofpacts_len, &s);
+ ofpacts_format(fm.ofpacts, fm.ofpacts_len, NULL, &s);
xlate_report(ctx, OFT_DETAIL, "%s", ds_cstr(&s));
ds_destroy(&s);
}
if (OVS_UNLIKELY(ctx->xin->trace)) {
struct ds s = DS_EMPTY_INITIALIZER;
- ofpacts_format(a, OFPACT_ALIGN(a->len), &s);
+ ofpacts_format(a, OFPACT_ALIGN(a->len), NULL, &s);
xlate_report(ctx, OFT_ACTION, "%s", ds_cstr(&s));
ds_destroy(&s);
}
char name[OFP10_MAX_PORT_NAME_LEN];
ofputil_port_to_string(ofbundle_get_a_port(bundle)->up.ofp_port,
- name, sizeof name);
+ NULL, name, sizeof name);
ds_put_format(&ds, "%5s %4d "ETH_ADDR_FMT" %3d\n",
name, e->vlan, ETH_ADDR_ARGS(e->mac),
mac_entry_age(ofproto->ml, e));
bundle = b->port;
ofputil_port_to_string(ofbundle_get_a_port(bundle)->up.ofp_port,
- name, sizeof name);
+ NULL, name, sizeof name);
ds_put_format(&ds, "%5s %4d ", name, grp->vlan);
ipv6_format_mapped(&grp->addr, &ds);
ds_put_format(&ds, " %3d\n",
bundle = mrouter->port;
ofputil_port_to_string(ofbundle_get_a_port(bundle)->up.ofp_port,
- name, sizeof name);
+ NULL, name, sizeof name);
ds_put_format(&ds, "%5s %4d querier %3d\n",
name, mrouter->vlan,
mcast_mrouter_age(ofproto->ms, mrouter));
ds_put_format(results, "duration=%llds, ", (time_msec() - created) / 1000);
ds_put_format(results, "n_packets=%"PRIu64", ", packet_count);
ds_put_format(results, "n_bytes=%"PRIu64", ", byte_count);
- cls_rule_format(&rule->cr, ofproto_get_tun_tab(ofproto), results);
+ cls_rule_format(&rule->cr, ofproto_get_tun_tab(ofproto), NULL, results);
ds_put_char(results, ',');
ds_put_cstr(results, "actions=");
- ofpacts_format(actions->ofpacts, actions->ofpacts_len, results);
+ ofpacts_format(actions->ofpacts, actions->ofpacts_len, NULL, results);
ds_put_cstr(results, "\n");
}
-/* Copyright (c) 2013, 2014, 2015 Nicira, Inc.
+/* Copyright (c) 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.
tnl_port = tnl_find(flow);
ofport = tnl_port ? tnl_port->ofport : NULL;
if (!tnl_port) {
- char *flow_str = flow_to_string(flow);
+ char *flow_str = flow_to_string(flow, NULL);
VLOG_WARN_RL(&rl, "receive tunnel port not found (%s)", flow_str);
free(flow_str);
}
if (!VLOG_DROP_DBG(&dbg_rl)) {
- pre_flow_str = flow_to_string(flow);
+ pre_flow_str = flow_to_string(flow, NULL);
}
if (pre_flow_str) {
- char *post_flow_str = flow_to_string(flow);
+ char *post_flow_str = flow_to_string(flow, NULL);
char *tnl_str = tnl_port_fmt(tnl_port);
VLOG_DBG("flow received\n"
"%s"
ovs_assert(cfg);
if (!VLOG_DROP_DBG(&dbg_rl)) {
- pre_flow_str = flow_to_string(flow);
+ pre_flow_str = flow_to_string(flow, NULL);
}
if (!cfg->ip_src_flow) {
}
if (pre_flow_str) {
- char *post_flow_str = flow_to_string(flow);
+ char *post_flow_str = flow_to_string(flow, NULL);
char *tnl_str = tnl_port_fmt(tnl_port);
VLOG_DBG("flow sent\n"
"%s"
VLOG_ERR("switch refused to allocate Geneve option (%s)",
ofperr_to_string(ofperr_decode_msg(oh, NULL)));
} else {
- char *s = ofp_to_string(oh, ntohs(oh->length), 1);
+ char *s = ofp_to_string(oh, ntohs(oh->length), NULL, 1);
VLOG_ERR("unexpected reply to TLV table request (%s)", s);
free(s);
}
goto error;
}
} else {
- char *s = ofp_to_string(oh, ntohs(oh->length), 1);
+ char *s = ofp_to_string(oh, ntohs(oh->length), NULL, 1);
VLOG_ERR("unexpected reply to Geneve option allocation request (%s)",
s);
free(s);
OVS_NOT_REACHED();
}
} else {
- char *s = ofp_to_string(oh, ntohs(oh->length), 1);
+ char *s = ofp_to_string(oh, ntohs(oh->length), NULL, 1);
VLOG_WARN("could not decode OpenFlow message (%s): %s",
ofperr_to_string(error), s);
free(s);
const struct ofp_header *oh, const char *title)
{
if (!vlog_should_drop(&this_module, level, rl)) {
- char *s = ofp_to_string(oh, ntohs(oh->length), 2);
+ char *s = ofp_to_string(oh, ntohs(oh->length), NULL, 2);
vlog(&this_module, level, "%s: %s", title, s);
free(s);
}
struct ds s = DS_EMPTY_INITIALIZER;
ds_put_format(&s, "table_id=%"PRIu8", ", f->table_id);
ds_put_format(&s, "priority=%"PRIu16", ", f->priority);
- match_format(&f->match, &s, OFP_DEFAULT_PRIORITY);
+ match_format(&f->match, NULL, &s, OFP_DEFAULT_PRIORITY);
ds_put_cstr(&s, ", actions=");
- ofpacts_format(f->ofpacts, f->ofpacts_len, &s);
+ ofpacts_format(f->ofpacts, f->ofpacts_len, NULL, &s);
return ds_steal_cstr(&s);
}
desired->group_id, ds_cstr(&desired->group));
error = parse_ofp_group_mod_str(&gm, OFPGC11_ADD,
- ds_cstr(&group_string),
+ ds_cstr(&group_string), NULL,
&usable_protocols);
if (!error) {
add_group_mod(&gm, &msgs);
ds_put_format(&group_string, "group_id=%u", installed->group_id);
error = parse_ofp_group_mod_str(&gm, OFPGC11_DELETE,
- ds_cstr(&group_string),
+ ds_cstr(&group_string), NULL,
&usable_protocols);
if (!error) {
add_group_mod(&gm, &msgs);
if (VLOG_IS_DBG_ENABLED()) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(30, 300);
- char *s = ofp_to_string(oh, ntohs(oh->length), 2);
+ char *s = ofp_to_string(oh, ntohs(oh->length), NULL, 2);
VLOG_DBG_RL(&rl, "OpenFlow packet ignored: %s", s);
free(s);
const struct expr_match *m;
HMAP_FOR_EACH (m, hmap_node, matches) {
- char *s = match_to_string(&m->match, OFP_DEFAULT_PRIORITY);
+ char *s = match_to_string(&m->match, NULL, OFP_DEFAULT_PRIORITY);
fputs(s, stream);
free(s);
ds_clear(&s);
if (stats) {
- ofp_print_flow_stats(&s, fs);
+ ofp_print_flow_stats(&s, fs, NULL);
} else {
ds_put_format(&s, " %stable=%s%"PRIu8" ",
colors.special, colors.end, fs->table_id);
- match_format(&fs->match, &s, OFP_DEFAULT_PRIORITY);
+ match_format(&fs->match, NULL, &s, OFP_DEFAULT_PRIORITY);
if (ds_last(&s) != ' ') {
ds_put_char(&s, ' ');
}
ds_put_format(&s, "%sactions=%s", colors.actions, colors.end);
- ofpacts_format(fs->ofpacts, fs->ofpacts_len, &s);
+ ofpacts_format(fs->ofpacts, fs->ofpacts_len, NULL, &s);
}
printf(" %s\n", ds_cstr(&s));
}
if (rsrc->ofs == 0 && rsrc->n_bits >= rsrc->field->n_bits) {
union mf_value value;
mf_get_value(rsrc->field, uflow, &value);
- mf_format(rsrc->field, &value, NULL, &s);
+ mf_format(rsrc->field, &value, NULL, NULL, &s);
} else {
union mf_subvalue cst;
mf_read_subfield(rsrc, uflow, &cst);
struct ds s = DS_EMPTY_INITIALIZER;
for (size_t i = 0; i < n_fses; i++) {
ds_clear(&s);
- ofp_print_flow_stats(&s, &fses[i]);
+ ofp_print_flow_stats(&s, &fses[i], NULL);
/* ofp_print_flow_stats() indents its output with a space.
* Omit it. */
struct ds output = DS_EMPTY_INITIALIZER;
ds_put_cstr(&output, "# ");
- flow_format(&output, &uflow);
+ flow_format(&output, &uflow, NULL);
ds_put_char(&output, '\n');
if (ovs) {
table=1 in_port=3 priority=1500 icmp actions=output(14),resubmit(,2)
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=1,nw_tos=0,nw_ttl=128,icmp_type=8,icmp_code=0'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=p1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=1,nw_tos=0,nw_ttl=128,icmp_type=8,icmp_code=0'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
[Datapath actions: 10,11,12,13,14,15,16,17,18,19,20,21
])
packet-out in_port=6, packet=0001020304050010203040501234 actions=table
flow in_port=7 actions=group:2
])
-AT_CHECK([ovs-ofctl bundle br0 bundle.txt 2>&1 | sed '/talking to/,$d'], [], [dnl
-Error OFPBAC_BAD_OUT_GROUP for: OFPT_FLOW_MOD (OF1.4) (xid=0x5): ADD in_port=7 actions=group:2
-Error OFPBFC_MSG_FAILED for: OFPT_BUNDLE_CONTROL (OF1.4) (xid=0x8):
+AT_CHECK([ovs-ofctl bundle br0 bundle.txt 2>&1 | sed '/talking to/,$d' | strip_xids], [], [dnl
+Error OFPBAC_BAD_OUT_GROUP for: OFPT_FLOW_MOD (OF1.4): ADD in_port=7 actions=group:2
+Error OFPBFC_MSG_FAILED for: OFPT_BUNDLE_CONTROL (OF1.4):
bundle_id=0 type=COMMIT_REQUEST flags=atomic ordered
])
])
# Verify that the packet-in was NOT received via controller action.
-AT_CHECK([sed 's/ (xid=0x[[1-9a-fA-F]][[0-9a-fA-F]]*)//' monitor.log], [0], [])
+AT_CHECK([strip_xids < monitor.log], [0], [])
OVS_VSWITCHD_STOP
AT_CLEANUP
packet-out in_port=6, packet=0001020304050010203040501234 actions=table
packet-out in_port=6, packet=0001020304050010203040501234 actions=group:2
])
-AT_CHECK([ovs-ofctl bundle br0 bundle.txt 2>&1 | sed '/talking to/,$d'], [], [dnl
-Error OFPBAC_BAD_OUT_GROUP for: OFPT_PACKET_OUT (OF1.4) (xid=0x5): in_port=6 actions=group:2 data_len=14
+AT_CHECK([ovs-ofctl bundle br0 bundle.txt 2>&1 | sed '/talking to/,$d' | strip_xids], [], [dnl
+Error OFPBAC_BAD_OUT_GROUP for: OFPT_PACKET_OUT (OF1.4): in_port=6 actions=group:2 data_len=14
vlan_tci=0x0000,dl_src=00:10:20:30:40:50,dl_dst=00:01:02:03:04:05,dl_type=0x1234
-Error OFPBFC_MSG_FAILED for: OFPT_BUNDLE_CONTROL (OF1.4) (xid=0x8):
+Error OFPBFC_MSG_FAILED for: OFPT_BUNDLE_CONTROL (OF1.4):
bundle_id=0 type=COMMIT_REQUEST flags=atomic ordered
])
])
# Verify that the packet-in was NOT received via controller action.
-AT_CHECK([sed 's/ (xid=0x[[1-9a-fA-F]][[0-9a-fA-F]]*)//' monitor.log], [0], [])
+AT_CHECK([strip_xids < monitor.log], [0], [])
OVS_VSWITCHD_STOP
AT_CLEANUP
for i in 1 2 3 4 5; do ovs-appctl time/warp 1000; done
# Check that no hidden flows are visible in OpenFlow.
-AT_CHECK([ovs-ofctl dump-flows br0], [0], [NXST_FLOW reply (xid=0x4):
+AT_CHECK([ovs-ofctl dump-flows br0 | strip_xids], [0], [NXST_FLOW reply:
])
# Check that some hidden flows related to 240.0.0.1 are actually in table 0.
# Check that dump-tables doesn't count the hidden flows.
head_table() {
- printf 'OFPST_TABLE reply (xid=0x2):
+ printf 'OFPST_TABLE reply:
table 0 ("%s"):
active=0, lookup=0, matched=0
max_entries=1000000
done
}
(head_table classifier; ditto 1 253) > expout
-AT_CHECK([ovs-ofctl dump-tables br0], [0], [expout])
+AT_CHECK([ovs-ofctl dump-tables br0 | strip_xids], [0], [expout])
OVS_VSWITCHD_STOP(["/240\.0\.0\.1/d"])
AT_CLEANUP
AT_CHECK([ovs-appctl vlog/set vconn:dbg])
-AT_CHECK([ovs-ofctl del-flows br0])
+AT_CHECK([ovs-ofctl --no-names del-flows br0])
AT_DATA([flows.txt], [dnl
add idle_timeout=50 in_port=2 dl_src=00:66:77:88:99:aa actions=1
delete in_port=2 dl_src=00:88:99:aa:bb:cc
])
-AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
+AT_CHECK([ovs-ofctl --no-names --bundle add-flows br0 flows.txt])
AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
idle_timeout=50, in_port=2,dl_src=00:66:77:88:99:aa actions=output:5
modify_strict in_port=2 dl_src=00:77:88:99:aa:bb actions=7
])
-AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
+AT_CHECK([ovs-ofctl --no-names --bundle add-flows br0 flows.txt])
AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
idle_timeout=50, in_port=2,dl_src=00:66:77:88:99:aa actions=drop
add in_port=2 dl_src=00:66:77:88:99:aa actions=drop
])
-AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
+AT_CHECK([ovs-ofctl --no-names --bundle add-flows br0 flows.txt])
AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
idle_timeout=60, in_port=2,dl_src=00:77:88:99:aa:bb actions=output:8
add table=254 actions=drop
])
-AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt 2>&1 | sed '/talking to/,$d'],
+AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt 2>&1 | sed '/talking to/,$d' | strip_xids],
[0], [dnl
-Error OFPBRC_EPERM for: OFPT_FLOW_MOD (OF1.4) (xid=0xb): ADD table:254 actions=drop
+Error OFPBRC_EPERM for: OFPT_FLOW_MOD (OF1.4): ADD table:254 actions=drop
])
AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
AT_CHECK([ovs-appctl vlog/set vconn:dbg])
-AT_CHECK([ovs-ofctl del-flows br0])
+AT_CHECK([ovs-ofctl --no-names del-flows br0])
AT_DATA([flows.txt], [dnl
add idle_timeout=50 in_port=2 dl_src=00:66:77:88:99:aa actions=1
delete in_port=2 dl_src=00:88:99:aa:bb:cc
])
-AT_CHECK([ovs-ofctl -O OpenFlow13 --bundle add-flows br0 flows.txt])
+AT_CHECK([ovs-ofctl -O OpenFlow13 --no-names --bundle add-flows br0 flows.txt])
AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
idle_timeout=50, in_port=2,dl_src=00:66:77:88:99:aa actions=output:5
modify_strict in_port=2 dl_src=00:77:88:99:aa:bb actions=7
])
-AT_CHECK([ovs-ofctl -O OpenFlow13 --bundle add-flows br0 flows.txt])
+AT_CHECK([ovs-ofctl -O OpenFlow13 --no-names --bundle add-flows br0 flows.txt])
AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
idle_timeout=50, in_port=2,dl_src=00:66:77:88:99:aa actions=drop
add in_port=2 dl_src=00:66:77:88:99:aa actions=drop
])
-AT_CHECK([ovs-ofctl -O OpenFlow13 --bundle add-flows br0 flows.txt])
+AT_CHECK([ovs-ofctl -O OpenFlow13 --bundle --no-names add-flows br0 flows.txt])
AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
idle_timeout=60, in_port=2,dl_src=00:77:88:99:aa:bb actions=output:8
add table=254 actions=drop
])
-AT_CHECK([ovs-ofctl -O OpenFlow13 --bundle add-flows br0 flows.txt 2>&1 | sed '/talking to/,$d'],
+AT_CHECK([ovs-ofctl -O OpenFlow13 --bundle add-flows br0 flows.txt 2>&1 | sed '/talking to/,$d' | strip_xids],
[0], [dnl
-Error OFPBRC_EPERM for: OFPT_FLOW_MOD (OF1.3) (xid=0xb): ADD table:254 actions=drop
+Error OFPBRC_EPERM for: OFPT_FLOW_MOD (OF1.3): ADD table:254 actions=drop
])
AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
add idle_timeout=70 in_port=2 dl_src=00:88:99:aa:bb:cc actions=group:3
])
-AT_CHECK([ovs-ofctl -O OpenFlow13 --bundle add-flows br0 flows.txt 2>&1 | sed '/talking to/,$d'],
+AT_CHECK([ovs-ofctl -O OpenFlow13 --bundle add-flows br0 flows.txt 2>&1 | sed '/talking to/,$d' | strip_xids],
[0], [dnl
-Error OFPBAC_BAD_OUT_GROUP for: OFPT_FLOW_MOD (OF1.3) (xid=0x2): ADD in_port=2,dl_src=00:66:77:88:99:aa idle:50 actions=group:1
-Error OFPBFC_MSG_FAILED for: ONFT_BUNDLE_CONTROL (OF1.3) (xid=0x7):
+Error OFPBAC_BAD_OUT_GROUP for: OFPT_FLOW_MOD (OF1.3): ADD in_port=2,dl_src=00:66:77:88:99:aa idle:50 actions=group:1
+Error OFPBFC_MSG_FAILED for: ONFT_BUNDLE_CONTROL (OF1.3):
bundle_id=0 type=COMMIT_REQUEST flags=atomic ordered
])
dnl Ignore the first 0x50 bytes of hex dump from the reply msg since the NXM
dnl header that describes the tunnel metadata starts at offset 0x50.
AT_CHECK([ovs-ofctl dump-flows br0 -mmmm], [0], [stdout])
-AT_CHECK([sed -e 's/duration=[[0-9.]]*s/duration=?s/' -e 's/idle_age=[[0-9]]*/idle_age=?/' -e '/^000000[[0-4]]0 / d' stdout], [0], [dnl
-NXST_FLOW reply (xid=0x4):
+AT_CHECK([sed -e 's/duration=[[0-9.]]*s/duration=?s/' -e 's/idle_age=[[0-9]]*/idle_age=?/' -e '/^000000[[0-4]]0 / d' stdout | strip_xids], [0], [dnl
+NXST_FLOW reply:
cookie=0x0, duration=?s, table=0, n_packets=0, n_bytes=0, idle_age=?, in_port=1 actions=move:NXM_NX_TUN_METADATA0[[0..31]]->NXM_NX_REG0[[]]
00000050 ff ff 00 18 00 00 23 20-00 06 00 20 00 00 00 00 |......# ... ....|
00000060 00 01 50 04 00 01 00 04- |..P..... |
AT_CLEANUP
AT_SETUP([ovs-ofctl action inconsistency (OpenFlow 1.1)])
+OVS_VSWITCHD_START
+add_of_ports br0 1 2 3
AT_CHECK([ovs-ofctl --protocols OpenFlow11 add-flow br0 'ip actions=mod_tp_dst:1234'
], [1], [stdout], [ovs-ofctl: none of the usable flow formats (OpenFlow10,NXM) is among the allowed flow formats (OpenFlow11)
])
+OVS_VSWITCHD_STOP
AT_CLEANUP
AT_SETUP([ovs-ofctl parse-flows (skb_priority)])
NXT_FLOW_MOD: ADD table:255 ct_state=+trk,ct_label=0x1234567890abcdef12345678,ip actions=ct(commit)
NXT_FLOW_MOD: ADD table:255 actions=output(port=123,max_len=100)
NXT_FLOW_MOD: ADD table:255 actions=output(port=100,max_len=123)
-NXT_FLOW_MOD: ADD table:255 actions=output(port=65534,max_len=123)
-NXT_FLOW_MOD: ADD table:255 actions=output(port=65528,max_len=123)
+NXT_FLOW_MOD: ADD table:255 actions=output(port=LOCAL,max_len=123)
+NXT_FLOW_MOD: ADD table:255 actions=output(port=IN_PORT,max_len=123)
]])
AT_CLEANUP
dnl Check that "-F openflow10" rejects a flow_mod with unsupported features,
dnl such as tunnels and metadata.
AT_SETUP([ovs-ofctl -F option and NXM features])
-AT_CHECK([ovs-ofctl -F openflow10 add-flow dummy tun_id=123,actions=drop],
+OVS_VSWITCHD_START
+AT_CHECK([ovs-ofctl -F openflow10 add-flow br0 tun_id=123,actions=drop],
[1], [], [ovs-ofctl: none of the usable flow formats (NXM,OXM) is among the allowed flow formats (OpenFlow10)
])
-AT_CHECK([ovs-ofctl -F openflow10 add-flow dummy metadata=123,actions=drop],
+AT_CHECK([ovs-ofctl -F openflow10 add-flow br0 metadata=123,actions=drop],
[1], [], [ovs-ofctl: none of the usable flow formats (NXM,OXM,OpenFlow11) is among the allowed flow formats (OpenFlow10)
])
+OVS_VSWITCHD_STOP
AT_CLEANUP
dnl Check that "-F nxm" really forces add-flow to use the NXM flow format.
OVS_VSWITCHD_STOP
AT_CLEANUP
+AT_SETUP([ovs-ofctl dump-flows --names])
+AT_KEYWORDS([port names])
+OVS_VSWITCHD_START([\
+ -- add-port br0 xyzzy -- set Interface xyzzy type=dummy -- \
+ -- add-port br0 x-y -- set Interface x-y type=dummy -- \
+ -- add-port br0 abc123 -- set Interface abc123 type=dummy -- \
+ -- add-port br0 reallyverylongportname -- set Interface reallyverylongportname type=dummy -- \
+ -- add-port br0 conflictinglongportname1 -- set Interface conflictinglongportname1 type=dummy -- \
+ -- add-port br0 conflictinglongportname2 -- set Interface conflictinglongportname2 type=dummy])
+
+# These plain port names should be accepted.
+AT_CHECK([ovs-ofctl add-flow br0 in_port=xyzzy,actions=x-y,abc123])
+
+# reallyverylongportname is accepted truncated, but not in full.
+AT_CHECK([ovs-ofctl add-flow br0 in_port=reallyverylongp,actions=drop])
+AT_CHECK([ovs-ofctl add-flow br0 in_port=reallyverylongportname,actions=drop],
+ [1], [], [ovs-ofctl: reallyverylongportname: invalid or unknown port for in_port
+])
+
+# conflictinglongportname1 and 2 can't be accepted even truncated, since
+# they conflict when truncated.
+AT_CHECK([ovs-ofctl add-flow br0 in_port=conflictinglongportname1,actions=drop], [1], [], [ovs-ofctl: conflictinglongportname1: invalid or unknown port for in_port
+])
+AT_CHECK([ovs-ofctl add-flow br0 in_port=conflictinglongportname2,actions=drop], [1], [], [ovs-ofctl: conflictinglongportname2: invalid or unknown port for in_port
+])
+AT_CHECK([ovs-ofctl add-flow br0 in_port=conflictinglong,actions=drop], [1], [], [ovs-ofctl: conflictinglong: invalid or unknown port for in_port
+])
+
+# Show that the port names get displayed properly and that port names that
+# aren't alphanumeric get quoted.
+AT_CHECK([ovs-ofctl --names dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ in_port=reallyverylongp actions=drop
+ in_port=xyzzy actions=output:"x-y",output:abc123
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
AT_SETUP([ovs-ofctl diff-flows])
OVS_VSWITCHD_START
dnl Add flows to br0 with importance via OF1.4+, using an OF1.4+ bundle. For more details refer "ovs-ofctl rule with importance" test case.
for i in 1 2 3 4 5 6 7 8; do echo "table=$i,dl_vlan=$i,importance=$i,actions=drop"; done > add-flows.txt
-AT_CHECK([ovs-ofctl --bundle add-flows br0 add-flows.txt])
+AT_CHECK([ovs-ofctl --bundle --no-names add-flows br0 add-flows.txt])
dnl Replace some flows in the bridge.
for i in 1 3 5 7; do echo " table=$i, importance=`expr $i + 10`, dl_vlan=$i actions=drop"; done > replace-flows.txt
-AT_CHECK([ovs-ofctl --bundle replace-flows br0 replace-flows.txt])
+AT_CHECK([ovs-ofctl --bundle --no-names replace-flows br0 replace-flows.txt])
dnl Dump them and compare the dump flows output against the expected output.
cat replace-flows.txt > expout
-AT_CHECK([ovs-ofctl -O OpenFlow14 dump-flows br0 | ofctl_strip | sed '/OFPST_FLOW/d' | sort],
+AT_CHECK([ovs-ofctl -O OpenFlow14 --no-names dump-flows br0 | ofctl_strip | sed '/OFPST_FLOW/d' | sort],
[0], [expout])
dnl Check logs for OpenFlow trace
-/* 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.
char *error;
ofpbuf_init(&ofpacts, 0);
- error = bundle_parse_load(actions, &ofpacts);
+ error = bundle_parse_load(actions, NULL, &ofpacts);
if (error) {
ovs_fatal(0, "%s", error);
}
/*
- * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 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.
ofputil_match_to_ofp10_match(&match, &extracted_match);
if (memcmp(&expected_match, &extracted_match, sizeof expected_match)) {
- char *exp_s = ofp10_match_to_string(&expected_match, 2);
- char *got_s = ofp10_match_to_string(&extracted_match, 2);
+ char *exp_s = ofp10_match_to_string(&expected_match, NULL, 2);
+ char *got_s = ofp10_match_to_string(&extracted_match, NULL, 2);
errors++;
printf("mismatch on packet #%d (1-based).\n", n);
printf("Packet:\n");
ofp_print_packet(stdout, dp_packet_data(packet), dp_packet_size(packet), htonl(PT_ETH));
ovs_hex_dump(stdout, dp_packet_data(packet), dp_packet_size(packet), 0, true);
- match_print(&match);
+ match_print(&match, NULL);
printf("Expected flow:\n%s\n", exp_s);
printf("Actually extracted flow:\n%s\n", got_s);
ovs_hex_dump(stdout, &expected_match, sizeof expected_match, 0, false);
ofpbuf_init(&ofpacts, 0);
ovnacts_encode(ovnacts.data, ovnacts.size, &ep, &ofpacts);
struct ds ofpacts_s = DS_EMPTY_INITIALIZER;
- ofpacts_format(ofpacts.data, ofpacts.size, &ofpacts_s);
+ ofpacts_format(ofpacts.data, ofpacts.size, NULL, &ofpacts_s);
printf(" encodes as %s\n", ds_cstr(&ofpacts_s));
ds_destroy(&ofpacts_s);
ofpbuf_uninit(&ofpacts);
.
.IP "\fBmod\-port \fIswitch\fR \fIport\fR \fIaction\fR"
Modify characteristics of port \fBport\fR in \fIswitch\fR. \fIport\fR
-may be an OpenFlow port number or name or the keyword \fBLOCAL\fR (the
+may be an OpenFlow port number or name (unless \fB\-\-no\-names\fR is
+specified) or the keyword \fBLOCAL\fR (the
preferred way to refer to the OpenFlow local port). The \fIaction\fR
may be any one of the following:
.
\fB\-\-strict\fR
Uses strict matching when running flow modification commands.
.
+.IP "\fB\-\-names\fR"
+.IQ "\fB\-\-no\-names\fR"
+Every OpenFlow port has a name and a number. By default,
+\fBovs\-ofctl\fR commands accept both port names and numbers, and they
+display port names if \fBovs\-ofctl\fR is running on an interactive
+console, port numbers otherwise. With \fB\-\-names\fR,
+\fBovs\-ofctl\fR commands both accept and display port names; with
+\fB\-\-no\-names\fR, commands neither accept nor display port names.
+.IP
+If a port name contains special characters or might be confused with a
+keyword within a flow, it may be enclosed in double quotes (escaped
+from the shell). If necessary, JSON-style escape sequences may be
+used inside quotes, as specified in RFC 7159. When it displays port
+names, \fBovs\-ofctl\fR quotes any name that does not start with a
+letter followed by letters or digits.
+.IP
+These options are new in Open vSwitch 2.8. Earlier versions always
+behaved as if \fB\-\-no\-names\fR were specified.
+.IP
+Open vSwitch does not place its own limit on the length of port names,
+but OpenFlow 1.0 to 1.5 limit port names to 15 bytes and OpenFlow 1.6
+limits them to 63 bytes. Because \fRovs\-ofctl\fR uses OpenFlow to
+retrieve the mapping between port names and numbers, names longer than
+this limit will be truncated for both display and acceptance.
+Truncation can also cause long names that are different to appear to
+be the same; when a switch has two ports with the same (truncated)
+name, \fBovs\-ofctl\fR refuses to display or accept the name, using
+the number instead.
+.
.IP "\fB\-\-read-only\fR"
Do not execute read/write commands.
.
#include "openvswitch/ofp-util.h"
#include "openvswitch/ofp-parse.h"
#include "openvswitch/ofpbuf.h"
+#include "openvswitch/shash.h"
#include "openvswitch/vconn.h"
#include "openvswitch/vlog.h"
#include "packets.h"
static struct sort_criterion *criteria;
static size_t n_criteria, allocated_criteria;
+/* --names, --no-names: Show port names in output and accept port numbers in
+ * input. (When neither is specified, the default is to accept port numbers
+ * but, for backward compatibility, not to show them unless this is an
+ * interactive console session.) */
+static int use_port_names = -1;
+static const struct ofputil_port_map *ports_to_accept(const char *vconn_name);
+static const struct ofputil_port_map *ports_to_show(const char *vconn_name);
+static bool should_accept_ports(void);
+static bool should_show_ports(void);
+
static const struct ovs_cmdl_command *get_all_commands(void);
OVS_NO_RETURN static void usage(void);
{"timestamp", no_argument, NULL, OPT_TIMESTAMP},
{"sort", optional_argument, NULL, OPT_SORT},
{"rsort", optional_argument, NULL, OPT_RSORT},
+ {"names", no_argument, &use_port_names, 1},
+ {"no-names", no_argument, &use_port_names, 0},
{"unixctl", required_argument, NULL, OPT_UNIXCTL},
{"help", no_argument, NULL, 'h'},
{"option", no_argument, NULL, 'o'},
case '?':
exit(EXIT_FAILURE);
+ case 0:
+ break;
+
default:
abort();
}
" -t, --timeout=SECS give up after SECS seconds\n"
" --sort[=field] sort in ascending order\n"
" --rsort[=field] sort in descending order\n"
+ " --names show port names instead of numbers\n"
" --unixctl=SOCKET set control socket name\n"
" --color[=always|never|auto] control use of color in output\n"
" -h, --help display this help message\n"
if (send_xid == recv_xid) {
enum ofpraw raw;
- ofp_print(stdout, reply->data, reply->size, verbosity + 1);
+ ofp_print(stdout, reply->data, reply->size,
+ ports_to_show(vconn_get_name(vconn)), verbosity + 1);
ofpraw_decode(&raw, reply->data);
if (ofptype_from_ofpraw(raw) == OFPTYPE_ERROR) {
done = !ofpmp_more(reply->data);
} else {
ovs_fatal(0, "received bad reply: %s",
- ofp_to_string(reply->data, reply->size,
- verbosity + 1));
+ ofp_to_string(
+ reply->data, reply->size,
+ ports_to_show(vconn_get_name(vconn)),
+ verbosity + 1));
}
} else {
VLOG_DBG("received reply with xid %08"PRIx32" "
run(vconn_transact(vconn, request, &reply), "talking to %s",
vconn_get_name(vconn));
- ofp_print(stdout, reply->data, reply->size, verbosity + 1);
+ ofp_print(stdout, reply->data, reply->size,
+ ports_to_show(vconn_get_name(vconn)), verbosity + 1);
ofpbuf_delete(reply);
}
}
run(vconn_transact_multiple_noreply(vconn, requests, &reply),
"talking to %s", vconn_get_name(vconn));
if (reply) {
- ofp_print(stderr, reply->data, reply->size, verbosity + 2);
+ ofp_print(stderr, reply->data, reply->size,
+ ports_to_show(vconn_get_name(vconn)), verbosity + 2);
exit(1);
}
ofpbuf_delete(reply);
/* Frees the error messages as they are printed. */
static void
-bundle_print_errors(struct ovs_list *errors, struct ovs_list *requests)
+bundle_print_errors(struct ovs_list *errors, struct ovs_list *requests,
+ const char *vconn_name)
{
struct vconn_bundle_error *error, *next;
struct ofpbuf *bmsg;
}
}
fprintf(stderr, "Error %s for: ", ofperr_get_name(ofperr));
- ofp_print(stderr, ofp_msg, msg_len, verbosity + 1);
+ ofp_print(stderr, ofp_msg, msg_len, ports_to_show(vconn_name),
+ verbosity + 1);
}
ofpbuf_uninit(&payload);
free(error);
struct ovs_list errors;
int retval = vconn_bundle_transact(vconn, requests, flags, &errors);
- bundle_print_errors(&errors, requests);
+ bundle_print_errors(&errors, requests, vconn_get_name(vconn));
if (retval) {
ovs_fatal(retval, "talking to %s", vconn_get_name(vconn));
run(vconn_transact(vconn, request, &reply), "talking to %s", vconn_name);
has_ports = ofputil_switch_features_has_ports(reply);
- ofp_print(stdout, reply->data, reply->size, verbosity + 1);
+ ofp_print(stdout, reply->data, reply->size, NULL, verbosity + 1);
ofpbuf_delete(reply);
if (!has_ports) {
if (error) {
ovs_fatal(0, "decode error: %s", ofperr_get_name(error));
} else if (type == OFPTYPE_ERROR) {
- ofp_print(stdout, reply->data, reply->size, verbosity + 1);
+ ofp_print(stdout, reply->data, reply->size, NULL,
+ verbosity + 1);
done = true;
} else if (type == OFPTYPE_TABLE_FEATURES_STATS_REPLY) {
done = !ofpmp_more(reply->data);
} else {
ovs_fatal(0, "received bad reply: %s",
ofp_to_string(reply->data, reply->size,
+ ports_to_show(ctx->argv[1]),
verbosity + 1));
}
} else {
} else if (retval != EOF) {
ovs_fatal(0, "received bad reply: %s",
ofp_to_string(pi->reply->data, pi->reply->size,
- verbosity + 1));
+ NULL, verbosity + 1));
}
}
if (ofptype_pull(&type, pi->reply)
|| type != OFPTYPE_PORT_DESC_STATS_REPLY) {
ovs_fatal(0, "received bad reply: %s",
- ofp_to_string(pi->reply->data, pi->reply->size,
+ ofp_to_string(pi->reply->data, pi->reply->size, NULL,
verbosity + 1));
}
}
}
+static const struct ofputil_port_map *
+get_port_map(const char *vconn_name)
+{
+ static struct shash port_maps = SHASH_INITIALIZER(&port_maps);
+ struct ofputil_port_map *map = shash_find_data(&port_maps, vconn_name);
+ if (!map) {
+ map = xmalloc(sizeof *map);
+ ofputil_port_map_init(map);
+ shash_add(&port_maps, vconn_name, map);
+
+ if (!strchr(vconn_name, ':') || !vconn_verify_name(vconn_name)) {
+ /* For an active vconn (which includes a vconn constructed from a
+ * bridge name), connect to it and pull down the port name-number
+ * mapping. */
+ struct vconn *vconn;
+ open_vconn(vconn_name, &vconn);
+
+ struct port_iterator pi;
+ struct ofputil_phy_port pp;
+ for (port_iterator_init(&pi, vconn);
+ port_iterator_next(&pi, &pp); ) {
+ ofputil_port_map_put(map, pp.port_no, pp.name);
+ }
+ port_iterator_destroy(&pi);
+
+ vconn_close(vconn);
+ } else {
+ /* Don't bother with passive vconns, since it could take a long
+ * time for the remote to try to connect to us. Don't bother with
+ * invalid vconn names either. */
+ }
+ }
+ return map;
+}
+
+static const struct ofputil_port_map *
+ports_to_accept(const char *vconn_name)
+{
+ return should_accept_ports() ? get_port_map(vconn_name) : NULL;
+}
+
+static const struct ofputil_port_map *
+ports_to_show(const char *vconn_name)
+{
+ return should_show_ports() ? get_port_map(vconn_name) : NULL;
+}
+
+/* We accept port names unless the feature is turned off explicitly. */
+static bool
+should_accept_ports(void)
+{
+ return use_port_names != 0;
+}
+
+/* We show port names only if the feature is turned on explicitly, or if we're
+ * interacting with a user on the console. */
+static bool
+should_show_ports(void)
+{
+ static int interactive = -1;
+ if (interactive == -1) {
+ interactive = isatty(STDOUT_FILENO);
+ }
+
+ return use_port_names > 0 || (use_port_names == -1 && interactive);
+}
+
/* Returns the port number corresponding to 'port_name' (which may be a port
* name or number) within the switch 'vconn_name'. */
static ofp_port_t
str_to_port_no(const char *vconn_name, const char *port_name)
{
ofp_port_t port_no;
-
- if (ofputil_port_from_string(port_name, &port_no)) {
+ if (ofputil_port_from_string(port_name, NULL, &port_no) ||
+ ofputil_port_from_string(port_name, ports_to_accept(vconn_name),
+ &port_no)) {
return port_no;
- } else {
- struct ofputil_phy_port pp;
-
- fetch_ofputil_phy_port(vconn_name, port_name, &pp);
- return pp.port_no;
}
+ ovs_fatal(0, "%s: unknown port `%s'", vconn_name, port_name);
}
static bool
run(vconn_transact_noreply(vconn, request, &reply),
"talking to %s", vconn_get_name(vconn));
if (reply) {
- char *s = ofp_to_string(reply->data, reply->size, 2);
+ char *s = ofp_to_string(reply->data, reply->size, NULL, 2);
VLOG_DBG("%s: failed to set protocol, switch replied: %s",
vconn_get_name(vconn), s);
free(s);
if (usable_protocols & allowed_protocols) {
ovs_fatal(0, "switch does not support any of the usable flow "
"formats (%s)", usable_s);
- } else {
+} else {
char *allowed_s = ofputil_protocols_to_string(allowed_protocols);
ovs_fatal(0, "none of the usable flow formats (%s) is among the "
"allowed flow formats (%s)", usable_s, allowed_s);
struct ofputil_flow_stats_request *fsr,
enum ofputil_protocol *protocolp)
{
+ const char *vconn_name = argv[1];
enum ofputil_protocol usable_protocols, protocol;
struct vconn *vconn;
char *error;
- error = parse_ofp_flow_stats_request_str(fsr, aggregate,
- argc > 2 ? argv[2] : "",
- &usable_protocols);
+ const char *match = argc > 2 ? argv[2] : "";
+ const struct ofputil_port_map *port_map
+ = *match ? ports_to_accept(vconn_name) : NULL;
+ error = parse_ofp_flow_stats_request_str(fsr, aggregate, match,
+ port_map, &usable_protocols);
if (error) {
ovs_fatal(0, "%s", error);
}
- protocol = open_vconn(argv[1], &vconn);
+ protocol = open_vconn(vconn_name, &vconn);
*protocolp = set_protocol_for_flow_dump(vconn, protocol, usable_protocols);
return vconn;
}
static void
ofctl_dump_flows(struct ovs_cmdl_context *ctx)
{
- if (!n_criteria) {
+ if (!n_criteria && !should_show_ports()) {
ofctl_dump_flows__(ctx->argc, ctx->argv, false);
return;
} else {
struct ds s = DS_EMPTY_INITIALIZER;
for (size_t i = 0; i < n_fses; i++) {
ds_clear(&s);
- ofp_print_flow_stats(&s, &fses[i]);
+ ofp_print_flow_stats(&s, &fses[i], ports_to_show(ctx->argv[1]));
puts(ds_cstr(&s));
}
ds_destroy(&s);
* this is backwards compatible. */
command = -2;
}
- error = parse_ofp_flow_mod_file(argv[2], command, &fms, &n_fms,
- &usable_protocols);
+ error = parse_ofp_flow_mod_file(argv[2], ports_to_accept(argv[1]), command,
+ &fms, &n_fms, &usable_protocols);
if (error) {
ovs_fatal(0, "%s", error);
}
char *error;
enum ofputil_protocol usable_protocols;
- error = parse_ofp_flow_mod_str(&fm, argc > 2 ? argv[2] : "", command,
+ error = parse_ofp_flow_mod_str(&fm, argc > 2 ? argv[2] : "",
+ ports_to_accept(argv[1]), command,
&usable_protocols);
if (error) {
ovs_fatal(0, "%s", error);
run(vconn_transact_noreply(vconn, spif, &reply),
"talking to %s", vconn_get_name(vconn));
if (reply) {
- char *s = ofp_to_string(reply->data, reply->size, 2);
+ char *s = ofp_to_string(reply->data, reply->size, NULL, 2);
VLOG_DBG("%s: failed to set packet in format to nx_packet_in, "
"controller replied: %s.",
vconn_get_name(vconn), s);
}
fprintf(stderr, "send: ");
- ofp_print(stderr, msg->data, msg->size, verbosity);
+ ofp_print(stderr, msg->data, msg->size,
+ ports_to_show(vconn_get_name(vconn)), verbosity);
error = vconn_send_block(vconn, msg);
if (error) {
struct ofputil_packet_out po;
char *error_msg;
- error_msg = parse_ofp_packet_out_str(&po, argv[1], &usable_protocols);
+ error_msg = parse_ofp_packet_out_str(
+ &po, argv[1], ports_to_accept(vconn_get_name(vconn)),
+ &usable_protocols);
if (error_msg) {
ds_put_format(&reply, "%s\n", error_msg);
free(error_msg);
if (ok) {
struct ofpbuf *msg = ofputil_encode_packet_out(&po, protocol);
- ofp_print(stderr, msg->data, msg->size, verbosity);
+ ofp_print(stderr, msg->data, msg->size,
+ ports_to_show(vconn_get_name(vconn)), verbosity);
int error = vconn_send_block(vconn, msg);
if (error) {
}
ofptype_decode(&type, b->data);
- ofp_print(stderr, b->data, b->size, verbosity + 2);
+ ofp_print(stderr, b->data, b->size,
+ ports_to_show(vconn_get_name(vconn)), verbosity + 2);
fflush(stderr);
switch ((int) type) {
fprintf(stderr, "send: ");
ofp_print(stderr, reply->data, reply->size,
+ ports_to_show(vconn_get_name(vconn)),
verbosity + 2);
fflush(stderr);
char *error;
error = parse_flow_monitor_request(&fmr, arg + 6,
+ ports_to_accept(ctx->argv[1]),
&usable_protocols);
if (error) {
ovs_fatal(0, "%s", error);
int i;
ofpbuf_init(&ofpacts, 64);
- error = ofpacts_parse_actions(ctx->argv[3], &ofpacts,
+ error = ofpacts_parse_actions(ctx->argv[3],
+ ports_to_accept(ctx->argv[1]), &ofpacts,
&usable_protocols);
if (error) {
ovs_fatal(0, "%s", error);
vconn_close(vconn);
ofpbuf_uninit(&ofpacts);
} else if (ctx->argc == 3) {
- error = parse_ofp_packet_out_str(&po, ctx->argv[2], &usable_protocols);
+ error = parse_ofp_packet_out_str(&po, ctx->argv[2],
+ ports_to_accept(ctx->argv[1]),
+ &usable_protocols);
if (error) {
ovs_fatal(0, "%s", error);
}
if (ofptype_pull(&type, &b)
|| type != OFPTYPE_TABLE_DESC_REPLY) {
ovs_fatal(0, "received bad reply: %s",
- ofp_to_string(reply->data, reply->size,
+ ofp_to_string(reply->data, reply->size, NULL,
verbosity + 1));
}
uint16_t flags = ofpmp_flags(oh);
ovs_fatal(0, "%s: unexpected end of file mid-message", filename);
}
- ofp_print(stdout, b.data, b.size, verbosity + 2);
+ ofp_print(stdout, b.data, b.size, NULL, verbosity + 2);
}
ofpbuf_uninit(&b);
printf(IP_FMT".%"PRIu16" > "IP_FMT".%"PRIu16":\n",
IP_ARGS(flow.nw_src), ntohs(flow.tp_src),
IP_ARGS(flow.nw_dst), ntohs(flow.tp_dst));
- ofp_print(stdout, dp_packet_data(payload), length, verbosity + 1);
+ ofp_print(stdout, dp_packet_data(payload), length,
+ NULL, verbosity + 1);
dp_packet_pull(payload, length);
}
}
|| reply->size != payload
|| memcmp(request->msg, reply->msg, payload)) {
printf("Reply does not match request. Request:\n");
- ofp_print(stdout, request, request->size, verbosity + 2);
+ ofp_print(stdout, request, request->size, NULL, verbosity + 2);
printf("Reply:\n");
- ofp_print(stdout, reply, reply->size, verbosity + 2);
+ ofp_print(stdout, reply, reply->size, NULL, verbosity + 2);
}
printf("%"PRIu32" bytes from %s: xid=%08"PRIx32" time=%.1f ms\n",
reply->size, ctx->argv[1], ntohl(rpy_hdr->xid),
* this is backwards compatible. */
command = -2;
}
- error = parse_ofp_group_mod_file(argv[2], command, &gms, &n_gms,
- &usable_protocols);
+ error = parse_ofp_group_mod_file(argv[2], ports_to_accept(argv[1]),
+ command, &gms, &n_gms, &usable_protocols);
if (error) {
ovs_fatal(0, "%s", error);
}
char *error;
error = parse_ofp_group_mod_str(&gm, command, argc > 2 ? argv[2] : "",
+ ports_to_accept(argv[1]),
&usable_protocols);
if (error) {
ovs_fatal(0, "%s", error);
error = parse_ofp_group_mod_str(&gm, OFPGC11_DELETE,
ctx->argc > 2 ? ctx->argv[2] : "",
+ ports_to_accept(ctx->argv[1]),
&usable_protocols);
if (error) {
ovs_fatal(0, "%s", error);
size_t n_bms;
char *error;
- error = parse_ofp_bundle_file(ctx->argv[2], &bms, &n_bms,
- &usable_protocols);
+ error = parse_ofp_bundle_file(ctx->argv[2], ports_to_accept(ctx->argv[1]),
+ &bms, &n_bms, &usable_protocols);
if (error) {
ovs_fatal(0, "%s", error);
}
/* The final metadata table that we have constructed. */
struct tun_table *tun_tab;
+
+ /* Port map. There is only one port map, not one per source, because it
+ * only makes sense to display a single name for a given port number. */
+ const struct ofputil_port_map *port_map;
};
/* Frees 'version' and the data that it owns. */
if (version->table_id) {
ds_put_format(s, "table=%"PRIu8" ", version->table_id);
}
- cls_rule_format(&fte->rule, fte_state->tun_tab, s);
+ cls_rule_format(&fte->rule, fte_state->tun_tab, fte_state->port_map, s);
if (version->cookie != htonll(0)) {
ds_put_format(s, " cookie=0x%"PRIx64, ntohll(version->cookie));
}
}
ds_put_cstr(s, " actions=");
- ofpacts_format(version->ofpacts, version->ofpacts_len, s);
+ ofpacts_format(version->ofpacts, version->ofpacts_len,
+ fte_state->port_map, s);
ds_put_char(s, '\n');
}
ovs_list_init(&state->fte_pending_list);
state->tun_tab = NULL;
+ state->port_map = NULL;
}
static void
char *error;
enum ofputil_protocol usable;
- error = parse_ofp_str(&fm, OFPFC_ADD, ds_cstr(&s), &usable);
+ error = parse_ofp_str(&fm, OFPFC_ADD, ds_cstr(&s), state->port_map,
+ &usable);
if (error) {
ovs_fatal(0, "%s:%d: %s", filename, line_number, error);
}
static void
ofctl_replace_flows(struct ovs_cmdl_context *ctx)
{
- enum { FILE_IDX = 0, SWITCH_IDX = 1 };
+ enum { FILE_IDX = 0, SWITCH_IDX = 1 };
enum ofputil_protocol usable_protocols, protocol;
struct fte_state fte_state;
struct flow_tables tables;
struct fte *fte;
fte_state_init(&fte_state);
+ fte_state.port_map = ports_to_accept(ctx->argv[1]);
usable_protocols = read_flows_from_file(ctx->argv[2], &fte_state, FILE_IDX);
protocol = open_vconn(ctx->argv[1], &vconn);
protocol = set_protocol_for_flow_dump(vconn, protocol, OFPUTIL_P_ANY);
read_flows_from_switch(vconn, protocol, state, index);
vconn_close(vconn);
+
+ if (!state->port_map) {
+ state->port_map = ports_to_show(source);
+ }
}
}
struct ofpbuf *msg;
msg = ofputil_encode_flow_mod(fm, protocol);
- ofp_print(stdout, msg->data, msg->size, verbosity);
+ ofp_print(stdout, msg->data, msg->size, NULL, verbosity);
ofpbuf_delete(msg);
free(CONST_CAST(struct ofpact *, fm->ofpacts));
struct ofputil_flow_mod fm;
char *error;
- error = parse_ofp_flow_mod_str(&fm, ctx->argv[1], OFPFC_ADD, &usable_protocols);
+ error = parse_ofp_flow_mod_str(&fm, ctx->argv[1], NULL,
+ OFPFC_ADD, &usable_protocols);
if (error) {
ovs_fatal(0, "%s", error);
}
size_t n_fms = 0;
char *error;
- error = parse_ofp_flow_mod_file(ctx->argv[1], OFPFC_ADD, &fms, &n_fms,
- &usable_protocols);
+ error = parse_ofp_flow_mod_file(ctx->argv[1], NULL, OFPFC_ADD,
+ &fms, &n_fms, &usable_protocols);
if (error) {
ovs_fatal(0, "%s", error);
}
/* Print cls_rule. */
ds_init(&s);
ds_put_cstr(&s, "actions=");
- ofpacts_format(ofpacts.data, ofpacts.size, &s);
+ ofpacts_format(ofpacts.data, ofpacts.size, NULL, &s);
puts(ds_cstr(&s));
ds_destroy(&s);
/* Convert to cls_rule and print. */
ofputil_match_from_ofp10_match(match_in.data, &match);
- match_print(&match);
+ match_print(&match, NULL);
/* Convert back to ofp10_match and print differences from input. */
ofputil_match_to_ofp10_match(&match, &match_out);
}
/* Print match. */
- match_print(&match);
+ match_print(&match, NULL);
/* Convert back to ofp11_match and print differences from input. */
ofputil_match_to_ofp11_match(&match, &match_out);
pkt_metadata_init(&packet->md, u32_to_odp(ofp_to_u16(OFPP_ANY)));
flow_extract(packet, &flow);
- flow_print(stdout, &flow);
+ flow_print(stdout, &flow, NULL);
putchar('\n');
dp_packet_delete(packet);
}
match.wc.masks.vlans[0].tci = htons(strtoul(ctx->argv[2], NULL, 16));
/* Convert to and from string. */
- string_s = match_to_string(&match, OFP_DEFAULT_PRIORITY);
+ string_s = match_to_string(&match, NULL, OFP_DEFAULT_PRIORITY);
printf("%s -> ", string_s);
fflush(stdout);
- error_s = parse_ofp_str(&fm, -1, string_s, &usable_protocols);
+ error_s = parse_ofp_str(&fm, -1, string_s, NULL, &usable_protocols);
if (error_s) {
ovs_fatal(0, "%s", error_s);
}
if (ofpbuf_put_hex(&packet, buffer, NULL)[0] != '\0') {
ovs_fatal(0, "trailing garbage following hex bytes");
}
- ofp_print(stdout, packet.data, packet.size, verbosity);
+ ofp_print(stdout, packet.data, packet.size, NULL, verbosity);
ofpbuf_uninit(&packet);
ds_destroy(&line);
}
hello = ofputil_encode_hello(bitmap);
ovs_hex_dump(stdout, hello->data, hello->size, 0, false);
- ofp_print(stdout, hello->data, hello->size, verbosity);
+ ofp_print(stdout, hello->data, hello->size, NULL, verbosity);
ofpbuf_delete(hello);
}
/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2015 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 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.
break;
case OPT_WITH_FLOWS:
- error = parse_ofp_flow_mod_file(optarg, OFPFC_ADD, &default_flows,
- &n_default_flows,
+ error = parse_ofp_flow_mod_file(optarg, NULL, OFPFC_ADD,
+ &default_flows, &n_default_flows,
&usable_protocols);
if (error) {
ovs_fatal(0, "%s", error);