mirror of
https://github.com/openvswitch/ovs
synced 2025-08-31 06:15:47 +00:00
Support accepting and displaying port names in OVS tools.
Until now, most ovs-ofctl commands have not accepted names for ports, only numbers, and have not been able to display port names either. It's a lot easier for users if they can use and see meaningful names instead of arbitrary numbers. This commit adds that support. For backward compatibility, only interactive ovs-ofctl commands by default display port names; to display them in scripts, use the new --names option. Signed-off-by: Ben Pfaff <blp@ovn.org> Tested-by: Aaron Conole <aconole@redhat.com>
This commit is contained in:
129
lib/ofp-parse.c
129
lib/ofp-parse.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
|
||||
* Copyright (c) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 Nicira, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -235,7 +235,8 @@ parse_protocol(const char *name, const struct protocol **p_out)
|
||||
* Returns NULL if successful, otherwise a malloc()'d string describing the
|
||||
* error. The caller is responsible for freeing the returned string. */
|
||||
static char * OVS_WARN_UNUSED_RESULT
|
||||
parse_field(const struct mf_field *mf, const char *s, struct match *match,
|
||||
parse_field(const struct mf_field *mf, const char *s,
|
||||
const struct ofputil_port_map *port_map, struct match *match,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
{
|
||||
union mf_value value, mask;
|
||||
@@ -247,7 +248,7 @@ parse_field(const struct mf_field *mf, const char *s, struct match *match,
|
||||
s = "0/0";
|
||||
}
|
||||
|
||||
error = mf_parse(mf, s, &value, &mask);
|
||||
error = mf_parse(mf, s, port_map, &value, &mask);
|
||||
if (!error) {
|
||||
*usable_protocols &= mf_set(mf, &value, &mask, match, &error);
|
||||
}
|
||||
@@ -281,7 +282,7 @@ parse_subfield(const char *name, const char *str_value, struct match *match,
|
||||
struct ds ds;
|
||||
|
||||
ds_init(&ds);
|
||||
mf_format(sf.field, &val, NULL, &ds);
|
||||
mf_format(sf.field, &val, NULL, NULL, &ds);
|
||||
error = xasprintf("%s: value %s does not fit into %d bits",
|
||||
name, ds_cstr(&ds), sf.n_bits);
|
||||
ds_destroy(&ds);
|
||||
@@ -316,6 +317,7 @@ extract_actions(char *s)
|
||||
|
||||
static char * OVS_WARN_UNUSED_RESULT
|
||||
parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string,
|
||||
const struct ofputil_port_map *port_map,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
{
|
||||
enum {
|
||||
@@ -431,7 +433,8 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string,
|
||||
|| !strcmp(name, "allow_hidden_fields")) {
|
||||
/* ignore these fields. */
|
||||
} else if ((mf = mf_from_name(name)) != NULL) {
|
||||
error = parse_field(mf, value, &fm->match, usable_protocols);
|
||||
error = parse_field(mf, value, port_map,
|
||||
&fm->match, usable_protocols);
|
||||
} else if (strchr(name, '[')) {
|
||||
error = parse_subfield(name, value, &fm->match, usable_protocols);
|
||||
} else {
|
||||
@@ -445,7 +448,8 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string,
|
||||
*usable_protocols &= OFPUTIL_P_TID;
|
||||
}
|
||||
} else if (fields & F_OUT_PORT && !strcmp(name, "out_port")) {
|
||||
if (!ofputil_port_from_string(value, &fm->out_port)) {
|
||||
if (!ofputil_port_from_string(value, port_map,
|
||||
&fm->out_port)) {
|
||||
error = xasprintf("%s is not a valid OpenFlow port",
|
||||
value);
|
||||
}
|
||||
@@ -540,7 +544,7 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string,
|
||||
char *error;
|
||||
|
||||
ofpbuf_init(&ofpacts, 32);
|
||||
error = ofpacts_parse_instructions(act_str, &ofpacts,
|
||||
error = ofpacts_parse_instructions(act_str, port_map, &ofpacts,
|
||||
&action_usable_protocols);
|
||||
*usable_protocols &= action_usable_protocols;
|
||||
if (!error) {
|
||||
@@ -588,12 +592,13 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string,
|
||||
* error. The caller is responsible for freeing the returned string. */
|
||||
char * OVS_WARN_UNUSED_RESULT
|
||||
parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
|
||||
const struct ofputil_port_map *port_map,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
{
|
||||
char *string = xstrdup(str_);
|
||||
char *error;
|
||||
|
||||
error = parse_ofp_str__(fm, command, string, usable_protocols);
|
||||
error = parse_ofp_str__(fm, command, string, port_map, usable_protocols);
|
||||
if (error) {
|
||||
fm->ofpacts = NULL;
|
||||
fm->ofpacts_len = 0;
|
||||
@@ -607,6 +612,7 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
|
||||
* both 'po->ofpacts' and 'po->packet' must be free()d by the caller. */
|
||||
static char * OVS_WARN_UNUSED_RESULT
|
||||
parse_ofp_packet_out_str__(struct ofputil_packet_out *po, char *string,
|
||||
const struct ofputil_port_map *port_map,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
{
|
||||
enum ofputil_protocol action_usable_protocols;
|
||||
@@ -635,7 +641,7 @@ parse_ofp_packet_out_str__(struct ofputil_packet_out *po, char *string,
|
||||
|
||||
if (!strcmp(name, "in_port")) {
|
||||
ofp_port_t in_port;
|
||||
if (!ofputil_port_from_string(value, &in_port)) {
|
||||
if (!ofputil_port_from_string(value, port_map, &in_port)) {
|
||||
error = xasprintf("%s is not a valid OpenFlow port", value);
|
||||
goto out;
|
||||
}
|
||||
@@ -662,7 +668,7 @@ parse_ofp_packet_out_str__(struct ofputil_packet_out *po, char *string,
|
||||
goto out;
|
||||
}
|
||||
|
||||
error = parse_field(mf, value, &po->flow_metadata,
|
||||
error = parse_field(mf, value, port_map, &po->flow_metadata,
|
||||
usable_protocols);
|
||||
if (error) {
|
||||
goto out;
|
||||
@@ -681,7 +687,7 @@ parse_ofp_packet_out_str__(struct ofputil_packet_out *po, char *string,
|
||||
}
|
||||
|
||||
if (act_str) {
|
||||
error = ofpacts_parse_actions(act_str, &ofpacts,
|
||||
error = ofpacts_parse_actions(act_str, port_map, &ofpacts,
|
||||
&action_usable_protocols);
|
||||
*usable_protocols &= action_usable_protocols;
|
||||
if (error) {
|
||||
@@ -707,12 +713,13 @@ out:
|
||||
* error. The caller is responsible for freeing the returned string. */
|
||||
char * OVS_WARN_UNUSED_RESULT
|
||||
parse_ofp_packet_out_str(struct ofputil_packet_out *po, const char *str_,
|
||||
const struct ofputil_port_map *port_map,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
{
|
||||
char *string = xstrdup(str_);
|
||||
char *error;
|
||||
|
||||
error = parse_ofp_packet_out_str__(po, string, usable_protocols);
|
||||
error = parse_ofp_packet_out_str__(po, string, port_map, usable_protocols);
|
||||
if (error) {
|
||||
po->ofpacts = NULL;
|
||||
po->ofpacts_len = 0;
|
||||
@@ -948,7 +955,9 @@ parse_ofp_meter_mod_str(struct ofputil_meter_mod *mm, const char *str_,
|
||||
|
||||
static char * OVS_WARN_UNUSED_RESULT
|
||||
parse_flow_monitor_request__(struct ofputil_flow_monitor_request *fmr,
|
||||
const char *str_, char *string,
|
||||
const char *str_,
|
||||
const struct ofputil_port_map *port_map,
|
||||
char *string,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
{
|
||||
static atomic_count id = ATOMIC_COUNT_INIT(0);
|
||||
@@ -984,8 +993,8 @@ parse_flow_monitor_request__(struct ofputil_flow_monitor_request *fmr,
|
||||
match_set_nw_proto(&fmr->match, p->nw_proto);
|
||||
}
|
||||
} else if (mf_from_name(name)) {
|
||||
error = parse_field(mf_from_name(name), value, &fmr->match,
|
||||
usable_protocols);
|
||||
error = parse_field(mf_from_name(name), value, port_map,
|
||||
&fmr->match, usable_protocols);
|
||||
} else {
|
||||
if (!*value) {
|
||||
return xasprintf("%s: field %s missing value", str_, name);
|
||||
@@ -1015,10 +1024,11 @@ parse_flow_monitor_request__(struct ofputil_flow_monitor_request *fmr,
|
||||
char * OVS_WARN_UNUSED_RESULT
|
||||
parse_flow_monitor_request(struct ofputil_flow_monitor_request *fmr,
|
||||
const char *str_,
|
||||
const struct ofputil_port_map *port_map,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
{
|
||||
char *string = xstrdup(str_);
|
||||
char *error = parse_flow_monitor_request__(fmr, str_, string,
|
||||
char *error = parse_flow_monitor_request__(fmr, str_, port_map, string,
|
||||
usable_protocols);
|
||||
free(string);
|
||||
return error;
|
||||
@@ -1035,10 +1045,11 @@ parse_flow_monitor_request(struct ofputil_flow_monitor_request *fmr,
|
||||
* error. The caller is responsible for freeing the returned string. */
|
||||
char * OVS_WARN_UNUSED_RESULT
|
||||
parse_ofp_flow_mod_str(struct ofputil_flow_mod *fm, const char *string,
|
||||
int command,
|
||||
const struct ofputil_port_map *port_map, int command,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
{
|
||||
char *error = parse_ofp_str(fm, command, string, usable_protocols);
|
||||
char *error = parse_ofp_str(fm, command, string, port_map,
|
||||
usable_protocols);
|
||||
|
||||
if (!error) {
|
||||
/* Normalize a copy of the match. This ensures that non-normalized
|
||||
@@ -1189,7 +1200,8 @@ parse_ofp_table_mod(struct ofputil_table_mod *tm, const char *table_id,
|
||||
* Returns NULL if successful, otherwise a malloc()'d string describing the
|
||||
* error. The caller is responsible for freeing the returned string. */
|
||||
char * OVS_WARN_UNUSED_RESULT
|
||||
parse_ofp_flow_mod_file(const char *file_name, int command,
|
||||
parse_ofp_flow_mod_file(const char *file_name,
|
||||
const struct ofputil_port_map *port_map, int command,
|
||||
struct ofputil_flow_mod **fms, size_t *n_fms,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
{
|
||||
@@ -1219,8 +1231,8 @@ parse_ofp_flow_mod_file(const char *file_name, int command,
|
||||
if (*n_fms >= allocated_fms) {
|
||||
*fms = x2nrealloc(*fms, &allocated_fms, sizeof **fms);
|
||||
}
|
||||
error = parse_ofp_flow_mod_str(&(*fms)[*n_fms], ds_cstr(&s), command,
|
||||
&usable);
|
||||
error = parse_ofp_flow_mod_str(&(*fms)[*n_fms], ds_cstr(&s), port_map,
|
||||
command, &usable);
|
||||
if (error) {
|
||||
char *err_msg;
|
||||
size_t i;
|
||||
@@ -1255,12 +1267,13 @@ parse_ofp_flow_mod_file(const char *file_name, int command,
|
||||
char * OVS_WARN_UNUSED_RESULT
|
||||
parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *fsr,
|
||||
bool aggregate, const char *string,
|
||||
const struct ofputil_port_map *port_map,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
{
|
||||
struct ofputil_flow_mod fm;
|
||||
char *error;
|
||||
|
||||
error = parse_ofp_str(&fm, -1, string, usable_protocols);
|
||||
error = parse_ofp_str(&fm, -1, string, port_map, usable_protocols);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
@@ -1295,7 +1308,7 @@ parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *fsr,
|
||||
char *
|
||||
parse_ofp_exact_flow(struct flow *flow, struct flow_wildcards *wc,
|
||||
const struct tun_table *tun_table, const char *s,
|
||||
const struct simap *portno_names)
|
||||
const struct ofputil_port_map *port_map)
|
||||
{
|
||||
char *pos, *key, *value_s;
|
||||
char *error = NULL;
|
||||
@@ -1353,28 +1366,17 @@ parse_ofp_exact_flow(struct flow *flow, struct flow_wildcards *wc,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!strcmp(key, "in_port")
|
||||
&& portno_names
|
||||
&& simap_contains(portno_names, value_s)) {
|
||||
flow->in_port.ofp_port = u16_to_ofp(
|
||||
simap_get(portno_names, value_s));
|
||||
if (wc) {
|
||||
wc->masks.in_port.ofp_port
|
||||
= u16_to_ofp(ntohs(OVS_BE16_MAX));
|
||||
}
|
||||
} else {
|
||||
field_error = mf_parse_value(mf, value_s, &value);
|
||||
if (field_error) {
|
||||
error = xasprintf("%s: bad value for %s (%s)",
|
||||
s, key, field_error);
|
||||
free(field_error);
|
||||
goto exit;
|
||||
}
|
||||
field_error = mf_parse_value(mf, value_s, port_map, &value);
|
||||
if (field_error) {
|
||||
error = xasprintf("%s: bad value for %s (%s)",
|
||||
s, key, field_error);
|
||||
free(field_error);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mf_set_flow_value(mf, &value, flow);
|
||||
if (wc) {
|
||||
mf_mask_field(mf, wc);
|
||||
}
|
||||
mf_set_flow_value(mf, &value, flow);
|
||||
if (wc) {
|
||||
mf_mask_field(mf, wc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1396,8 +1398,9 @@ exit:
|
||||
}
|
||||
|
||||
static char * OVS_WARN_UNUSED_RESULT
|
||||
parse_bucket_str(struct ofputil_bucket *bucket, char *str_, uint8_t group_type,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
parse_bucket_str(struct ofputil_bucket *bucket, char *str_,
|
||||
const struct ofputil_port_map *port_map, uint8_t group_type,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
{
|
||||
char *pos, *key, *value;
|
||||
struct ofpbuf ofpacts;
|
||||
@@ -1417,7 +1420,7 @@ parse_bucket_str(struct ofputil_bucket *bucket, char *str_, uint8_t group_type,
|
||||
if (!strcasecmp(key, "weight")) {
|
||||
error = str_to_u16(value, "weight", &bucket->weight);
|
||||
} else if (!strcasecmp(key, "watch_port")) {
|
||||
if (!ofputil_port_from_string(value, &bucket->watch_port)
|
||||
if (!ofputil_port_from_string(value, port_map, &bucket->watch_port)
|
||||
|| (ofp_to_u16(bucket->watch_port) >= ofp_to_u16(OFPP_MAX)
|
||||
&& bucket->watch_port != OFPP_ANY)) {
|
||||
error = xasprintf("%s: invalid watch_port", value);
|
||||
@@ -1453,7 +1456,7 @@ parse_bucket_str(struct ofputil_bucket *bucket, char *str_, uint8_t group_type,
|
||||
ds_chomp(&actions, ',');
|
||||
|
||||
ofpbuf_init(&ofpacts, 0);
|
||||
error = ofpacts_parse_actions(ds_cstr(&actions), &ofpacts,
|
||||
error = ofpacts_parse_actions(ds_cstr(&actions), port_map, &ofpacts,
|
||||
usable_protocols);
|
||||
ds_destroy(&actions);
|
||||
if (error) {
|
||||
@@ -1467,7 +1470,8 @@ parse_bucket_str(struct ofputil_bucket *bucket, char *str_, uint8_t group_type,
|
||||
}
|
||||
|
||||
static char * OVS_WARN_UNUSED_RESULT
|
||||
parse_select_group_field(char *s, struct field_array *fa,
|
||||
parse_select_group_field(char *s, const struct ofputil_port_map *port_map,
|
||||
struct field_array *fa,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
{
|
||||
char *name, *value_str;
|
||||
@@ -1484,7 +1488,7 @@ parse_select_group_field(char *s, struct field_array *fa,
|
||||
}
|
||||
|
||||
if (*value_str) {
|
||||
error = mf_parse_value(mf, value_str, &value);
|
||||
error = mf_parse_value(mf, value_str, port_map, &value);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
@@ -1527,6 +1531,7 @@ parse_select_group_field(char *s, struct field_array *fa,
|
||||
static char * OVS_WARN_UNUSED_RESULT
|
||||
parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, int command,
|
||||
char *string,
|
||||
const struct ofputil_port_map *port_map,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
{
|
||||
enum {
|
||||
@@ -1720,7 +1725,8 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, int command,
|
||||
error = xstrdup("fields are not needed");
|
||||
goto out;
|
||||
}
|
||||
error = parse_select_group_field(value, &gm->props.fields,
|
||||
error = parse_select_group_field(value, port_map,
|
||||
&gm->props.fields,
|
||||
usable_protocols);
|
||||
if (error) {
|
||||
goto out;
|
||||
@@ -1779,7 +1785,8 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, int command,
|
||||
}
|
||||
|
||||
bucket = xzalloc(sizeof(struct ofputil_bucket));
|
||||
error = parse_bucket_str(bucket, bkt_str, gm->type, usable_protocols);
|
||||
error = parse_bucket_str(bucket, bkt_str, port_map,
|
||||
gm->type, usable_protocols);
|
||||
if (error) {
|
||||
free(bucket);
|
||||
goto out;
|
||||
@@ -1811,11 +1818,12 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, int command,
|
||||
char * OVS_WARN_UNUSED_RESULT
|
||||
parse_ofp_group_mod_str(struct ofputil_group_mod *gm, int command,
|
||||
const char *str_,
|
||||
const struct ofputil_port_map *port_map,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
{
|
||||
char *string = xstrdup(str_);
|
||||
char *error = parse_ofp_group_mod_str__(gm, command, string,
|
||||
usable_protocols);
|
||||
port_map, usable_protocols);
|
||||
free(string);
|
||||
return error;
|
||||
}
|
||||
@@ -1825,7 +1833,9 @@ parse_ofp_group_mod_str(struct ofputil_group_mod *gm, int command,
|
||||
* missing command name is treated as "add".
|
||||
*/
|
||||
char * OVS_WARN_UNUSED_RESULT
|
||||
parse_ofp_group_mod_file(const char *file_name, int command,
|
||||
parse_ofp_group_mod_file(const char *file_name,
|
||||
const struct ofputil_port_map *port_map,
|
||||
int command,
|
||||
struct ofputil_group_mod **gms, size_t *n_gms,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
{
|
||||
@@ -1862,7 +1872,7 @@ parse_ofp_group_mod_file(const char *file_name, int command,
|
||||
*gms = new_gms;
|
||||
}
|
||||
error = parse_ofp_group_mod_str(&(*gms)[*n_gms], command, ds_cstr(&s),
|
||||
&usable);
|
||||
port_map, &usable);
|
||||
if (error) {
|
||||
size_t i;
|
||||
|
||||
@@ -1900,6 +1910,7 @@ parse_ofp_group_mod_file(const char *file_name, int command,
|
||||
* error. The caller is responsible for freeing the returned string. */
|
||||
char * OVS_WARN_UNUSED_RESULT
|
||||
parse_ofp_bundle_file(const char *file_name,
|
||||
const struct ofputil_port_map *port_map,
|
||||
struct ofputil_bundle_msg **bms, size_t *n_bms,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
{
|
||||
@@ -1946,7 +1957,8 @@ parse_ofp_bundle_file(const char *file_name,
|
||||
|
||||
if (!strncmp(s, "flow", len)) {
|
||||
s += len;
|
||||
error = parse_ofp_flow_mod_str(&(*bms)[*n_bms].fm, s, -2, &usable);
|
||||
error = parse_ofp_flow_mod_str(&(*bms)[*n_bms].fm, s, port_map,
|
||||
-2, &usable);
|
||||
if (error) {
|
||||
break;
|
||||
}
|
||||
@@ -1954,14 +1966,15 @@ parse_ofp_bundle_file(const char *file_name,
|
||||
} else if (!strncmp(s, "group", len)) {
|
||||
s += len;
|
||||
error = parse_ofp_group_mod_str(&(*bms)[*n_bms].gm, -2, s,
|
||||
&usable);
|
||||
port_map, &usable);
|
||||
if (error) {
|
||||
break;
|
||||
}
|
||||
(*bms)[*n_bms].type = OFPTYPE_GROUP_MOD;
|
||||
} else if (!strncmp(s, "packet-out", len)) {
|
||||
s += len;
|
||||
error = parse_ofp_packet_out_str(&(*bms)[*n_bms].po, s, &usable);
|
||||
error = parse_ofp_packet_out_str(&(*bms)[*n_bms].po, s, port_map,
|
||||
&usable);
|
||||
if (error) {
|
||||
break;
|
||||
}
|
||||
|
Reference in New Issue
Block a user