ovsdb-server: Free memory on exit.
[openvswitch] / vswitchd / ovs-brcompatd.c
index b7627e01ef1f59f5982c765b22ab67d5fe6a8423..585ab2c70576f3f080ddf84f890e0ebde5fc3fb9 100644 (file)
@@ -1,4 +1,4 @@
-/* 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.
@@ -39,7 +39,6 @@
 #include "dirs.h"
 #include "dynamic-string.h"
 #include "fatal-signal.h"
-#include "fault.h"
 #include "leak-checker.h"
 #include "netdev.h"
 #include "netlink.h"
@@ -75,10 +74,6 @@ static void usage(void) NO_RETURN;
 
 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;
@@ -760,7 +755,7 @@ handle_fdb_query_cmd(const struct ovsrec_open_vswitch *ovs,
         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++;
@@ -983,6 +978,14 @@ brc_recv_update(const struct ovsrec_open_vswitch *ovs)
         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);
@@ -1023,10 +1026,9 @@ error:
     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;
 
@@ -1068,27 +1070,21 @@ rtnl_recv_update(void)
                 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
@@ -1135,12 +1131,10 @@ rtnl_recv_update(void)
                           "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[])
@@ -1148,11 +1142,10 @@ 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);
@@ -1163,11 +1156,11 @@ main(int argc, char *argv[])
     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)) {
@@ -1181,45 +1174,33 @@ main(int argc, char *argv[])
         }
     }
 
+    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.
@@ -1227,14 +1208,15 @@ main(int argc, char *argv[])
          *   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);
@@ -1253,6 +1235,7 @@ main(int argc, char *argv[])
             ovs_fatal(0, "transaction aborted");
         
         case TXN_SUCCESS:
+        case TXN_UNCHANGED:
             break;
         
         case TXN_TRY_AGAIN:
@@ -1305,7 +1288,6 @@ static const char *
 parse_options(int argc, char *argv[])
 {
     enum {
-        OPT_LOCK_TIMEOUT = UCHAR_MAX + 1,
         OPT_PRUNE_TIMEOUT,
         OPT_APPCTL_COMMAND,
         VLOG_OPTION_ENUMS,
@@ -1314,7 +1296,6 @@ parse_options(int argc, char *argv[])
     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,
@@ -1342,10 +1323,6 @@ parse_options(int argc, char *argv[])
             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;
@@ -1390,7 +1367,6 @@ usage(void)
     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();