daemon: Integrate checking for an existing pidfile into daemonize_start().
[sliver-openvswitch.git] / vswitchd / ovs-brcompatd.c
index a182b49..9d5cdfb 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2009, 2010 Nicira Networks
+/* Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -43,6 +43,7 @@
 #include "leak-checker.h"
 #include "netdev.h"
 #include "netlink.h"
+#include "netlink-socket.h"
 #include "ofpbuf.h"
 #include "openvswitch/brcompat-netlink.h"
 #include "ovsdb-idl.h"
 #include "poll-loop.h"
 #include "process.h"
 #include "signals.h"
-#include "svec.h"
+#include "sset.h"
 #include "timeval.h"
 #include "unixctl.h"
 #include "util.h"
+#include "vlog.h"
 #include "vswitchd/vswitch-idl.h"
 
-#include "vlog.h"
-#define THIS_MODULE VLM_brcompatd
+VLOG_DEFINE_THIS_MODULE(brcompatd);
 
 
 /* xxx Just hangs if datapath is rmmod/insmod.  Learn to reconnect? */
@@ -75,7 +76,7 @@ static void usage(void) NO_RETURN;
 
 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 60);
 
-/* Maximum number of milliseconds to wait before pruning port entries that 
+/* 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;
 
@@ -110,12 +111,12 @@ lookup_brc_multicast_group(int *multicast_group)
     struct nlattr *attrs[ARRAY_SIZE(brc_multicast_policy)];
     int retval;
 
-    retval = nl_sock_create(NETLINK_GENERIC, 0, 0, 0, &sock);
+    retval = nl_sock_create(NETLINK_GENERIC, &sock);
     if (retval) {
         return retval;
     }
     ofpbuf_init(&request, 0);
-    nl_msg_put_genlmsghdr(&request, sock, 0, brc_family,
+    nl_msg_put_genlmsghdr(&request, 0, brc_family,
             NLM_F_REQUEST, BRC_GENL_C_QUERY_MC, 1);
     retval = nl_sock_transact(sock, &request, &reply);
     ofpbuf_uninit(&request);
@@ -155,12 +156,17 @@ brc_open(struct nl_sock **sock)
         return retval;
     }
 
-    retval = nl_sock_create(NETLINK_GENERIC, multicast_group, 0, 0, sock);
+    retval = nl_sock_create(NETLINK_GENERIC, sock);
     if (retval) {
         return retval;
     }
 
-    return 0;
+    retval = nl_sock_join_mcgroup(*sock, multicast_group);
+    if (retval) {
+        nl_sock_destroy(*sock);
+        *sock = NULL;
+    }
+    return retval;
 }
 
 static const struct nl_policy brc_dp_policy[] = {
@@ -224,17 +230,14 @@ execute_appctl_command(const char *unixctl_command, char **output)
 }
 
 static void
-do_get_bridge_parts(const struct ovsrec_bridge *br, struct svec *parts, 
+do_get_bridge_parts(const struct ovsrec_bridge *br, struct sset *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) {
@@ -244,13 +247,12 @@ do_get_bridge_parts(const struct ovsrec_bridge *br, struct svec *parts,
         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);
+                sset_add(parts, iface->name);
             }
         } else {
-            svec_add(parts, port->name);
+            sset_add(parts, port->name);
         }
     }
-    svec_destroy(&ports);
 }
 
 /* Add all the interfaces for 'bridge' to 'ifaces', breaking bonded interfaces
@@ -261,7 +263,7 @@ do_get_bridge_parts(const struct ovsrec_bridge *br, struct svec *parts,
  * 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, 
+get_bridge_ifaces(const struct ovsrec_bridge *br, struct sset *ifaces,
                   int vlan)
 {
     do_get_bridge_parts(br, ifaces, vlan, true);
@@ -274,7 +276,7 @@ get_bridge_ifaces(const struct ovsrec_bridge *br, struct svec *ifaces,
  * 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, 
+get_bridge_ports(const struct ovsrec_bridge *br, struct sset *ports,
                  int vlan)
 {
     do_get_bridge_parts(br, ports, vlan, false);
@@ -299,7 +301,7 @@ ovs_insert_bridge(const struct ovsrec_open_vswitch *ovs,
                   struct ovsrec_bridge *bridge)
 {
     struct ovsrec_bridge **bridges;
-    size_t i;     
+    size_t i;
 
     bridges = xmalloc(sizeof *ovs->bridges * (ovs->n_bridges + 1));
     for (i = 0; i < ovs->n_bridges; i++) {
@@ -308,7 +310,7 @@ ovs_insert_bridge(const struct ovsrec_open_vswitch *ovs,
     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)
@@ -437,18 +439,18 @@ add_bridge(struct ovsdb_idl *idl, const struct ovsrec_open_vswitch *ovs,
     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);
 
     return commit_txn(txn, true);
 }
 
 static void
-add_port(const struct ovsrec_open_vswitch *ovs, 
+add_port(const struct ovsrec_open_vswitch *ovs,
          const struct ovsrec_bridge *br, const char *port_name)
 {
     struct ovsrec_interface *iface;
@@ -491,14 +493,6 @@ del_port(const struct ovsrec_bridge *br, const struct ovsrec_port *port)
     }
     ovsrec_bridge_set_ports(br, ports, n);
     free(ports);
-
-    /* Delete all of the port's interfaces. */
-    for (i = 0; i < port->n_interfaces; i++) {
-        ovsrec_interface_delete(port->interfaces[i]);
-    }
-
-    /* Delete the port itself. */
-    ovsrec_port_delete(port);
 }
 
 /* Delete 'iface' from 'port' (which must be within 'br').  If 'iface' was
@@ -524,7 +518,6 @@ del_interface(const struct ovsrec_bridge *br,
         }
         ovsrec_port_set_interfaces(port, ifaces, n);
         free(ifaces);
-        ovsrec_interface_delete(iface);
     }
 }
 
@@ -585,24 +578,6 @@ del_bridge(struct ovsdb_idl *idl,
 
     ovsdb_idl_txn_add_comment(txn, "ovs-brcompatd: delbr %s", br_name);
 
-    /* Delete everything that the bridge points to, then delete the bridge
-     * itself. */
-    while (br->n_ports > 0) {
-        del_port(br, br->ports[0]);
-    }
-    for (i = 0; i < br->n_mirrors; i++) {
-        ovsrec_mirror_delete(br->mirrors[i]);
-    }
-    if (br->netflow) {
-        ovsrec_netflow_delete(br->netflow);
-    }
-    if (br->sflow) {
-        ovsrec_sflow_delete(br->sflow);
-    }
-    for (i = 0; i < br->n_controller; i++) {
-        ovsrec_controller_delete(br->controller[i]);
-    }
-
     /* Remove 'br' from the vswitch's list of bridges. */
     bridges = xmalloc(sizeof *ovs->bridges * ovs->n_bridges);
     for (i = n = 0; i < ovs->n_bridges; i++) {
@@ -613,9 +588,6 @@ del_bridge(struct ovsdb_idl *idl,
     ovsrec_open_vswitch_set_bridges(ovs, bridges, n);
     free(bridges);
 
-    /* Delete the bridge itself. */
-    ovsrec_bridge_delete(br);
-
     return commit_txn(txn, true);
 }
 
@@ -663,7 +635,7 @@ static struct ofpbuf *
 compose_reply(uint32_t seq, int error)
 {
     struct ofpbuf *reply = ofpbuf_new(4096);
-    nl_msg_put_genlmsghdr(reply, brc_sock, 32, brc_family, NLM_F_REQUEST,
+    nl_msg_put_genlmsghdr(reply, 32, brc_family, NLM_F_REQUEST,
                           BRC_GENL_C_DP_RESULT, 1);
     ((struct nlmsghdr *) reply->data)->nlmsg_seq = seq;
     nl_msg_put_u32(reply, BRC_GENL_A_ERR_CODE, error);
@@ -692,7 +664,7 @@ send_simple_reply(uint32_t seq, int error)
 
 static int
 handle_bridge_cmd(struct ovsdb_idl *idl,
-                  const struct ovsrec_open_vswitch *ovs, 
+                  const struct ovsrec_open_vswitch *ovs,
                   struct ofpbuf *buffer, bool add)
 {
     const char *br_name;
@@ -841,9 +813,10 @@ handle_fdb_query_cmd(const struct ovsrec_open_vswitch *ovs,
     const char *linux_name;   /* Name used by brctl. */
     const struct ovsrec_bridge *ovs_bridge;  /* Bridge used by ovs-vswitchd. */
     int br_vlan;                /* VLAN tag. */
-    struct svec ifaces;
+    struct sset ifaces;
 
     struct ofpbuf query_data;
+    const char *iface_name;
     struct ofpbuf *reply;
     char *unixctl_command;
     uint64_t count, skip;
@@ -859,7 +832,7 @@ handle_fdb_query_cmd(const struct ovsrec_open_vswitch *ovs,
     }
 
     /* Figure out vswitchd bridge and VLAN. */
-    error = linux_bridge_to_ovs_bridge(ovs, linux_name, 
+    error = linux_bridge_to_ovs_bridge(ovs, linux_name,
                                        &ovs_bridge, &br_vlan);
     if (error) {
         send_simple_reply(seq, error);
@@ -877,12 +850,11 @@ handle_fdb_query_cmd(const struct ovsrec_open_vswitch *ovs,
 
     /* Fetch the MAC address for each interface on the bridge, so that we can
      * fill in the is_local field in the response. */
-    svec_init(&ifaces);
+    sset_init(&ifaces);
     get_bridge_ifaces(ovs_bridge, &ifaces, br_vlan);
-    local_macs = xmalloc(ifaces.n * sizeof *local_macs);
+    local_macs = xmalloc(sset_count(&ifaces) * sizeof *local_macs);
     n_local_macs = 0;
-    for (i = 0; i < ifaces.n; i++) {
-        const char *iface_name = ifaces.names[i];
+    SSET_FOR_EACH (iface_name, &ifaces) {
         struct mac *mac = &local_macs[n_local_macs];
         struct netdev *netdev;
 
@@ -894,7 +866,7 @@ handle_fdb_query_cmd(const struct ovsrec_open_vswitch *ovs,
             netdev_close(netdev);
         }
     }
-    svec_destroy(&ifaces);
+    sset_destroy(&ifaces);
 
     /* Parse the response from ovs-appctl and convert it to binary format to
      * pass back to the kernel. */
@@ -916,7 +888,7 @@ handle_fdb_query_cmd(const struct ovsrec_open_vswitch *ovs,
         if (sscanf(line, "%d %d "ETH_ADDR_SCAN_FMT" %d",
                    &port, &vlan, ETH_ADDR_SCAN_ARGS(mac), &age)
             != 2 + ETH_ADDR_SCAN_COUNT + 1) {
-            struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
             VLOG_INFO_RL(&rl, "fdb/show output has invalid format: %s", line);
             continue;
         }
@@ -959,27 +931,23 @@ handle_fdb_query_cmd(const struct ovsrec_open_vswitch *ovs,
 
     /* Free memory. */
     ofpbuf_uninit(&query_data);
+    free(local_macs);
 
     return 0;
 }
 
 static void
-send_ifindex_reply(uint32_t seq, struct svec *ifaces)
+send_ifindex_reply(uint32_t seq, struct sset *ifaces)
 {
     struct ofpbuf *reply;
     const char *iface;
     size_t n_indices;
     int *indices;
-    size_t i;
-
-    /* Make sure that any given interface only occurs once.  This shouldn't
-     * happen, but who knows what people put into their configuration files. */
-    svec_sort_unique(ifaces);
 
     /* Convert 'ifaces' into ifindexes. */
     n_indices = 0;
-    indices = xmalloc(ifaces->n * sizeof *indices);
-    SVEC_FOR_EACH (i, iface, ifaces) {
+    indices = xmalloc(sset_count(ifaces) * sizeof *indices);
+    SSET_FOR_EACH (iface, ifaces) {
         int ifindex = if_nametoindex(iface);
         if (ifindex) {
             indices[n_indices++] = ifindex;
@@ -1000,7 +968,7 @@ static int
 handle_get_bridges_cmd(const struct ovsrec_open_vswitch *ovs,
                        struct ofpbuf *buffer)
 {
-    struct svec bridges;
+    struct sset bridges;
     size_t i, j;
 
     uint32_t seq;
@@ -1017,22 +985,22 @@ handle_get_bridges_cmd(const struct ovsrec_open_vswitch *ovs,
     }
 
     /* Get all the real bridges and all the fake ones. */
-    svec_init(&bridges);
+    sset_init(&bridges);
     for (i = 0; i < ovs->n_bridges; i++) {
         const struct ovsrec_bridge *br = ovs->bridges[i];
 
-        svec_add(&bridges, br->name);
+        sset_add(&bridges, br->name);
         for (j = 0; j < br->n_ports; j++) {
             const struct ovsrec_port *port = br->ports[j];
 
             if (port->fake_bridge) {
-                svec_add(&bridges, port->name);
+                sset_add(&bridges, port->name);
             }
         }
     }
 
     send_ifindex_reply(seq, &bridges);
-    svec_destroy(&bridges);
+    sset_destroy(&bridges);
 
     return 0;
 }
@@ -1047,7 +1015,7 @@ handle_get_ports_cmd(const struct ovsrec_open_vswitch *ovs,
     const struct ovsrec_bridge *ovs_bridge;
     int br_vlan;
 
-    struct svec ports;
+    struct sset ports;
 
     int error;
 
@@ -1057,43 +1025,61 @@ handle_get_ports_cmd(const struct ovsrec_open_vswitch *ovs,
         return error;
     }
 
-    error = linux_bridge_to_ovs_bridge(ovs, linux_name, 
+    error = linux_bridge_to_ovs_bridge(ovs, linux_name,
                                        &ovs_bridge, &br_vlan);
     if (error) {
         send_simple_reply(seq, error);
         return error;
     }
 
-    svec_init(&ports);
+    sset_init(&ports);
     get_bridge_ports(ovs_bridge, &ports, br_vlan);
-    svec_sort(&ports);
-    svec_del(&ports, linux_name);
+    sset_find_and_delete(&ports, linux_name);
     send_ifindex_reply(seq, &ports); /* XXX bonds won't show up */
-    svec_destroy(&ports);
+    sset_destroy(&ports);
 
     return 0;
 }
 
+static struct ofpbuf *
+brc_recv_update__(void)
+{
+    for (;;) {
+        struct ofpbuf *buffer;
+        int retval;
+
+        retval = nl_sock_recv(brc_sock, &buffer, false);
+        switch (retval) {
+        case 0:
+            if (nl_msg_nlmsgerr(buffer, NULL)
+                || nl_msg_nlmsghdr(buffer)->nlmsg_type == NLMSG_DONE) {
+                break;
+            }
+            return buffer;
+
+        case ENOBUFS:
+            break;
+
+        case EAGAIN:
+            return NULL;
+
+        default:
+            VLOG_WARN_RL(&rl, "brc_recv_update: %s", strerror(retval));
+            return NULL;
+        }
+        ofpbuf_delete(buffer);
+    }
+}
+
 static void
 brc_recv_update(struct ovsdb_idl *idl)
 {
-    int retval;
     struct ofpbuf *buffer;
     struct genlmsghdr *genlmsghdr;
     const struct ovsrec_open_vswitch *ovs;
 
-    buffer = NULL;
-    do {
-        ofpbuf_delete(buffer);
-        retval = nl_sock_recv(brc_sock, &buffer, false);
-    } while (retval == ENOBUFS
-            || (!retval
-                && (nl_msg_nlmsgerr(buffer, NULL)
-                    || nl_msg_nlmsghdr(buffer)->nlmsg_type == NLMSG_DONE)));
-    if (retval) {
-        if (retval != EAGAIN) {
-            VLOG_WARN_RL(&rl, "brc_recv_update: %s", strerror(retval));
-        }
+    buffer = brc_recv_update__();
+    if (!buffer) {
         return;
     }
 
@@ -1172,7 +1158,7 @@ rtnl_recv_update(struct ovsdb_idl *idl,
     } else if (error == ENOBUFS) {
         VLOG_WARN_RL(&rl, "network monitor socket overflowed");
     } else if (error) {
-        VLOG_WARN_RL(&rl, "error on network monitor socket: %s", 
+        VLOG_WARN_RL(&rl, "error on network monitor socket: %s",
                 strerror(error));
     } else {
         struct nlattr *attrs[ARRAY_SIZE(rtnlgrp_link_policy)];
@@ -1185,8 +1171,8 @@ rtnl_recv_update(struct ovsdb_idl *idl,
             VLOG_WARN_RL(&rl, "received bad rtnl message (no ifinfomsg)");
             ofpbuf_delete(buf);
             return;
-        } 
-    
+        }
+
         if (!nl_policy_parse(buf, NLMSG_HDRLEN + sizeof(struct ifinfomsg),
                              rtnlgrp_link_policy,
                              attrs, ARRAY_SIZE(rtnlgrp_link_policy))) {
@@ -1216,7 +1202,7 @@ rtnl_recv_update(struct ovsdb_idl *idl,
 
                 br = find_bridge(ovs, br_name);
                 if (!br) {
-                    VLOG_WARN("no bridge named %s from which to remove %s", 
+                    VLOG_WARN("no bridge named %s from which to remove %s",
                             br_name, port_name);
                     ofpbuf_delete(buf);
                     return;
@@ -1287,6 +1273,7 @@ rtnl_recv_update(struct ovsdb_idl *idl,
 int
 main(int argc, char *argv[])
 {
+    extern struct vlog_module VLM_reconnect;
     struct unixctl_server *unixctl;
     const char *remote;
     struct ovsdb_idl *idl;
@@ -1294,17 +1281,14 @@ main(int argc, char *argv[])
 
     proctitle_init(argc, argv);
     set_program_name(argv[0]);
-    time_init();
-    vlog_init();
-    vlog_set_levels(VLM_ANY_MODULE, VLF_CONSOLE, VLL_WARN);
-    vlog_set_levels(VLM_reconnect, VLF_ANY_FACILITY, VLL_WARN);
+    vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN);
+    vlog_set_levels(&VLM_reconnect, VLF_ANY_FACILITY, VLL_WARN);
 
     remote = parse_options(argc, argv);
     signal(SIGPIPE, SIG_IGN);
     process_init();
     ovsrec_init();
 
-    die_if_already_running();
     daemonize_start();
 
     retval = unixctl_server_create(NULL, &unixctl);
@@ -1313,19 +1297,29 @@ main(int argc, char *argv[])
     }
 
     if (brc_open(&brc_sock)) {
-        ovs_fatal(0, "could not open brcompat socket.  Check "
-                "\"brcompat\" kernel module.");
+        VLOG_FATAL("could not open brcompat socket.  Check "
+                   "\"brcompat\" kernel module.");
     }
 
     if (prune_timeout) {
-        if (nl_sock_create(NETLINK_ROUTE, RTNLGRP_LINK, 0, 0, &rtnl_sock)) {
-            ovs_fatal(0, "could not create rtnetlink socket");
+        int error;
+
+        error = nl_sock_create(NETLINK_ROUTE, &rtnl_sock);
+        if (error) {
+            VLOG_FATAL("could not create rtnetlink socket (%s)",
+                       strerror(error));
+        }
+
+        error = nl_sock_join_mcgroup(rtnl_sock, RTNLGRP_LINK);
+        if (error) {
+            VLOG_FATAL("could not join RTNLGRP_LINK multicast group (%s)",
+                       strerror(error));
         }
     }
 
     daemonize_complete();
 
-    idl = ovsdb_idl_create(remote, &ovsrec_idl_class);
+    idl = ovsdb_idl_create(remote, &ovsrec_idl_class, true);
 
     for (;;) {
         const struct ovsrec_open_vswitch *ovs;
@@ -1344,8 +1338,8 @@ main(int argc, char *argv[])
         netdev_run();
 
         /* If 'prune_timeout' is non-zero, we actively prune from the
-         * configuration of 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.
@@ -1385,11 +1379,11 @@ validate_appctl_command(void)
         } else if (p[1] == 's') {
             n++;
         } else {
-            ovs_fatal(0, "only '%%s' and '%%%%' allowed in --appctl-command");
+            VLOG_FATAL("only '%%s' and '%%%%' allowed in --appctl-command");
         }
     }
     if (n != 1) {
-        ovs_fatal(0, "'%%s' must appear exactly once in --appctl-command");
+        VLOG_FATAL("'%%s' must appear exactly once in --appctl-command");
     }
 }
 
@@ -1400,7 +1394,8 @@ parse_options(int argc, char *argv[])
         OPT_PRUNE_TIMEOUT,
         OPT_APPCTL_COMMAND,
         VLOG_OPTION_ENUMS,
-        LEAK_CHECKER_OPTION_ENUMS
+        LEAK_CHECKER_OPTION_ENUMS,
+        DAEMON_OPTION_ENUMS
     };
     static struct option long_options[] = {
         {"help",             no_argument, 0, 'h'},
@@ -1414,7 +1409,7 @@ parse_options(int argc, char *argv[])
     };
     char *short_options = long_options_to_short_options(long_options);
 
-    appctl_command = xasprintf("%s/ovs-appctl %%s", ovs_bindir);
+    appctl_command = xasprintf("%s/ovs-appctl %%s", ovs_bindir());
     for (;;) {
         int c;
 
@@ -1459,8 +1454,8 @@ parse_options(int argc, char *argv[])
     argv += optind;
 
     if (argc != 1) {
-        ovs_fatal(0, "database socket is non-option argument; "
-                "use --help for usage");
+        VLOG_FATAL("database socket is non-option argument; "
+                   "use --help for usage");
     }
 
     return argv[0];