-static struct ovsrec_bridge *
-find_bridge(const struct ovsrec_open_vswitch *ovs, const char *br_name)
-{
- size_t i;
-
- for (i = 0; i < ovs->n_bridges; i++) {
- if (!strcmp(br_name, ovs->bridges[i]->name)) {
- return ovs->bridges[i];
- }
- }
-
- return NULL;
-}
-
-static int
-execute_appctl_command(const char *unixctl_command, char **output)
-{
- char *stdout_log, *stderr_log;
- int error, status;
- char *argv[5];
-
- argv[0] = "/bin/sh";
- argv[1] = "-c";
- argv[2] = xasprintf(appctl_command, unixctl_command);
- argv[3] = NULL;
-
- /* Run process and log status. */
- error = process_run_capture(argv, &stdout_log, &stderr_log, &status);
- if (error) {
- VLOG_ERR("failed to execute %s command via ovs-appctl: %s",
- unixctl_command, strerror(error));
- } else if (status) {
- char *msg = process_status_msg(status);
- VLOG_ERR("ovs-appctl exited with error (%s)", msg);
- free(msg);
- error = ECHILD;
- }
-
- /* Deal with stdout_log. */
- if (output) {
- *output = stdout_log;
- } else {
- free(stdout_log);
- }
-
- /* Deal with stderr_log */
- if (stderr_log && *stderr_log) {
- VLOG_INFO("ovs-appctl wrote to stderr:\n%s", stderr_log);
- }
- free(stderr_log);
-
- free(argv[2]);
-
- return error;
-}
-
-static void
-do_get_bridge_parts(const struct ovsrec_bridge *br, struct svec *parts,
- int vlan, bool break_down_bonds)
-{
- struct svec ports;
- size_t i, j;
-
- svec_init(&ports);
- for (i = 0; i < br->n_ports; i++) {
- const struct ovsrec_port *port = br->ports[i];
-
- svec_add(&ports, port->name);
- if (vlan >= 0) {
- int port_vlan = port->n_tag ? *port->tag : 0;
- if (vlan != port_vlan) {
- continue;
- }
- }
- if (break_down_bonds) {
- for (j = 0; j < port->n_interfaces; j++) {
- const struct ovsrec_interface *iface = port->interfaces[j];
- svec_add(parts, iface->name);
- }
- } else {
- svec_add(parts, port->name);
- }
- }
- svec_destroy(&ports);
-}
-
-/* Add all the interfaces for 'bridge' to 'ifaces', breaking bonded interfaces
- * down into their constituent parts.
- *
- * If 'vlan' < 0, all interfaces on 'bridge' are reported. If 'vlan' == 0,
- * then only interfaces for trunk ports or ports with implicit VLAN 0 are
- * reported. If 'vlan' > 0, only interfaces with implicit VLAN 'vlan' are
- * reported. */
-static void
-get_bridge_ifaces(const struct ovsrec_bridge *br, struct svec *ifaces,
- int vlan)
-{
- do_get_bridge_parts(br, ifaces, vlan, true);
-}
-
-/* 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);
-}
-
-#if 0
-/* Go through the configuration file and remove any ports that no longer
- * exist associated with a bridge. */
-static void
-prune_ports(void)
-{
- int i, j;
- struct svec bridges, delete;
-
- if (cfg_lock(NULL, 0)) {
- /* Couldn't lock config file. */
- return;
- }
-
- svec_init(&bridges);
- svec_init(&delete);
- cfg_get_subsections(&bridges, "bridge");
- for (i=0; i<bridges.n; i++) {
- const char *br_name = bridges.names[i];
- struct svec ifaces;
-
- /* Check that each bridge interface exists. */
- svec_init(&ifaces);
- get_bridge_ifaces(br_name, &ifaces, -1);
- for (j = 0; j < ifaces.n; j++) {
- const char *iface_name = ifaces.names[j];
-
- /* The local port and internal ports are created and destroyed by
- * ovs-vswitchd itself, so don't bother checking for them at all.
- * In practice, they might not exist if ovs-vswitchd hasn't
- * finished reloading since the configuration file was updated. */
- if (!strcmp(iface_name, br_name)
- || cfg_get_bool(0, "iface.%s.internal", iface_name)) {
- continue;
- }
-
- if (!netdev_exists(iface_name)) {
- VLOG_INFO_RL(&rl, "removing dead interface %s from %s",
- iface_name, br_name);
- svec_add(&delete, iface_name);
- }
- }
- svec_destroy(&ifaces);
- }
- svec_destroy(&bridges);
-
- if (delete.n) {
- size_t i;
-
- for (i = 0; i < delete.n; i++) {
- cfg_del_match("bridge.*.port=%s", delete.names[i]);
- cfg_del_match("bonding.*.slave=%s", delete.names[i]);
- }
- reload_config();
- cfg_unlock();
- } else {
- cfg_unlock();
- }
- svec_destroy(&delete);
-}
-#endif
-
-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 int
-add_bridge(const struct ovsrec_open_vswitch *ovs, const char *br_name)
-{
- struct ovsrec_bridge *br;
- struct ovsrec_port *port;
- struct ovsrec_interface *iface;
-
- if (find_bridge(ovs, br_name)) {
- VLOG_WARN("addbr %s: bridge %s exists", br_name, br_name);
- return EEXIST;
- } else if (netdev_exists(br_name)) {
- size_t i;
-
- for (i = 0; i < ovs->n_bridges; i++) {
- size_t j;
- struct ovsrec_bridge *br_cfg = ovs->bridges[i];
-
- for (j = 0; j < br_cfg->n_ports; j++) {
- if (port_is_fake_bridge(br_cfg->ports[j])) {
- VLOG_WARN("addbr %s: %s exists as a fake bridge",
- br_name, br_name);
- return 0;
- }
- }
- }
-
- VLOG_WARN("addbr %s: cannot create bridge %s because a network "
- "device named %s already exists",
- br_name, br_name, br_name);
- return EEXIST;
- }
-
- iface = ovsrec_interface_insert(txn_from_openvswitch(ovs));
- ovsrec_interface_set_name(iface, br_name);
-
- port = ovsrec_port_insert(txn_from_openvswitch(ovs));
- ovsrec_port_set_name(port, br_name);
- ovsrec_port_set_interfaces(port, &iface, 1);
-
- br = ovsrec_bridge_insert(txn_from_openvswitch(ovs));
- ovsrec_bridge_set_name(br, br_name);
- ovsrec_bridge_set_ports(br, &port, 1);
-
- ovs_insert_bridge(ovs, br);
-
- VLOG_INFO("addbr %s: success", br_name);
-
- return 0;
-}
-
-static void
-add_port(const struct ovsrec_open_vswitch *ovs,
- const struct ovsrec_bridge *br, const char *port_name)
-{
- struct ovsrec_interface *iface;
- struct ovsrec_port *port;
- struct ovsrec_port **ports;
- size_t i;
-
- /* xxx Check conflicts? */
- iface = ovsrec_interface_insert(txn_from_openvswitch(ovs));
- ovsrec_interface_set_name(iface, port_name);
-
- port = ovsrec_port_insert(txn_from_openvswitch(ovs));
- ovsrec_port_set_name(port, port_name);
- ovsrec_port_set_interfaces(port, &iface, 1);
-
- ports = xmalloc(sizeof *br->ports * (br->n_ports + 1));
- for (i = 0; i < br->n_ports; i++) {
- ports[i] = br->ports[i];
- }
- ports[br->n_ports] = port;
- ovsrec_bridge_set_ports(br, ports, br->n_ports + 1);
- free(ports);
-}
-
-static void
-del_port(const struct ovsrec_bridge *br, const char *port_name)
-{
- size_t i, j;
- struct ovsrec_port *port_rec = NULL;
-
- for (i = 0; i < br->n_ports; i++) {
- struct ovsrec_port *port = br->ports[i];
- if (!strcmp(port_name, port->name)) {
- port_rec = port;
- }
- for (j = 0; j < port->n_interfaces; j++) {
- struct ovsrec_interface *iface = port->interfaces[j];
- if (!strcmp(port_name, iface->name)) {
- ovsrec_interface_delete(iface);
- }
- }
- }
-
- /* xxx Probably can move this into the "for" loop. */
- if (port_rec) {
- struct ovsrec_port **ports;
- size_t n;
-
- ports = xmalloc(sizeof *br->ports * br->n_ports);
- for (i = n = 0; i < br->n_ports; i++) {
- if (br->ports[i] != port_rec) {
- ports[n++] = br->ports[i];
- }
- }
- ovsrec_bridge_set_ports(br, ports, n);
- free(ports);
- }
-}
-
-static int
-del_bridge(const struct ovsrec_open_vswitch *ovs, const char *br_name)
-{
- struct ovsrec_bridge *br = find_bridge(ovs, br_name);
- struct ovsrec_bridge **bridges;
- size_t i, n;
-
- if (!br) {
- VLOG_WARN("delbr %s: no bridge named %s", br_name, br_name);
- return ENXIO;
- }
-
- del_port(br, br_name);
-
- ovsrec_bridge_delete(br);
-
- bridges = xmalloc(sizeof *ovs->bridges * ovs->n_bridges);
- for (i = n = 0; i < ovs->n_bridges; i++) {
- if (ovs->bridges[i] != br) {
- bridges[n++] = ovs->bridges[i];
- }
- }
- ovsrec_open_vswitch_set_bridges(ovs, bridges, n);
- free(bridges);
-
- VLOG_INFO("delbr %s: success", br_name);
-
- return 0;
-}
-