summaryrefslogtreecommitdiff
path: root/utilities
diff options
context:
space:
mode:
authorBen Pfaff <blp@ovn.org>2018-08-29 11:30:13 -0700
committerBen Pfaff <blp@ovn.org>2019-01-15 16:59:37 -0800
commit4e413ac88d4841d7e17de3e36bba3fa12796e938 (patch)
treef2b60dfccac0bec0393e261721cfa78f99458a98 /utilities
parentd1a227ecef81773a748320cee733334d21b484ce (diff)
downloadopenvswitch-4e413ac88d4841d7e17de3e36bba3fa12796e938.tar.gz
ovs-vswitchd: Implement OFPT_TABLE_FEATURES table modification request.
This allows a controller to change the name of OpenFlow flow tables in the OVS software switch. CC: Brad Cowie <brad@cowie.nz> Acked-by: Justin Pettit <jpettit@ovn.org> Signed-off-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'utilities')
-rw-r--r--utilities/ovs-ofctl.8.in12
-rw-r--r--utilities/ovs-ofctl.c128
2 files changed, 119 insertions, 21 deletions
diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in
index 81827b1ec..c7b156571 100644
--- a/utilities/ovs-ofctl.8.in
+++ b/utilities/ovs-ofctl.8.in
@@ -84,6 +84,18 @@ Send to controller. (This is how an OpenFlow 1.0 switch always
handles packets that do not match any flow in the last table.)
.RE
.IP
+In OpenFlow 1.3 and later (which must be enabled with the \fB\-O\fR
+option) and Open vSwitch 2.11 and later only, \fBmod\-table\fR can
+change the name of a table:
+.RS
+.IP \fBname:\fInew-name\fR
+Changes the name of the table to \fInew-name\fR. Use an empty
+\fInew-name\fR to clear the name. (This will be ineffective if the
+name is set via the \fBname\fR column in the \fBFlow_Table\fR table in
+the \fBOpen_vSwitch\fR database as described in
+\fBovs\-vswitchd.conf.db\fR(5).)
+.RE
+.IP
In OpenFlow 1.4 and later (which must be enabled with the \fB\-O\fR
option) only, \fBmod\-table\fR configures the behavior when a
controller attempts to add a flow to a flow table that is full. The
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index 0ff4ed259..aab5a5cd9 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -913,9 +913,9 @@ ofctl_dump_table_features(struct ovs_cmdl_context *ctx)
done = !ofpmp_more(reply->data);
for (;;) {
struct ofputil_table_features tf;
- int retval;
-
- retval = ofputil_decode_table_features(reply, &tf, true);
+ struct ofpbuf raw_properties;
+ int retval = ofputil_decode_table_features(
+ reply, &tf, &raw_properties);
if (retval) {
if (retval != EOF) {
ovs_fatal(0, "decode error: %s",
@@ -1207,6 +1207,7 @@ struct table_iterator {
bool more;
struct ofputil_table_features features;
+ struct ofpbuf raw_properties;
};
/* Initializes 'ti' to prepare for iterating through all of the tables on the
@@ -1248,7 +1249,7 @@ table_iterator_next(struct table_iterator *ti)
ovs_assert(ti->variant == TI_FEATURES);
retval = ofputil_decode_table_features(ti->reply,
&ti->features,
- true);
+ &ti->raw_properties);
}
if (!retval) {
return &ti->features;
@@ -2581,15 +2582,94 @@ fetch_table_desc(struct vconn *vconn, struct ofputil_table_mod *tm,
}
static void
+change_table_name(struct vconn *vconn, uint8_t table_id, const char *new_name)
+{
+ /* Get all tables' features and properties. */
+ struct table {
+ struct ofputil_table_features tf;
+ struct ofpbuf *raw_properties;
+ } *tables[256];
+ memset(tables, 0, sizeof tables);
+
+ struct table_iterator ti;
+ table_iterator_init(&ti, vconn);
+ while (table_iterator_next(&ti)) {
+ struct table *t = tables[ti.features.table_id] = xmalloc(sizeof *t);
+ t->tf = ti.features;
+ t->raw_properties = ofpbuf_clone(&ti.raw_properties);
+ }
+ table_iterator_destroy(&ti);
+
+ /* Change the name for table 'table_id'. */
+ struct table *t = tables[table_id];
+ if (!t) {
+ ovs_fatal(0, "switch does not have table %"PRIu8, table_id);
+ }
+ ovs_strlcpy(t->tf.name, new_name, OFP_MAX_TABLE_NAME_LEN);
+
+ /* Compose the transaction. */
+ enum ofp_version version = vconn_get_version(vconn);
+ struct ovs_list requests = OVS_LIST_INITIALIZER(&requests);
+ struct ofpbuf *tfr = ofputil_encode_table_features_request(version);
+ ovs_list_push_back(&requests, &tfr->list_node);
+ if (version >= OFP15_VERSION) {
+ /* For OpenFlow 1.5, we can use a single OFPTFC15_MODIFY without any
+ * properties. */
+ t->tf.command = OFPTFC15_MODIFY;
+ t->tf.any_properties = false;
+ ofputil_append_table_features(&t->tf, NULL, &requests);
+ } else {
+ /* For OpenFlow 1.3 and 1.4, we have to regurgitate all of the tables
+ * and their properties. */
+ for (size_t i = 0; i < 256; i++) {
+ if (tables[i]) {
+ ofputil_append_table_features(&tables[i]->tf,
+ tables[i]->raw_properties,
+ &requests);
+ }
+ }
+ }
+
+ /* Transact.
+ *
+ * The reply repeats the entire new configuration of the tables, so we
+ * don't bother printing it unless there's an error. */
+ struct ovs_list replies;
+ struct ofpbuf *reply;
+ vconn_transact_multipart(vconn, &requests, &replies);
+ LIST_FOR_EACH (reply, list_node, &replies) {
+ enum ofptype type;
+ enum ofperr error = ofptype_decode(&type, reply->data);
+ if (error) {
+ ovs_fatal(0, "decode error: %s", ofperr_get_name(error));
+ } else if (type == OFPTYPE_ERROR) {
+ ofp_print(stderr, reply->data, reply->size, NULL, NULL,
+ verbosity + 1);
+ exit(1);
+ }
+ }
+ ofpbuf_list_delete(&replies);
+
+ /* Clean up. */
+ for (size_t i = 0; i < ARRAY_SIZE(tables); i++) {
+ if (tables[i]) {
+ ofpbuf_delete(tables[i]->raw_properties);
+ free(tables[i]);
+ }
+ }
+}
+
+static void
ofctl_mod_table(struct ovs_cmdl_context *ctx)
{
uint32_t usable_versions;
struct ofputil_table_mod tm;
+ const char *name;
struct vconn *vconn;
char *error;
int i;
- error = parse_ofp_table_mod(&tm, ctx->argv[2], ctx->argv[3],
+ error = parse_ofp_table_mod(&tm, &name, ctx->argv[2], ctx->argv[3],
tables_to_accept(ctx->argv[1]),
&usable_versions);
if (error) {
@@ -2607,27 +2687,33 @@ ofctl_mod_table(struct ovs_cmdl_context *ctx)
mask_allowed_ofp_versions(usable_versions);
enum ofputil_protocol protocol = open_vconn(ctx->argv[1], &vconn);
- /* For OpenFlow 1.4+, ovs-ofctl mod-table should not affect table-config
- * properties that the user didn't ask to change, so it is necessary to
- * restore the current configuration of table-config parameters using
- * OFPMP14_TABLE_DESC request. */
- if ((allowed_versions & (1u << OFP14_VERSION)) ||
- (allowed_versions & (1u << OFP15_VERSION))) {
- struct ofputil_table_desc td;
-
- if (tm.table_id == OFPTT_ALL) {
- for (i = 0; i < OFPTT_MAX; i++) {
- tm.table_id = i;
+ if (name) {
+ change_table_name(vconn, tm.table_id, name);
+ } else {
+ /* For OpenFlow 1.4+, ovs-ofctl mod-table should not affect
+ * table-config properties that the user didn't ask to change, so it is
+ * necessary to restore the current configuration of table-config
+ * parameters using OFPMP14_TABLE_DESC request. */
+ if (allowed_versions & ((1u << OFP14_VERSION) |
+ (1u << OFP15_VERSION) |
+ (1u << OFP16_VERSION))) {
+ struct ofputil_table_desc td;
+
+ if (tm.table_id == OFPTT_ALL) {
+ for (i = 0; i < OFPTT_MAX; i++) {
+ tm.table_id = i;
+ fetch_table_desc(vconn, &tm, &td);
+ transact_noreply(vconn,
+ ofputil_encode_table_mod(&tm, protocol));
+ }
+ } else {
fetch_table_desc(vconn, &tm, &td);
- transact_noreply(vconn,
- ofputil_encode_table_mod(&tm, protocol));
+ transact_noreply(vconn, ofputil_encode_table_mod(&tm,
+ protocol));
}
} else {
- fetch_table_desc(vconn, &tm, &td);
transact_noreply(vconn, ofputil_encode_table_mod(&tm, protocol));
}
- } else {
- transact_noreply(vconn, ofputil_encode_table_mod(&tm, protocol));
}
vconn_close(vconn);
}