+ return (port->fake_bridge
+ && port->tag
+ && *port->tag >= 1 && *port->tag <= 4095);
+}
+
+static void
+ovs_insert_bridge(const struct ovsrec_open_vswitch *ovs,
+ struct ovsrec_bridge *bridge)
+{
+ struct ovsrec_bridge **bridges;
+ size_t i;
+
+ bridges = xmalloc(sizeof *ovs->bridges * (ovs->n_bridges + 1));
+ for (i = 0; i < ovs->n_bridges; i++) {
+ bridges[i] = ovs->bridges[i];
+ }
+ bridges[ovs->n_bridges] = bridge;
+ ovsrec_open_vswitch_set_bridges(ovs, bridges, ovs->n_bridges + 1);
+ free(bridges);
+}
+
+static struct json *
+where_uuid_equals(const struct uuid *uuid)
+{
+ return
+ json_array_create_1(
+ json_array_create_3(
+ json_string_create("_uuid"),
+ json_string_create("=="),
+ json_array_create_2(
+ json_string_create("uuid"),
+ json_string_create_nocopy(
+ xasprintf(UUID_FMT, UUID_ARGS(uuid))))));
+}
+
+/* Commits 'txn'. If 'wait_for_reload' is true, also waits for Open vSwitch to
+ reload the configuration before returning.
+
+ Returns EAGAIN if the caller should try the operation again, 0 on success,
+ otherwise a positive errno value. */
+static int
+commit_txn(struct ovsdb_idl_txn *txn, bool wait_for_reload)
+{
+ struct ovsdb_idl *idl = ovsdb_idl_txn_get_idl (txn);
+ enum ovsdb_idl_txn_status status;
+ int64_t next_cfg = 0;
+
+ if (wait_for_reload) {
+ const struct ovsrec_open_vswitch *ovs = ovsrec_open_vswitch_first(idl);
+ struct json *where = where_uuid_equals(&ovs->header_.uuid);
+ ovsdb_idl_txn_increment(txn, "Open_vSwitch", "next_cfg", where);
+ json_destroy(where);
+ }
+ status = ovsdb_idl_txn_commit_block(txn);
+ if (wait_for_reload && status == TXN_SUCCESS) {
+ next_cfg = ovsdb_idl_txn_get_increment_new_value(txn);
+ }
+ ovsdb_idl_txn_destroy(txn);
+
+ switch (status) {
+ case TXN_INCOMPLETE:
+ NOT_REACHED();
+
+ case TXN_ABORTED:
+ VLOG_ERR_RL(&rl, "OVSDB transaction unexpectedly aborted");
+ return ECONNABORTED;