Until now, the ovs-vswitchd main loop has managed the connection to the
database. This worked adequately until now, but upcoming patches will tie
the bridge code more tightly to the database, which means that the bridge
needs more control over interaction with the database connection and thus
that it is better for the bridge to handle that connection itself. This
commit makes the latter change, moving the database interaction from the
ovs-vswitchd main loop into bridge.c.
/* List of all bridges. */
static struct list all_bridges = LIST_INITIALIZER(&all_bridges);
/* List of all bridges. */
static struct list all_bridges = LIST_INITIALIZER(&all_bridges);
+/* OVSDB IDL used to obtain configuration. */
+static struct ovsdb_idl *idl;
+
static struct bridge *bridge_create(const struct ovsrec_bridge *br_cfg);
static void bridge_destroy(struct bridge *);
static struct bridge *bridge_lookup(const char *name);
static struct bridge *bridge_create(const struct ovsrec_bridge *br_cfg);
static void bridge_destroy(struct bridge *);
static struct bridge *bridge_lookup(const char *name);
\f
/* Public functions. */
\f
/* Public functions. */
+/* Initializes the bridge module, configuring it to obtain its configuration
+ * from an OVSDB server accessed over 'remote', which should be a string in a
+ * form acceptable to ovsdb_idl_create(). */
-bridge_init(const struct ovsrec_open_vswitch *cfg)
+bridge_init(const char *remote)
+{
+ /* Create connection to database. */
+ idl = ovsdb_idl_create(remote, &ovsrec_idl_class);
+
+ /* Register unixctl commands. */
+ unixctl_command_register("fdb/show", bridge_unixctl_fdb_show, NULL);
+ unixctl_command_register("bridge/dump-flows", bridge_unixctl_dump_flows,
+ NULL);
+ bond_init();
+}
+
+/* Performs configuration that is only necessary once at ovs-vswitchd startup,
+ * but for which the ovs-vswitchd configuration 'cfg' is required. */
+static void
+bridge_configure_once(const struct ovsrec_open_vswitch *cfg)
+ static bool already_configured_once;
struct svec bridge_names;
struct svec dpif_names, dpif_types;
size_t i;
struct svec bridge_names;
struct svec dpif_names, dpif_types;
size_t i;
- unixctl_command_register("fdb/show", bridge_unixctl_fdb_show, NULL);
+ /* Only do this once per ovs-vswitchd run. */
+ if (already_configured_once) {
+ return;
+ }
+ already_configured_once = true;
+ /* Get all the configured bridges' names from 'cfg' into 'bridge_names'. */
svec_init(&bridge_names);
for (i = 0; i < cfg->n_bridges; i++) {
svec_add(&bridge_names, cfg->bridges[i]->name);
}
svec_sort(&bridge_names);
svec_init(&bridge_names);
for (i = 0; i < cfg->n_bridges; i++) {
svec_add(&bridge_names, cfg->bridges[i]->name);
}
svec_sort(&bridge_names);
+ /* Iterate over all system dpifs and delete any of them that do not appear
+ * in 'cfg'. */
svec_init(&dpif_names);
svec_init(&dpif_types);
dp_enumerate_types(&dpif_types);
svec_init(&dpif_names);
svec_init(&dpif_types);
dp_enumerate_types(&dpif_types);
dp_enumerate_names(dpif_types.names[i], &dpif_names);
dp_enumerate_names(dpif_types.names[i], &dpif_names);
for (j = 0; j < dpif_names.n; j++) {
retval = dpif_open(dpif_names.names[j], dpif_types.names[i], &dpif);
if (!retval) {
struct svec all_names;
size_t k;
for (j = 0; j < dpif_names.n; j++) {
retval = dpif_open(dpif_names.names[j], dpif_types.names[i], &dpif);
if (!retval) {
struct svec all_names;
size_t k;
+ /* ...check whether any of its names is in 'bridge_names'. */
svec_init(&all_names);
dpif_get_all_names(dpif, &all_names);
for (k = 0; k < all_names.n; k++) {
svec_init(&all_names);
dpif_get_all_names(dpif, &all_names);
for (k = 0; k < all_names.n; k++) {
+
+ /* No. Delete the dpif. */
found:
svec_destroy(&all_names);
dpif_close(dpif);
found:
svec_destroy(&all_names);
dpif_close(dpif);
svec_destroy(&bridge_names);
svec_destroy(&dpif_names);
svec_destroy(&dpif_types);
svec_destroy(&bridge_names);
svec_destroy(&dpif_names);
svec_destroy(&dpif_types);
-
- unixctl_command_register("bridge/dump-flows", bridge_unixctl_dump_flows,
- NULL);
-
- bond_init();
- bridge_reconfigure(cfg);
*n_managersp = n_managers;
}
*n_managersp = n_managers;
}
bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
{
bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
{
- struct ovsdb_idl_txn *txn;
struct shash old_br, new_br;
struct shash_node *node;
struct bridge *br, *next;
struct shash old_br, new_br;
struct shash_node *node;
struct bridge *br, *next;
COVERAGE_INC(bridge_reconfigure);
COVERAGE_INC(bridge_reconfigure);
- txn = ovsdb_idl_txn_create(ovs_cfg->header_.table->idl);
-
collect_managers(ovs_cfg, &managers, &n_managers);
/* Collect old and new bridges. */
collect_managers(ovs_cfg, &managers, &n_managers);
/* Collect old and new bridges. */
iterate_and_prune_ifaces(br, set_iface_properties, NULL);
}
iterate_and_prune_ifaces(br, set_iface_properties, NULL);
}
- ovsrec_open_vswitch_set_cur_cfg(ovs_cfg, ovs_cfg->next_cfg);
-
- ovsdb_idl_txn_commit(txn);
- ovsdb_idl_txn_destroy(txn); /* XXX */
-
return eth_addr_to_uint64(hash);
}
return eth_addr_to_uint64(hash);
}
- struct bridge *br, *next;
- int retval;
+ bool datapath_destroyed;
+ struct bridge *br;
- retval = 0;
- LIST_FOR_EACH_SAFE (br, next, struct bridge, node, &all_bridges) {
+ /* Let each bridge do the work that it needs to do. */
+ datapath_destroyed = false;
+ LIST_FOR_EACH (br, struct bridge, node, &all_bridges) {
int error = bridge_run_one(br);
if (error) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
VLOG_ERR_RL(&rl, "bridge %s: datapath was destroyed externally, "
"forcing reconfiguration", br->name);
int error = bridge_run_one(br);
if (error) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
VLOG_ERR_RL(&rl, "bridge %s: datapath was destroyed externally, "
"forcing reconfiguration", br->name);
- if (!retval) {
- retval = error;
- }
+ datapath_destroyed = true;
+ }
+ }
+
+ /* (Re)configure if necessary. */
+ if (ovsdb_idl_run(idl) || datapath_destroyed) {
+ const struct ovsrec_open_vswitch *cfg = ovsrec_open_vswitch_first(idl);
+ if (cfg) {
+ struct ovsdb_idl_txn *txn = ovsdb_idl_txn_create(idl);
+
+ bridge_configure_once(cfg);
+ bridge_reconfigure(cfg);
+
+ ovsrec_open_vswitch_set_cur_cfg(cfg, cfg->next_cfg);
+ ovsdb_idl_txn_commit(txn);
+ ovsdb_idl_txn_destroy(txn); /* XXX */
mac_learning_wait(br->ml);
bond_wait(br);
}
mac_learning_wait(br->ml);
bond_wait(br);
}
}
/* Forces 'br' to revalidate all of its flows. This is appropriate when 'br''s
}
/* Forces 'br' to revalidate all of its flows. This is appropriate when 'br''s
-/* Copyright (c) 2008, 2009 Nicira Networks
+/* Copyright (c) 2008, 2009, 2010 Nicira Networks
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <stdbool.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdint.h>
-struct ovsrec_open_vswitch;
-void bridge_init(const struct ovsrec_open_vswitch *);
-void bridge_reconfigure(const struct ovsrec_open_vswitch *);
-int bridge_run(void);
+void bridge_init(const char *remote);
+void bridge_run(void);
void bridge_wait(void);
#endif /* bridge.h */
void bridge_wait(void);
#endif /* bridge.h */
{
struct unixctl_server *unixctl;
struct signal *sighup;
{
struct unixctl_server *unixctl;
struct signal *sighup;
int retval;
proctitle_init(argc, argv);
int retval;
proctitle_init(argc, argv);
- idl = ovsdb_idl_create(remote, &ovsrec_idl_class);
-
- inited = false;
exiting = false;
while (!exiting) {
exiting = false;
while (!exiting) {
- bool need_reconfigure;
-
if (signal_poll(sighup)) {
vlog_reopen_log_file();
}
if (signal_poll(sighup)) {
vlog_reopen_log_file();
}
-
- need_reconfigure = false;
- if (inited && bridge_run()) {
- need_reconfigure = true;
- }
- if (ovsdb_idl_run(idl)) {
- need_reconfigure = true;
- }
-
- if (need_reconfigure) {
- const struct ovsrec_open_vswitch *cfg;
-
- cfg = ovsrec_open_vswitch_first(idl);
- if (cfg) {
- if (inited) {
- bridge_reconfigure(cfg);
- } else {
- bridge_init(cfg);
- inited = true;
- }
- }
- }
unixctl_server_run(unixctl);
dp_run();
netdev_run();
signal_wait(sighup);
unixctl_server_run(unixctl);
dp_run();
netdev_run();
signal_wait(sighup);
- if (inited) {
- bridge_wait();
- }
- ovsdb_idl_wait(idl);
unixctl_server_wait(unixctl);
dp_wait();
netdev_wait();
unixctl_server_wait(unixctl);
dp_wait();
netdev_wait();