+/* Add all the ports for 'bridge' to 'ports'. Bonded ports are reported under
+ * the bond name, not broken down into their constituent interfaces.
+ *
+ * If 'vlan' < 0, all ports on 'bridge' are reported. If 'vlan' == 0, then
+ * only trunk ports or ports with implicit VLAN 0 are reported. If 'vlan' > 0,
+ * only port with implicit VLAN 'vlan' are reported. */
+static void
+get_bridge_ports(const struct ovsrec_bridge *br, struct svec *ports,
+ int vlan)
+{
+ do_get_bridge_parts(br, ports, vlan, false);
+}
+
+static struct ovsdb_idl_txn *
+txn_from_openvswitch(const struct ovsrec_open_vswitch *ovs)
+{
+ return ovsdb_idl_txn_get(&ovs->header_);
+}
+
+static bool
+port_is_fake_bridge(const struct ovsrec_port *port)
+{
+ 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;
+
+ case TXN_UNCHANGED:
+ return 0;
+
+ case TXN_SUCCESS:
+ if (wait_for_reload) {
+ for (;;) {
+ /* We can't use 'ovs' any longer because ovsdb_idl_run() can
+ * destroy it. */
+ const struct ovsrec_open_vswitch *ovs2;
+
+ ovsdb_idl_run(idl);
+ OVSREC_OPEN_VSWITCH_FOR_EACH (ovs2, idl) {
+ if (ovs2->cur_cfg >= next_cfg) {
+ goto done;
+ }
+ }
+ ovsdb_idl_wait(idl);
+ poll_block();