diff options
author | Ben Pfaff <blp@ovn.org> | 2018-01-05 16:59:13 -0800 |
---|---|---|
committer | Ben Pfaff <blp@ovn.org> | 2018-02-01 10:08:32 -0800 |
commit | 4bc938ccb3124282c873084a7d11cd8bc37e27a7 (patch) | |
tree | 1e890e37284ea4a4f4618d073e064b2a194d244a /lib/ofp-util.c | |
parent | a203f653b1a6a2544603be00966b8d4731d91b69 (diff) | |
download | openvswitch-4bc938ccb3124282c873084a7d11cd8bc37e27a7.tar.gz |
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: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
Diffstat (limited to 'lib/ofp-util.c')
-rw-r--r-- | lib/ofp-util.c | 109 |
1 files changed, 98 insertions, 11 deletions
diff --git a/lib/ofp-util.c b/lib/ofp-util.c index f3b2e3f61..09ad93132 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -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"). |