-/* 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.
#include "dirs.h"
#include "dynamic-string.h"
#include "fatal-signal.h"
-#include "fault.h"
#include "leak-checker.h"
#include "netdev.h"
#include "netlink.h"
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 60);
-/* Maximum number of milliseconds to wait for the config file to be
- * unlocked. If set to zero, no waiting will occur. */
-static int lock_timeout = 500;
-
/* Maximum number of milliseconds to wait before pruning port entries that
* no longer exist. If set to zero, ports are never pruned. */
static int prune_timeout = 5000;
struct mac *mac = &local_macs[n_local_macs];
struct netdev *netdev;
- error = netdev_open(iface_name, NETDEV_ETH_TYPE_NONE, &netdev);
+ error = netdev_open_default(iface_name, &netdev);
if (netdev) {
if (!netdev_get_etheraddr(netdev, mac->addr)) {
n_local_macs++;
goto error;
}
+ /* Just drop the request on the floor if a valid configuration
+ * doesn't exist. We don't immediately do this check, because we
+ * want to drain pending netlink messages. */
+ if (!ovs) {
+ VLOG_WARN_RL(&rl, "could not find valid configuration to update");
+ goto error;
+ }
+
switch (genlmsghdr->cmd) {
case BRC_GENL_C_DP_ADD:
handle_bridge_cmd(ovs, buffer, true);
return;
}
-#if 0
/* Check for interface configuration changes announced through RTNL. */
static void
-rtnl_recv_update(void)
+rtnl_recv_update(const struct ovsrec_open_vswitch *ovs)
{
struct ofpbuf *buf;
return;
}
- if (cfg_lock(NULL, lock_timeout)) {
- /* Couldn't lock config file. */
- /* xxx this should try again and print error msg. */
- ofpbuf_delete(buf);
- return;
- }
-
if (!netdev_exists(port_name)) {
/* Network device is really gone. */
- struct svec ports;
+ struct ovsrec_bridge *br = find_bridge(ovs, br_name);
VLOG_INFO("network device %s destroyed, "
"removing from bridge %s", port_name, br_name);
- svec_init(&ports);
- cfg_get_all_keys(&ports, "bridge.%s.port", br_name);
- svec_sort(&ports);
- if (svec_contains(&ports, port_name)) {
- del_port(br_name, port_name);
+ if (!br) {
+ VLOG_WARN("no bridge named %s from which to remove %s",
+ br_name, port_name);
+ ofpbuf_delete(buf);
+ return;
}
- svec_destroy(&ports);
+
+ del_port(br, port_name);
} else {
/* A network device by that name exists even though the kernel
* told us it had disappeared. Probably, what happened was
"a device by that name exists (XS Tools 5.0.0?)",
port_name);
}
- cfg_unlock();
}
ofpbuf_delete(buf);
}
}
-#endif
int
main(int argc, char *argv[])
struct unixctl_server *unixctl;
const char *remote;
struct ovsdb_idl *idl;
- unsigned int idl_seqno;
int retval;
+ proctitle_init(argc, argv);
set_program_name(argv[0]);
- register_fault_handlers();
time_init();
vlog_init();
vlog_set_levels(VLM_ANY_MODULE, VLF_CONSOLE, VLL_WARN);
process_init();
die_if_already_running();
- daemonize();
+ daemonize_start();
retval = unixctl_server_create(NULL, &unixctl);
if (retval) {
- ovs_fatal(retval, "could not listen for vlog connections");
+ exit(EXIT_FAILURE);
}
if (brc_open(&brc_sock)) {
}
}
+ daemonize_complete();
+
idl = ovsdb_idl_create(remote, &ovsrec_idl_class);
- idl_seqno = ovsdb_idl_get_seqno(idl);
for (;;) {
const struct ovsrec_open_vswitch *ovs;
struct ovsdb_idl_txn *txn;
- int status;
- unsigned int new_idl_seqno;
+ enum ovsdb_idl_txn_status status;
ovsdb_idl_run(idl);
- /* xxx Complete hack to get around bad ovs! */
- new_idl_seqno = ovsdb_idl_get_seqno(idl);
- if (new_idl_seqno == idl_seqno) {
- ovsdb_idl_wait(idl);
- poll_block();
- printf("xxx trying again...\n");
- idl_seqno = new_idl_seqno;
- continue;
- }
-
- ovs = ovsrec_open_vswitch_first(idl);
- if (!ovs) {
- /* XXX it would be more user-friendly to create a record ourselves
- * (while verifying that the table is empty before doing so). */
- ovs_fatal(0, "%s: database does not contain any Open vSwitch "
- "configuration", remote);
- }
-
txn = ovsdb_idl_txn_create(idl);
unixctl_server_run(unixctl);
+ ovs = ovsrec_open_vswitch_first(idl);
brc_recv_update(ovs);
+
+ if (!ovs && ovsdb_idl_has_ever_connected(idl)) {
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+ VLOG_WARN_RL(&rl, "%s: database does not contain any Open vSwitch "
+ "configuration", remote);
+ }
netdev_run();
-#if 0
/* If 'prune_timeout' is non-zero, we actively prune from the
- * config file any 'bridge.<br_name>.port' entries that are no
- * longer valid. We use two methods:
+ * configuration of port entries that are no longer valid. We
+ * use two methods:
*
* 1) The kernel explicitly notifies us of removed ports
* through the RTNL messages.
* 2) We periodically check all ports associated with bridges
* to see if they no longer exist.
*/
- if (prune_timeout) {
- rtnl_recv_update();
+ if (ovs && prune_timeout) {
+ rtnl_recv_update(ovs);
+#if 0
prune_ports();
+#endif
nl_sock_wait(rtnl_sock, POLLIN);
poll_timer_wait(prune_timeout);
}
-#endif
while ((status = ovsdb_idl_txn_commit(txn)) == TXN_INCOMPLETE) {
ovsdb_idl_run(idl);
ovs_fatal(0, "transaction aborted");
case TXN_SUCCESS:
+ case TXN_UNCHANGED:
break;
case TXN_TRY_AGAIN:
parse_options(int argc, char *argv[])
{
enum {
- OPT_LOCK_TIMEOUT = UCHAR_MAX + 1,
OPT_PRUNE_TIMEOUT,
OPT_APPCTL_COMMAND,
VLOG_OPTION_ENUMS,
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
- {"lock-timeout", required_argument, 0, OPT_LOCK_TIMEOUT},
{"prune-timeout", required_argument, 0, OPT_PRUNE_TIMEOUT},
{"appctl-command", required_argument, 0, OPT_APPCTL_COMMAND},
DAEMON_LONG_OPTIONS,
OVS_PRINT_VERSION(0, 0);
exit(EXIT_SUCCESS);
- case OPT_LOCK_TIMEOUT:
- lock_timeout = atoi(optarg);
- break;
-
case OPT_PRUNE_TIMEOUT:
prune_timeout = atoi(optarg) * 1000;
break;
printf("\nConfiguration options:\n"
" --appctl-command=COMMAND shell command to run ovs-appctl\n"
" --prune-timeout=SECS wait at most SECS before pruning ports\n"
- " --lock-timeout=MSECS wait at most MSECS for CONFIG to unlock\n"
);
daemon_usage();
vlog_usage();