Commit 4bc938cc authored by Ben Pfaff's avatar Ben Pfaff

Support accepting and displaying table names in OVS tools.

OpenFlow has little-known support for naming tables.  Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation.  This commit adds
support for table names in ovs-ofctl.  When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
    table=1, arp, actions=resubmit(,2)
might become:
    table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.

For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.

This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.

CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: default avatarBen Pfaff <blp@ovn.org>
Acked-by: default avatarMark Michelson <mmichels@redhat.com>
Reviewed-by: default avatarYifeng Sun <pkusunyifeng@gmail.com>
parent a203f653
......@@ -2,6 +2,14 @@ Post-v2.9.0
--------------------
- ovs-vswitchd:
* New options --l7 and --l7-len to "ofproto/trace" command.
- ovs-ofctl:
* ovs-ofctl now accepts and display table 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.
- ovs-vswitchd:
* Previous versions gave OpenFlow tables default names of the form
"table#". These are not helpful names for the purpose of accepting
and displaying table names, so now tables by default have no names.
v2.9.0 - xx xxx xxxx
......
......@@ -1068,6 +1068,7 @@ uint32_t ofpacts_get_meter(const struct ofpact[], size_t ofpacts_len);
struct ofpact_format_params {
/* Input. */
const struct ofputil_port_map *port_map;
const struct ofputil_table_map *table_map;
/* Output. */
struct ds *s;
......@@ -1080,6 +1081,7 @@ const char *ofpact_name(enum ofpact_type);
struct ofpact_parse_params {
/* Input. */
const struct ofputil_port_map *port_map;
const struct ofputil_table_map *table_map;
/* Output. */
struct ofpbuf *ofpacts;
......
......@@ -45,26 +45,33 @@ enum ofputil_protocol;
char *parse_ofp_str(struct ofputil_flow_mod *, int command, const char *str_,
const struct ofputil_port_map *,
const struct ofputil_table_map *,
enum ofputil_protocol *usable_protocols)
OVS_WARN_UNUSED_RESULT;
char *parse_ofp_flow_mod_str(struct ofputil_flow_mod *, const char *string,
const struct ofputil_port_map *, int command,
const struct ofputil_port_map *,
const struct ofputil_table_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 *,
const struct ofputil_table_map *,
enum ofputil_protocol *usable_protocols)
OVS_WARN_UNUSED_RESULT;
char *parse_ofp_table_mod(struct ofputil_table_mod *,
const char *table_id, const char *flow_miss_handling,
const struct ofputil_table_map *,
uint32_t *usable_versions)
OVS_WARN_UNUSED_RESULT;
char *parse_ofp_flow_mod_file(const char *file_name,
const struct ofputil_port_map *, int command,
const struct ofputil_port_map *,
const struct ofputil_table_map *,
int command,
struct ofputil_flow_mod **fms, size_t *n_fms,
enum ofputil_protocol *usable_protocols)
OVS_WARN_UNUSED_RESULT;
......@@ -72,6 +79,7 @@ char *parse_ofp_flow_mod_file(const char *file_name,
char *parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *,
bool aggregate, const char *string,
const struct ofputil_port_map *,
const struct ofputil_table_map *,
enum ofputil_protocol *usable_protocols)
OVS_WARN_UNUSED_RESULT;
......@@ -86,12 +94,14 @@ char *parse_ofp_meter_mod_str(struct ofputil_meter_mod *, const char *string,
char *parse_flow_monitor_request(struct ofputil_flow_monitor_request *,
const char *,
const struct ofputil_port_map *port_map,
const struct ofputil_port_map *,
const struct ofputil_table_map *,
enum ofputil_protocol *usable_protocols)
OVS_WARN_UNUSED_RESULT;
char *parse_ofp_group_mod_file(const char *file_name,
const struct ofputil_port_map *, int command,
const struct ofputil_port_map *,
const struct ofputil_table_map *, int command,
struct ofputil_group_mod **gms, size_t *n_gms,
enum ofputil_protocol *usable_protocols)
OVS_WARN_UNUSED_RESULT;
......@@ -99,11 +109,13 @@ char *parse_ofp_group_mod_file(const char *file_name,
char *parse_ofp_group_mod_str(struct ofputil_group_mod *, int command,
const char *string,
const struct ofputil_port_map *,
const struct ofputil_table_map *,
enum ofputil_protocol *usable_protocols)
OVS_WARN_UNUSED_RESULT;
char *parse_ofp_bundle_file(const char *file_name,
const struct ofputil_port_map *,
const struct ofputil_table_map *,
struct ofputil_bundle_msg **, size_t *n_bms,
enum ofputil_protocol *)
OVS_WARN_UNUSED_RESULT;
......
......@@ -31,6 +31,7 @@ struct ofp_header;
struct ofputil_flow_stats;
struct ofputil_port_map;
struct ofputil_table_features;
struct ofputil_table_map;
struct ofputil_table_stats;
struct dp_packet;
......@@ -39,7 +40,7 @@ extern "C" {
#endif
void ofp_print(FILE *, const void *, size_t, const struct ofputil_port_map *,
int verbosity);
const struct ofputil_table_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);
......@@ -48,7 +49,7 @@ 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, const struct ofputil_port_map *,
int verbosity);
const struct ofputil_table_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);
......@@ -59,10 +60,13 @@ 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);
const struct ofputil_table_stats *prev_stats,
const struct ofputil_table_map *table_map);
void ofp_print_flow_stats(struct ds *, const struct ofputil_flow_stats *,
const struct ofputil_port_map *, bool show_stats);
const struct ofputil_port_map *,
const struct ofputil_table_map *,
bool show_stats);
#ifdef __cplusplus
}
......
......@@ -816,6 +816,14 @@ void ofputil_table_map_put(struct ofputil_table_map *,
uint8_t, const char *name);
void ofputil_table_map_destroy(struct ofputil_table_map *);
/* Table numbers. */
bool ofputil_table_from_string(const char *, const struct ofputil_table_map *,
uint8_t *tablep);
void ofputil_format_table(uint8_t table, const struct ofputil_table_map *,
struct ds *);
void ofputil_table_to_string(uint8_t, const struct ofputil_table_map *,
char *namebuf, size_t bufsize);
/* Abstract ofp_table_mod. */
struct ofputil_table_mod {
uint8_t table_id; /* ID of the table, 0xff indicates all tables. */
......
......@@ -381,6 +381,7 @@ learn_parse_spec(const char *orig, char *name, char *value,
* error. The caller is responsible for freeing the returned string. */
static char * OVS_WARN_UNUSED_RESULT
learn_parse__(char *orig, char *arg, const struct ofputil_port_map *port_map,
const struct ofputil_table_map *table_map,
struct ofpbuf *ofpacts)
{
struct ofpact_learn *learn;
......@@ -396,8 +397,10 @@ learn_parse__(char *orig, char *arg, const struct ofputil_port_map *port_map,
match_init_catchall(&match);
while (ofputil_parse_key_value(&arg, &name, &value)) {
if (!strcmp(name, "table")) {
learn->table_id = atoi(value);
if (learn->table_id == 255) {
if (!ofputil_table_from_string(value, table_map,
&learn->table_id)) {
return xasprintf("unknown table \"%s\"", value);
} else if (learn->table_id == 255) {
return xasprintf("%s: table id 255 not valid for `learn' "
"action", orig);
}
......@@ -465,10 +468,11 @@ learn_parse__(char *orig, char *arg, const struct ofputil_port_map *port_map,
* Modifies 'arg'. */
char * OVS_WARN_UNUSED_RESULT
learn_parse(char *arg, const struct ofputil_port_map *port_map,
const struct ofputil_table_map *table_map,
struct ofpbuf *ofpacts)
{
char *orig = xstrdup(arg);
char *error = learn_parse__(orig, arg, port_map, ofpacts);
char *error = learn_parse__(orig, arg, port_map, table_map, ofpacts);
free(orig);
return error;
}
......@@ -477,16 +481,18 @@ learn_parse(char *arg, const struct ofputil_port_map *port_map,
* describes. */
void
learn_format(const struct ofpact_learn *learn,
const struct ofputil_port_map *port_map, struct ds *s)
const struct ofputil_port_map *port_map,
const struct ofputil_table_map *table_map,
struct ds *s)
{
const struct ofpact_learn_spec *spec;
struct match match;
match_init_catchall(&match);
ds_put_format(s, "%slearn(%s%stable=%s%"PRIu8,
colors.learn, colors.end, colors.special, colors.end,
learn->table_id);
ds_put_format(s, "%slearn(%s%stable=%s",
colors.learn, colors.end, colors.special, colors.end);
ofputil_format_table(learn->table_id, table_map, s);
if (learn->idle_timeout != OFP_FLOW_PERMANENT) {
ds_put_format(s, ",%sidle_timeout=%s%"PRIu16,
colors.param, colors.end, learn->idle_timeout);
......
......@@ -28,6 +28,7 @@ struct ofpbuf;
struct ofpact_learn;
struct ofputil_flow_mod;
struct ofputil_port_map;
struct ofputil_table_map;
struct nx_action_learn;
/* NXAST_LEARN helper functions.
......@@ -41,9 +42,10 @@ void learn_execute(const struct ofpact_learn *, const struct flow *,
void learn_mask(const struct ofpact_learn *, struct flow_wildcards *);
char *learn_parse(char *, const struct ofputil_port_map *,
struct ofpbuf *ofpacts)
const struct ofputil_table_map *, struct ofpbuf *ofpacts)
OVS_WARN_UNUSED_RESULT;
void learn_format(const struct ofpact_learn *,
const struct ofputil_port_map *, struct ds *);
const struct ofputil_port_map *,
const struct ofputil_table_map *, struct ds *);
#endif /* learn.h */
......@@ -369,7 +369,7 @@ lswitch_process_packet(struct lswitch *sw, const struct ofpbuf *msg)
} else if (type == OFPTYPE_FLOW_REMOVED) {
/* Nothing to do. */
} else if (VLOG_IS_DBG_ENABLED()) {
char *s = ofp_to_string(msg->data, msg->size, NULL, 2);
char *s = ofp_to_string(msg->data, msg->size, NULL, NULL, 2);
VLOG_DBG_RL(&rl, "%016llx: OpenFlow packet ignored: %s",
sw->datapath_id, s);
free(s);
......
......@@ -4398,14 +4398,10 @@ parse_RESUBMIT(char *arg, const struct ofpact_parse_params *pp)
table_s = strsep(&arg, ",");
if (table_s && table_s[0]) {
uint32_t table_id = 0;
char *error;
error = str_to_u32(table_s, &table_id);
if (error) {
return error;
if (!ofputil_table_from_string(table_s, pp->table_map,
&resubmit->table_id)) {
return xasprintf("%s: resubmit to unknown table", table_s);
}
resubmit->table_id = table_id;
} else {
resubmit->table_id = 255;
}
......@@ -4441,7 +4437,7 @@ format_RESUBMIT(const struct ofpact_resubmit *a,
}
ds_put_char(fp->s, ',');
if (a->table_id != 255) {
ds_put_format(fp->s, "%"PRIu8, a->table_id);
ofputil_format_table(a->table_id, fp->table_map, fp->s);
}
if (a->with_ct_orig) {
ds_put_cstr(fp->s, ",ct");
......@@ -5024,14 +5020,14 @@ encode_LEARN(const struct ofpact_learn *learn,
static char * OVS_WARN_UNUSED_RESULT
parse_LEARN(char *arg, const struct ofpact_parse_params *pp)
{
return learn_parse(arg, pp->port_map, pp->ofpacts);
return learn_parse(arg, pp->port_map, pp->table_map, pp->ofpacts);
}
static void
format_LEARN(const struct ofpact_learn *a,
const struct ofpact_format_params *fp)
{
learn_format(a, fp->port_map, fp->s);
learn_format(a, fp->port_map, fp->table_map, fp->s);
}
/* Action structure for NXAST_CONJUNCTION. */
......@@ -5372,10 +5368,11 @@ static void
format_UNROLL_XLATE(const struct ofpact_unroll_xlate *a,
const struct ofpact_format_params *fp)
{
ds_put_format(fp->s, "%sunroll_xlate(%s%stable=%s%"PRIu8
", %scookie=%s%"PRIu64"%s)%s",
ds_put_format(fp->s, "%sunroll_xlate(%s%stable=%s",
colors.paren, colors.end,
colors.special, colors.end, a->rule_table_id,
colors.special, colors.end);
ofputil_format_table(a->rule_table_id, fp->table_map, fp->s);
ds_put_format(fp->s, ", %scookie=%s%"PRIu64"%s)%s",
colors.param, colors.end, ntohll(a->rule_cookie),
colors.paren, colors.end);
}
......@@ -6038,8 +6035,10 @@ parse_CT(char *arg, const struct ofpact_parse_params *pp)
} else if (!strcmp(key, "force")) {
oc->flags |= NX_CT_F_FORCE;
} else if (!strcmp(key, "table")) {
error = str_to_u8(value, "recirc_table", &oc->recirc_table);
if (!error && oc->recirc_table == NX_CT_RECIRC_NONE) {
if (!ofputil_table_from_string(value, pp->table_map,
&oc->recirc_table)) {
error = xasprintf("unknown table %s", value);
} else if (oc->recirc_table == NX_CT_RECIRC_NONE) {
error = xasprintf("invalid table %#"PRIx8, oc->recirc_table);
}
} else if (!strcmp(key, "zone")) {
......@@ -6125,8 +6124,9 @@ format_CT(const struct ofpact_conntrack *a,
ds_put_format(fp->s, "%sforce%s,", colors.value, colors.end);
}
if (a->recirc_table != NX_CT_RECIRC_NONE) {
ds_put_format(fp->s, "%stable=%s%"PRIu8",",
colors.special, colors.end, a->recirc_table);
ds_put_format(fp->s, "%stable=%s", colors.special, colors.end);
ofputil_format_table(a->recirc_table, fp->table_map, fp->s);
ds_put_char(fp->s, ',');
}
if (a->zone_src.field) {
ds_put_format(fp->s, "%szone=%s", colors.param, colors.end);
......@@ -6816,19 +6816,18 @@ static char * OVS_WARN_UNUSED_RESULT
parse_GOTO_TABLE(char *arg, const struct ofpact_parse_params *pp)
{
struct ofpact_goto_table *ogt = ofpact_put_GOTO_TABLE(pp->ofpacts);
char *table_s = strsep(&arg, ",");
if (!table_s || !table_s[0]) {
return xstrdup("instruction goto-table needs table id");
if (!ofputil_table_from_string(arg, pp->table_map, &ogt->table_id)) {
return xasprintf("unknown table \"%s\"", arg);
}
return str_to_u8(table_s, "table", &ogt->table_id);
return NULL;
}
static void
format_GOTO_TABLE(const struct ofpact_goto_table *a,
const struct ofpact_format_params *fp)
{
ds_put_format(fp->s, "%sgoto_table:%s%"PRIu8,
colors.param, colors.end, a->table_id);
ds_put_format(fp->s, "%sgoto_table:%s", colors.param, colors.end);
ofputil_format_table(a->table_id, fp->table_map, fp->s);
}
static void
......
This diff is collapsed.
This diff is collapsed.
......@@ -7378,16 +7378,16 @@ ofputil_port_get_reserved_name(ofp_port_t port)
}
}
/* A port name doesn't need to be quoted if it is alphanumeric and starts with
* a letter. */
/* A table or 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)
name_needs_quotes(const char *name)
{
if (!isalpha((unsigned char) port_name[0])) {
if (!isalpha((unsigned char) name[0])) {
return true;
}
for (const char *p = port_name + 1; *p; p++) {
for (const char *p = name + 1; *p; p++) {
if (!isalnum((unsigned char) *p)) {
return true;
}
......@@ -7395,13 +7395,14 @@ port_name_needs_quotes(const char *port_name)
return false;
}
/* Appends port or table 'name' to 's', quoting it if necessary. */
static void
put_port_name(const char *port_name, struct ds *s)
put_name(const char *name, struct ds *s)
{
if (port_name_needs_quotes(port_name)) {
json_string_escape(port_name, s);
if (name_needs_quotes(name)) {
json_string_escape(name, s);
} else {
ds_put_cstr(s, port_name);
ds_put_cstr(s, name);
}
}
......@@ -7420,7 +7421,7 @@ ofputil_format_port(ofp_port_t port, const struct ofputil_port_map *port_map,
const char *port_name = ofputil_port_map_get_name(port_map, port);
if (port_name) {
put_port_name(port_name, s);
put_name(port_name, s);
return;
}
......@@ -7445,7 +7446,7 @@ ofputil_port_to_string(ofp_port_t port,
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);
put_name(port_name, &s);
ovs_strlcpy(namebuf, ds_cstr(&s), bufsize);
ds_destroy(&s);
return;
......@@ -7644,6 +7645,92 @@ ofputil_table_map_destroy(struct ofputil_table_map *map)
ofputil_name_map_destroy(&map->map);
}
/* Table numbers. */
/* Stores the table number represented by 's' into '*tablep'. 's' may be an
* integer or, if 'table_map' is nonnull, a name (quoted or unquoted).
*
* Returns true if successful, false if 's' is not a valid OpenFlow table
* number or name. The caller should issue an error message in this case,
* because this function usually does not. (This gives the caller an
* opportunity to look up the table name another way, e.g. by contacting the
* switch and listing the names of all its tables). */
bool
ofputil_table_from_string(const char *s,
const struct ofputil_table_map *table_map,
uint8_t *tablep)
{
*tablep = 0;
if (*s == '-') {
VLOG_WARN("Negative value %s is not a valid table number.", s);
return false;
}
unsigned int table;
if (str_to_uint(s, 10, &table)) {
if (table > 255) {
VLOG_WARN("table %u is outside the supported range 0 through 255",
table);
return false;
}
*tablep = table;
return true;
} else {
if (s[0] != '"') {
table = ofputil_table_map_get_number(table_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)) {
table = ofputil_table_map_get_number(table_map, name);
}
free(name);
}
if (table != UINT8_MAX) {
*tablep = table;
return true;
}
return false;
}
}
/* Appends to 's' a string representation of the OpenFlow table number 'table',
* either the table number or a name drawn from 'table_map'. */
void
ofputil_format_table(uint8_t table, const struct ofputil_table_map *table_map,
struct ds *s)
{
const char *table_name = ofputil_table_map_get_name(table_map, table);
if (table_name) {
put_name(table_name, s);
} else {
ds_put_format(s, "%"PRIu8, table);
}
}
/* Puts in the 'bufsize' byte in 'namebuf' a null-terminated string
* representation of OpenFlow table number 'table', either the table's number
* or a name drawn from 'table_map'. */
void
ofputil_table_to_string(uint8_t table,
const struct ofputil_table_map *table_map,
char *namebuf, size_t bufsize)
{
const char *table_name = ofputil_table_map_get_name(table_map, table);
if (table_name) {
struct ds s = DS_EMPTY_INITIALIZER;
put_name(table_name, &s);
ovs_strlcpy(namebuf, ds_cstr(&s), bufsize);
ds_destroy(&s);
return;
}
snprintf(namebuf, bufsize, "%"PRIu8, table);
}
/* 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").
......
......@@ -496,7 +496,7 @@ vcs_recv_hello(struct vconn *vconn)
ofpbuf_delete(b);
return;
} else {
char *s = ofp_to_string(b->data, b->size, NULL, 1);
char *s = ofp_to_string(b->data, b->size, NULL, NULL, 1);
VLOG_WARN_RL(&bad_ofmsg_rl,
"%s: received message while expecting hello: %s",
vconn->name, s);
......@@ -642,7 +642,8 @@ do_recv(struct vconn *vconn, struct ofpbuf **msgp)
if (!retval) {
COVERAGE_INC(vconn_received);
if (VLOG_IS_DBG_ENABLED()) {
char *s = ofp_to_string((*msgp)->data, (*msgp)->size, NULL, 1);
char *s = ofp_to_string((*msgp)->data, (*msgp)->size,
NULL, NULL, 1);
VLOG_DBG_RL(&ofmsg_rl, "%s: received: %s", vconn->name, s);
free(s);
}
......@@ -682,7 +683,7 @@ do_send(struct vconn *vconn, struct ofpbuf *msg)
COVERAGE_INC(vconn_sent);
retval = (vconn->vclass->send)(vconn, msg);
} else {
char *s = ofp_to_string(msg->data, msg->size, NULL, 1);
char *s = ofp_to_string(msg->data, msg->size, NULL, NULL, 1);
retval = (vconn->vclass->send)(vconn, msg);
if (retval != EAGAIN) {
VLOG_DBG_RL(&ofmsg_rl, "%s: sent (%s): %s",
......@@ -958,7 +959,8 @@ recv_flow_stats_reply(struct vconn *vconn, ovs_be32 send_xid,
error = ofptype_decode(&type, reply->data);
if (error || type != OFPTYPE_FLOW_STATS_REPLY) {
VLOG_WARN_RL(&rl, "received bad reply: %s",
ofp_to_string(reply->data, reply->size, NULL, 1));
ofp_to_string(reply->data, reply->size,
NULL, NULL, 1));
return EPROTO;
}
}
......
......@@ -1734,11 +1734,9 @@ flush(struct ofproto *ofproto_)
static void
query_tables(struct ofproto *ofproto,
struct ofputil_table_features *features,
struct ofputil_table_features *features OVS_UNUSED,
struct ofputil_table_stats *stats)
{
strcpy(features->name, "classifier");
if (stats) {
int i;
......
......@@ -3221,7 +3221,7 @@ query_tables(struct ofproto *ofproto,
struct ofputil_table_features *f = &features[i];
f->table_id = i;
sprintf(f->name, "table%d", i);
f->name[0] = '\0';
f->metadata_match = OVS_BE64_MAX;
f->metadata_write = OVS_BE64_MAX;
atomic_read_relaxed(&ofproto->tables[i].miss_config, &f->miss_config);
......
......@@ -294,7 +294,7 @@ recv_S_TLV_TABLE_REQUESTED(const struct ofp_header *oh, enum ofptype type,
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), NULL, 1);
char *s = ofp_to_string(oh, ntohs(oh->length), NULL, NULL, 1);
VLOG_ERR("unexpected reply to TLV table request (%s)", s);
free(s);
}
......@@ -348,7 +348,7 @@ recv_S_TLV_TABLE_MOD_SENT(const struct ofp_header *oh, enum ofptype type,
goto error;
}
} else {
char *s = ofp_to_string(oh, ntohs(oh->length), NULL, 1);
char *s = ofp_to_string(oh, ntohs(oh->length), NULL, NULL, 1);
VLOG_ERR("unexpected reply to Geneve option allocation request (%s)",
s);
free(s);
......@@ -533,7 +533,7 @@ ofctrl_run(const struct ovsrec_bridge *br_int, struct shash *pending_ct_zones)
OVS_NOT_REACHED();
}
} else {
char *s = ofp_to_string(oh, ntohs(oh->length), NULL, 1);
char *s = ofp_to_string(oh, ntohs(oh->length), NULL, NULL, 1);
VLOG_WARN("could not decode OpenFlow message (%s): %s",
ofperr_to_string(error), s);
free(s);
......@@ -593,7 +593,7 @@ log_openflow_rl(struct vlog_rate_limit *rl, enum vlog_level level,
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), NULL, 2);
char *s = ofp_to_string(oh, ntohs(oh->length), NULL, NULL, 2);
vlog(&this_module, level, "%s: %s", title, s);
free(s);
}
......@@ -870,7 +870,7 @@ ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones,
desired->table_id,
ds_cstr(&desired->info));
char *error = parse_ofp_group_mod_str(&gm, OFPGC11_ADD, group_string,
NULL, &usable_protocols);
NULL, NULL, &usable_protocols);
if (!error) {
add_group_mod(&gm, &msgs);
} else {
......@@ -985,7 +985,7 @@ ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones,
char *group_string = xasprintf("group_id=%"PRIu32"",
installed->table_id);
char *error = parse_ofp_group_mod_str(&gm, OFPGC11_DELETE,
group_string, NULL,
group_string, NULL, NULL,
&usable_protocols);
if (!error) {
add_group_mod(&gm, &msgs);
......
......@@ -1039,7 +1039,7 @@ pinctrl_recv(const struct ofp_header *oh, enum ofptype type,
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), NULL, 2);
char *s = ofp_to_string(oh, ntohs(oh->length), NULL, NULL, 2);
VLOG_DBG_RL(&rl, "OpenFlow packet ignored: %s", s);
free(s);
......
......@@ -796,7 +796,7 @@ sbctl_dump_openflow(struct vconn *vconn, const struct uuid *uuid, bool stats)
ds_clear(&s);
if (stats) {
ofp_print_flow_stats(&s, fs, NULL, true);
ofp_print_flow_stats(&s, fs, NULL, NULL, true);
} else {
ds_put_format(&s, "%stable=%s%"PRIu8" ",
colors.special, colors.end, fs->table_id);
......
......@@ -1936,7 +1936,7 @@ trace_openflow(const struct ovntrace_flow *f, struct ovs_list *super)
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], NULL, true);
ofp_print_flow_stats(&s, &fses[i], NULL, NULL, true);
ovntrace_node_append(super, OVNTRACE_NODE_ACTION,
"%s", ds_cstr(&s));
}
......
......@@ -2174,7 +2174,7 @@ OVS_VSWITCHD_START
# Check the default configuration.
head_table() {
printf 'OFPST_TABLE reply (xid=0x2):
table 0 ("%s"):
table 0%s:
active=0, lookup=0, matched=0
max_entries=1000000
matching:
......@@ -2191,14 +2191,14 @@ head_table() {
tcp_src: exact match or wildcard
tcp_dst: exact match or wildcard
' $1
' "$1"
}
ditto() {
for i in `seq $1 $2`; do
printf ' table %d ("table%d"): ditto\n' $i $i
printf ' table %d: ditto\n' $i
done
}
(head_table classifier; ditto 1 253) > expout
(head_table; ditto 1 253) > expout
AT_CHECK([ovs-ofctl dump-tables br0], [0], [expout])
# Change the configuration.
AT_CHECK(
......@@ -2211,12 +2211,12 @@ AT_CHECK(
<1>
])
# Check that the configuration was updated.
(head_table main; echo ' table 1 ("table1"):
(head_table ' ("main")'; echo ' table 1:
active=0, lookup=0, matched=0
max_entries=1024
(same matching)
table 2 ("table2"):
table 2:
active=0, lookup=0, matched=0
max_entries=1000000
(same matching)
......@@ -2250,7 +2250,7 @@ AT_CHECK([test `grep '240\.0\.0\.1' stdout | grep -v table_id= | wc -l` -gt 0])
# Check that dump-tables doesn't count the hidden flows.
head_table() {
printf 'OFPST_TABLE reply:
table 0 ("%s"):
table 0:
active=0, lookup=0, matched=0
max_entries=1000000
matching:
......@@ -2267,14 +2267,14 @@ head_table() {
tcp_src: exact match or wildcard
tcp_dst: exact match or wildcard
' $1
'
}
ditto() {
for i in `seq $1 $2`; do
printf ' table %d ("table%d"): ditto\n' $i $i
printf ' table %d: ditto\n' $i
done
}
(head_table classifier; ditto 1 253) > expout
(head_table; ditto 1 253) > expout
AT_CHECK([ovs-ofctl dump-tables br0 | strip_xids], [0], [expout])
OVS_VSWITCHD_STOP(["/240\.0\.0\.1/d"])
AT_CLEANUP
......@@ -2284,7 +2284,7 @@ OVS_VSWITCHD_START
# Check the default configuration.