ovs-vswitchd should only write to write-only columns. Furthermore,
writing to a column which is not write-only can cause serious
performance degradations. This patch causes ovs-vswitchd to log
and reject writes to read-write columns.
Signed-off-by: Ethan Jackson <ethan@nicira.com>
struct json *monitor_request_id;
unsigned int last_monitor_request_seqno;
unsigned int change_seqno;
struct json *monitor_request_id;
unsigned int last_monitor_request_seqno;
unsigned int change_seqno;
+ bool verify_write_only;
/* Database locking. */
char *lock_name; /* Name of lock we need, NULL if none. */
/* Database locking. */
char *lock_name; /* Name of lock we need, NULL if none. */
{
jsonrpc_session_force_reconnect(idl->session);
}
{
jsonrpc_session_force_reconnect(idl->session);
}
+
+/* Some IDL users should only write to write-only columns. Furthermore,
+ * writing to a column which is not write-only can cause serious performance
+ * degradations for these users. This function causes 'idl' to reject writes
+ * to columns which are not marked write only using ovsdb_idl_omit_alert(). */
+void
+ovsdb_idl_verify_write_only(struct ovsdb_idl *idl)
+{
+ idl->verify_write_only = true;
+}
\f
static unsigned char *
ovsdb_idl_get_mode(struct ovsdb_idl *idl,
\f
static unsigned char *
ovsdb_idl_get_mode(struct ovsdb_idl *idl,
struct ovsdb_idl_row *row = CONST_CAST(struct ovsdb_idl_row *, row_);
const struct ovsdb_idl_table_class *class;
size_t column_idx;
struct ovsdb_idl_row *row = CONST_CAST(struct ovsdb_idl_row *, row_);
const struct ovsdb_idl_table_class *class;
size_t column_idx;
if (ovsdb_idl_row_is_synthetic(row)) {
ovsdb_datum_destroy(datum, &column->type);
if (ovsdb_idl_row_is_synthetic(row)) {
ovsdb_datum_destroy(datum, &column->type);
class = row->table->class;
column_idx = column - class->columns;
class = row->table->class;
column_idx = column - class->columns;
+ write_only = row->table->modes[column_idx] == OVSDB_IDL_MONITOR;
assert(row->new != NULL);
assert(column_idx < class->n_columns);
assert(row->old == NULL ||
row->table->modes[column_idx] & OVSDB_IDL_MONITOR);
assert(row->new != NULL);
assert(column_idx < class->n_columns);
assert(row->old == NULL ||
row->table->modes[column_idx] & OVSDB_IDL_MONITOR);
+ if (row->table->idl->verify_write_only && !write_only) {
+ VLOG_ERR("Bug: Attempt to write to a read/write column (%s:%s) when"
+ " explicitly configured not to.", class->name, column->name);
+ ovsdb_datum_destroy(datum, &column->type);
+ return;
+ }
+
/* If this is a write-only column and the datum being written is the same
* as the one already there, just skip the update entirely. This is worth
* optimizing because we have a lot of columns that get periodically
/* If this is a write-only column and the datum being written is the same
* as the one already there, just skip the update entirely. This is worth
* optimizing because we have a lot of columns that get periodically
* transaction only does writes of existing values, without making any real
* changes, we will drop the whole transaction later in
* ovsdb_idl_txn_commit().) */
* transaction only does writes of existing values, without making any real
* changes, we will drop the whole transaction later in
* ovsdb_idl_txn_commit().) */
- if (row->table->modes[column_idx] == OVSDB_IDL_MONITOR
- && ovsdb_datum_equals(ovsdb_idl_read(row, column),
- datum, &column->type)) {
+ if (write_only && ovsdb_datum_equals(ovsdb_idl_read(row, column),
+ datum, &column->type)) {
ovsdb_datum_destroy(datum, &column->type);
return;
}
ovsdb_datum_destroy(datum, &column->type);
return;
}
unsigned int ovsdb_idl_get_seqno(const struct ovsdb_idl *);
bool ovsdb_idl_has_ever_connected(const struct ovsdb_idl *);
void ovsdb_idl_force_reconnect(struct ovsdb_idl *);
unsigned int ovsdb_idl_get_seqno(const struct ovsdb_idl *);
bool ovsdb_idl_has_ever_connected(const struct ovsdb_idl *);
void ovsdb_idl_force_reconnect(struct ovsdb_idl *);
+void ovsdb_idl_verify_write_only(struct ovsdb_idl *);
\f
/* Choosing columns and tables to replicate. */
\f
/* Choosing columns and tables to replicate. */
idl = ovsdb_idl_create(remote, &ovsrec_idl_class, true);
idl_seqno = ovsdb_idl_get_seqno(idl);
ovsdb_idl_set_lock(idl, "ovs_vswitchd");
idl = ovsdb_idl_create(remote, &ovsrec_idl_class, true);
idl_seqno = ovsdb_idl_get_seqno(idl);
ovsdb_idl_set_lock(idl, "ovs_vswitchd");
+ ovsdb_idl_verify_write_only(idl);
ovsdb_idl_omit_alert(idl, &ovsrec_open_vswitch_col_cur_cfg);
ovsdb_idl_omit_alert(idl, &ovsrec_open_vswitch_col_statistics);
ovsdb_idl_omit_alert(idl, &ovsrec_open_vswitch_col_cur_cfg);
ovsdb_idl_omit_alert(idl, &ovsrec_open_vswitch_col_statistics);