[ovs-dev] [vlog 5/6] vlog: Make the vlog module catalog program-specific.

Ben Pfaff blp at nicira.com
Wed Jul 14 23:20:54 UTC 2010


Until now, the collection of vlog modules supported by a given OVS program
was not specific to that program.  That means that, for example, even
though ovs-dpctl does not have anything to do with jsonrpc, it still has
a vlog module for it.  This is confusing, at best.

This commit fixes the problem on some systems, in particular on ones that
use GCC and the GNU linker.  It uses the feature of the GNU linker
described in its manual as:

    If an orphaned section's name is representable as a C identifier then
    the linker will automatically see PROVIDE two symbols: __start_SECNAME
    and __end_SECNAME, where SECNAME is the name of the section.  These
    indicate the start address and end address of the orphaned section
    respectively.

Systems that don't support these features retain the earlier behavior.

This commit also fixes the annoyance that modifying lib/vlog-modules.def
causes all sources files that #include "vlog.h" to recompile.
---
 build-aux/check-vlog-modules |   66 +++++++++++++++++++
 configure.ac                 |    1 +
 extras/ezio/ezio-term.c      |    4 +-
 extras/ezio/ovs-switchui.c   |    6 +-
 extras/ezio/terminal.c       |    4 +-
 extras/ezio/tty.c            |    4 +-
 extras/ezio/vt-dummy.c       |    6 +-
 extras/ezio/vt-linux.c       |    6 +-
 lib/automake.mk              |   32 ++--------
 lib/backtrace.c              |    4 +-
 lib/coverage.c               |    4 +-
 lib/daemon.c                 |    4 +-
 lib/dhcp-client.c            |    4 +-
 lib/dhcp.c                   |    4 +-
 lib/dpif-linux.c             |    4 +-
 lib/dpif-netdev.c            |    4 +-
 lib/dpif.c                   |    4 +-
 lib/fatal-signal.c           |    4 +-
 lib/flow.c                   |    4 +-
 lib/jsonrpc.c                |    4 +-
 lib/leak-checker.c           |    4 +-
 lib/learning-switch.c        |    4 +-
 lib/lockfile.c               |    4 +-
 lib/mac-learning.c           |    4 +-
 lib/netdev-gre.c             |    4 +-
 lib/netdev-linux.c           |    4 +-
 lib/netdev-patch.c           |    4 +-
 lib/netdev-vport.c           |    4 +-
 lib/netdev.c                 |    4 +-
 lib/netlink.c                |    4 +-
 lib/ofp-util.c               |    4 +-
 lib/ovsdb-error.c            |    3 +-
 lib/ovsdb-idl.c              |    4 +-
 lib/pcap.c                   |    4 +-
 lib/poll-loop.c              |    4 +-
 lib/process.c                |    4 +-
 lib/rconn.c                  |    4 +-
 lib/reconnect.c              |    4 +-
 lib/rtnetlink.c              |    6 +-
 lib/socket-util.c            |    4 +-
 lib/stp.c                    |    6 +-
 lib/stream-fd.c              |    4 +-
 lib/stream-ssl.c             |    4 +-
 lib/stream-tcp.c             |    4 +-
 lib/stream-unix.c            |    4 +-
 lib/stream.c                 |    6 +-
 lib/stream.h                 |    2 +-
 lib/svec.c                   |    6 +-
 lib/timeval.c                |    4 +-
 lib/unixctl.c                |    4 +-
 lib/util.c                   |    4 +-
 lib/vconn-stream.c           |    4 +-
 lib/vconn.c                  |    4 +-
 lib/vlog.c                   |  144 ++++++++++++++++++++++-------------------
 lib/vlog.h                   |   80 +++++++++++++++--------
 m4/openvswitch.m4            |   75 ++++++++++++++++++++++
 ofproto/collectors.c         |    4 +-
 ofproto/discovery.c          |    4 +-
 ofproto/fail-open.c          |    4 +-
 ofproto/in-band.c            |    4 +-
 ofproto/netflow.c            |    6 +-
 ofproto/ofproto-sflow.c      |    4 +-
 ofproto/ofproto.c            |    4 +-
 ofproto/pktbuf.c             |    4 +-
 ofproto/status.c             |    4 +-
 ovsdb/file.c                 |    4 +-
 ovsdb/jsonrpc-server.c       |    4 +-
 ovsdb/log.c                  |    4 +-
 ovsdb/ovsdb-client.c         |    4 +-
 ovsdb/ovsdb-server.c         |    4 +-
 ovsdb/ovsdb-tool.c           |    4 +-
 tests/test-lockfile.c        |    3 +-
 tests/test-reconnect.c       |    3 +-
 tests/test-stp.c             |    2 +
 tests/test-vconn.c           |    4 +-
 utilities/nlmon.c            |    2 +-
 utilities/ovs-controller.c   |    4 +-
 utilities/ovs-discover.c     |    4 +-
 utilities/ovs-dpctl.c        |    4 +-
 utilities/ovs-ofctl.c        |    4 +-
 utilities/ovs-openflowd.c    |    4 +-
 utilities/ovs-vsctl.c        |   13 ++--
 vswitchd/bridge.c            |    4 +-
 vswitchd/ovs-brcompatd.c     |    9 ++-
 vswitchd/ovs-vswitchd.c      |    4 +-
 vswitchd/proc-net-compat.c   |    4 +-
 vswitchd/xenserver.c         |    6 +-
 87 files changed, 453 insertions(+), 292 deletions(-)
 create mode 100755 build-aux/check-vlog-modules

diff --git a/build-aux/check-vlog-modules b/build-aux/check-vlog-modules
new file mode 100755
index 0000000..d40c048
--- /dev/null
+++ b/build-aux/check-vlog-modules
@@ -0,0 +1,66 @@
+#! /bin/sh
+
+if test "$1" = --help; then
+    cat <<EOF
+$0: cross-check declared and defined vlog modules
+usage: $0 [--help]
+
+Must be run from the top-level source directory.
+
+On systems that don't support user-defined section names, the 'vlog'
+logging subsystem requires the list of modules in lib/vlog-modules.def
+to match the set of vlog modules actually used by the source files.
+However, most Open vSwitch development happens on systems that do
+support user-defined section names and don't have this requirement.
+This utility runs automatically at build time to check this
+requirement "by hand", so that Open vSwitch developers don't
+accidentally break the build for others.
+EOF
+    exit 0
+elif test "$#" != 0; then
+    echo "no arguments accepted (use --help for help)"
+    exit 1
+elif test ! -e lib/vlog-modules.def; then
+    echo "must run from the top-level source directory (use --help for help)"
+    exit 1
+fi
+
+# We can only get a list of source files if this is a Git checkout.
+if test -e .git && (git --version) >/dev/null 2>&1; then
+    :
+else
+    exit 0
+fi
+
+# Get the list of modules declared in lib/vlog-modules.def.
+vlog_modules=`
+    sed -n 's/^VLOG_MODULE(\([_a-zA-Z0-9]\{1,\}\)).*$/\1/p' \
+    lib/vlog-modules.def \
+    | LC_ALL=C sort -u | xargs echo`
+
+# Get the list of modules defined in some source file.
+src_modules=`
+    git grep -h -E '^[ 	]*VLOG_DEFINE(_THIS)?_MODULE\([_a-zA-Z0-9]+\)[ 	]*$' \
+    | sed 's/.*(\([_a-zA-Z0-9]\{1,\}\)).*/\1/' \
+    | LC_ALL=C sort -u \
+    | xargs echo`
+
+rc=0
+
+for module in $vlog_modules; do
+    case " $src_modules " in
+        *" $module "*) ;;
+        *) echo "vlog module $module is declared in lib/vlog-modules.def but not defined by any source file";
+            rc=1 ;;
+    esac
+done
+
+for module in $src_modules; do
+    case " $vlog_modules " in
+        *" $module "*) ;;
+        *) echo "vlog module $module is defined in a source file but not declared in lib/vlog-modules.def";
+            rc=1 ;;
+    esac
+done
+
+exit $rc
diff --git a/configure.ac b/configure.ac
index aff53a1..fd3ce85 100644
--- a/configure.ac
+++ b/configure.ac
@@ -65,6 +65,7 @@ OVS_CHECK_MALLOC_HOOKS
 OVS_CHECK_VALGRIND
 OVS_CHECK_TTY_LOCK_DIR
 OVS_CHECK_SOCKET_LIBS
+OVS_CHECK_LINKER_SECTIONS
 
 AC_CHECK_FUNCS([strsignal])
 
diff --git a/extras/ezio/ezio-term.c b/extras/ezio/ezio-term.c
index d96122b..b67cee9 100644
--- a/extras/ezio/ezio-term.c
+++ b/extras/ezio/ezio-term.c
@@ -37,10 +37,10 @@
 #include "terminal.h"
 #include "timeval.h"
 #include "util.h"
-
-#define THIS_MODULE VLM_ezio_term
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(ezio_term)
+
 /* EZIO button status. */
 enum btn_status {
     BTN_UP    = 1 << 0,
diff --git a/extras/ezio/ovs-switchui.c b/extras/ezio/ovs-switchui.c
index 36fa376..bf7b64a 100644
--- a/extras/ezio/ovs-switchui.c
+++ b/extras/ezio/ovs-switchui.c
@@ -49,10 +49,10 @@
 #include "timeval.h"
 #include "util.h"
 #include "vconn.h"
+#include "vlog.h"
 #include "xtoxll.h"
 
-#define THIS_MODULE VLM_switchui
-#include "vlog.h"
+VLOG_DEFINE_THIS_MODULE(switchui)
 
 static void parse_options(int argc, char *argv[]);
 static void usage(void);
@@ -151,7 +151,7 @@ main(int argc, char *argv[])
     vlog_init();
     parse_options(argc, argv);
     signal(SIGPIPE, SIG_IGN);
-    vlog_set_levels(VLM_ANY_MODULE, VLF_CONSOLE, VLL_EMER);
+    vlog_set_levels(NULL, VLF_CONSOLE, VLL_EMER);
     init_reboot_notifier();
 
     argc -= optind;
diff --git a/extras/ezio/terminal.c b/extras/ezio/terminal.c
index 090e80e..3e499ab 100644
--- a/extras/ezio/terminal.c
+++ b/extras/ezio/terminal.c
@@ -26,10 +26,10 @@
 #include "ezio.h"
 #include "poll-loop.h"
 #include "util.h"
-
-#define THIS_MODULE VLM_terminal
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(terminal)
+
 /* UTF-8 decoding. */
 static struct utf8_reader *utf8_reader_create(void);
 static void utf8_reader_destroy(struct utf8_reader *);
diff --git a/extras/ezio/tty.c b/extras/ezio/tty.c
index 4328828..a4bb14c 100644
--- a/extras/ezio/tty.c
+++ b/extras/ezio/tty.c
@@ -28,10 +28,10 @@
 #include "fatal-signal.h"
 #include "socket-util.h"
 #include "util.h"
-
-#define THIS_MODULE VLM_tty
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(tty)
+
 /* Get major() and minor() macros. */
 #if MAJOR_IN_MKDEV
 #  include <sys/mkdev.h>
diff --git a/extras/ezio/vt-dummy.c b/extras/ezio/vt-dummy.c
index c1de6c8..18da821 100644
--- a/extras/ezio/vt-dummy.c
+++ b/extras/ezio/vt-dummy.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2009 Nicira Networks, Inc.
+/* Copyright (c) 2008, 2009, 2010 Nicira Networks, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,10 +16,10 @@
 #include <config.h>
 #include "extras/ezio/vt.h"
 #include <errno.h>
-
-#define THIS_MODULE VLM_vt
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(vt)
+
 int
 vt_open(int open_flags)
 {
diff --git a/extras/ezio/vt-linux.c b/extras/ezio/vt-linux.c
index 92f7ebb..b281c89 100644
--- a/extras/ezio/vt-linux.c
+++ b/extras/ezio/vt-linux.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2009 Nicira Networks, Inc.
+/* Copyright (c) 2008, 2009, 2010 Nicira Networks, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,10 +24,10 @@
 #include <sys/ioctl.h>
 #include <unistd.h>
 #include "util.h"
-
-#define THIS_MODULE VLM_vt
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(vt)
+
 static bool get_console_fd(int *fd);
 
 int
diff --git a/lib/automake.mk b/lib/automake.mk
index 71e4d61..3bf9da1 100644
--- a/lib/automake.mk
+++ b/lib/automake.mk
@@ -263,30 +263,8 @@ lib/coverage-counters.c: $(COVERAGE_FILES) lib/coverage-scan.pl
 	mv $@.tmp $@
 EXTRA_DIST += lib/coverage-scan.pl
 
-
-# Make sure that every vlog module listed in vlog-modules.def is
-# actually used somewhere.
-ALL_LOCAL += check-for-unused-vlog-modules
-check-for-unused-vlog-modules:
-	if test -e $(srcdir)/.git && (git --version) >/dev/null 2>&1; then    \
-	  cd $(srcdir);							      \
-	  decl_vlog=`sed -n 's/^VLOG_MODULE(\([_a-z0-9]\{1,\}\)).*$$/\1/p'    \
-	             lib/vlog-modules.def |				      \
-                     LC_ALL=C sort -u |					      \
-                     xargs echo`;					      \
-	  used_vlog=`git grep VLM_ |					      \
-	             sed -n 's/.*VLM_\([a-z_0-9]\{1,\}\).*/\1/p' |	      \
-	             LC_ALL=C sort -u |					      \
-                     xargs echo`;					      \
-	  rc=0;								      \
-	  for decl in $$decl_vlog; do					      \
-            case " $$used_vlog " in					      \
-	      *" $$decl "*) ;;						      \
-	      *) echo "vlog module $$decl is declared in lib/vlog-modules.def \
-but not used by any source file";					      \
-                 rc=1 ;;						      \
-            esac							      \
-          done;								      \
-	  exit $$rc;							      \
-	fi
-.PHONY: check-for-unused-vlog-modules
+ALL_LOCAL += check-vlog-modules
+check-vlog-modules:
+	cd $(srcdir) && build-aux/check-vlog-modules
+.PHONY: check-vlog-modules
+EXTRA_DIST += build-aux/check-vlog-modules
diff --git a/lib/backtrace.c b/lib/backtrace.c
index 80cae54..131bdf4 100644
--- a/lib/backtrace.c
+++ b/lib/backtrace.c
@@ -21,10 +21,10 @@
 #include <stdbool.h>
 #include <stdio.h>
 #include "compiler.h"
-
-#define THIS_MODULE VLM_backtrace
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(backtrace)
+
 static uintptr_t OVS_UNUSED
 get_max_stack(void)
 {
diff --git a/lib/coverage.c b/lib/coverage.c
index 5c99c18..6e65810 100644
--- a/lib/coverage.c
+++ b/lib/coverage.c
@@ -23,10 +23,10 @@
 #include "hash.h"
 #include "unixctl.h"
 #include "util.h"
-
-#define THIS_MODULE VLM_coverage
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(coverage)
+
 static unsigned int epoch;
 
 static void
diff --git a/lib/daemon.c b/lib/daemon.c
index 59628f2..6cb553a 100644
--- a/lib/daemon.c
+++ b/lib/daemon.c
@@ -32,10 +32,10 @@
 #include "socket-util.h"
 #include "timeval.h"
 #include "util.h"
-
-#define THIS_MODULE VLM_daemon
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(daemon)
+
 /* Should we run in the background? */
 static bool detach;
 
diff --git a/lib/dhcp-client.c b/lib/dhcp-client.c
index 7168361..961994a 100644
--- a/lib/dhcp-client.c
+++ b/lib/dhcp-client.c
@@ -35,10 +35,10 @@
 #include "poll-loop.h"
 #include "sat-math.h"
 #include "timeval.h"
-
-#define THIS_MODULE VLM_dhcp_client
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(dhcp_client)
+
 #define DHCLIENT_STATES                         \
     DHCLIENT_STATE(INIT, 1 << 0)                \
     DHCLIENT_STATE(INIT_REBOOT, 1 << 1)         \
diff --git a/lib/dhcp.c b/lib/dhcp.c
index e16176b..e6d5735 100644
--- a/lib/dhcp.c
+++ b/lib/dhcp.c
@@ -24,10 +24,10 @@
 #include <stdlib.h>
 #include "dynamic-string.h"
 #include "ofpbuf.h"
-
-#define THIS_MODULE VLM_dhcp
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(dhcp)
+
 /* Information about a DHCP argument type. */
 struct arg_type {
     const char *name;           /* Name. */
diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c
index af6eee4..2d9dd88 100644
--- a/lib/dpif-linux.c
+++ b/lib/dpif-linux.c
@@ -40,9 +40,9 @@
 #include "shash.h"
 #include "svec.h"
 #include "util.h"
-
 #include "vlog.h"
-#define THIS_MODULE VLM_dpif_linux
+
+VLOG_DEFINE_THIS_MODULE(dpif_linux)
 
 /* Datapath interface for the openvswitch Linux kernel module. */
 struct dpif_linux {
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 5021874..cd620a5 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -45,9 +45,9 @@
 #include "queue.h"
 #include "timeval.h"
 #include "util.h"
-
 #include "vlog.h"
-#define THIS_MODULE VLM_dpif_netdev
+
+VLOG_DEFINE_THIS_MODULE(dpif_netdev)
 
 /* Configuration parameters. */
 enum { N_QUEUES = 2 };          /* Number of queues for dpif_recv(). */
diff --git a/lib/dpif.c b/lib/dpif.c
index 8286da4..5c01af9 100644
--- a/lib/dpif.c
+++ b/lib/dpif.c
@@ -37,9 +37,9 @@
 #include "svec.h"
 #include "util.h"
 #include "valgrind.h"
-
 #include "vlog.h"
-#define THIS_MODULE VLM_dpif
+
+VLOG_DEFINE_THIS_MODULE(dpif)
 
 static const struct dpif_class *base_dpif_classes[] = {
 #ifdef HAVE_NETLINK
diff --git a/lib/fatal-signal.c b/lib/fatal-signal.c
index 0f36036..d9442a3 100644
--- a/lib/fatal-signal.c
+++ b/lib/fatal-signal.c
@@ -28,10 +28,10 @@
 #include "shash.h"
 #include "socket-util.h"
 #include "util.h"
-
-#define THIS_MODULE VLM_fatal_signal
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(fatal_signal)
+
 /* Signals to catch. */
 static const int fatal_signals[] = { SIGTERM, SIGINT, SIGHUP, SIGALRM };
 
diff --git a/lib/flow.c b/lib/flow.c
index 7ae90d2..490c46b 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -28,10 +28,10 @@
 #include "openvswitch/datapath-protocol.h"
 #include "packets.h"
 #include "unaligned.h"
+#include "vlog.h"
 #include "xtoxll.h"
 
-#include "vlog.h"
-#define THIS_MODULE VLM_flow
+VLOG_DEFINE_THIS_MODULE(flow)
 
 static struct arp_eth_header *
 pull_arp(struct ofpbuf *packet)
diff --git a/lib/jsonrpc.c b/lib/jsonrpc.c
index 32d34b4..5d394c6 100644
--- a/lib/jsonrpc.c
+++ b/lib/jsonrpc.c
@@ -32,9 +32,9 @@
 #include "reconnect.h"
 #include "stream.h"
 #include "timeval.h"
-
-#define THIS_MODULE VLM_jsonrpc
 #include "vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(jsonrpc)
 
 struct jsonrpc {
     struct stream *stream;
diff --git a/lib/leak-checker.c b/lib/leak-checker.c
index 4ab55e5..28beb0b 100644
--- a/lib/leak-checker.c
+++ b/lib/leak-checker.c
@@ -18,10 +18,10 @@
 #include "leak-checker.h"
 #include <inttypes.h>
 #include "backtrace.h"
-
-#define THIS_MODULE VLM_leak_checker
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(leak_checker)
+
 #ifndef HAVE_MALLOC_HOOKS
 void
 leak_checker_start(const char *file_name OVS_UNUSED)
diff --git a/lib/learning-switch.c b/lib/learning-switch.c
index 7eb9e1c..31733f7 100644
--- a/lib/learning-switch.c
+++ b/lib/learning-switch.c
@@ -35,10 +35,10 @@
 #include "stp.h"
 #include "timeval.h"
 #include "vconn.h"
+#include "vlog.h"
 #include "xtoxll.h"
 
-#define THIS_MODULE VLM_learning_switch
-#include "vlog.h"
+VLOG_DEFINE_THIS_MODULE(learning_switch)
 
 enum port_state {
     P_DISABLED = 1 << 0,
diff --git a/lib/lockfile.c b/lib/lockfile.c
index 100440e..84bfb3c 100644
--- a/lib/lockfile.c
+++ b/lib/lockfile.c
@@ -29,10 +29,10 @@
 #include "hmap.h"
 #include "timeval.h"
 #include "util.h"
-
-#define THIS_MODULE VLM_lockfile
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(lockfile)
+
 struct lockfile {
     struct hmap_node hmap_node;
     char *name;
diff --git a/lib/mac-learning.c b/lib/mac-learning.c
index 5d64f54..c8582f3 100644
--- a/lib/mac-learning.c
+++ b/lib/mac-learning.c
@@ -29,10 +29,10 @@
 #include "tag.h"
 #include "timeval.h"
 #include "util.h"
-
-#define THIS_MODULE VLM_mac_learning
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(mac_learning)
+
 /* Returns the number of seconds since 'e' was last learned. */
 int
 mac_entry_age(const struct mac_entry *e)
diff --git a/lib/netdev-gre.c b/lib/netdev-gre.c
index 45b574f..c206871 100644
--- a/lib/netdev-gre.c
+++ b/lib/netdev-gre.c
@@ -27,10 +27,10 @@
 #include "openvswitch/gre.h"
 #include "packets.h"
 #include "socket-util.h"
-
-#define THIS_MODULE VLM_netdev_gre
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(netdev_gre)
+
 struct netdev_dev_gre {
     struct netdev_dev netdev_dev;
 };
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index 8cd40cd..1864021 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -61,9 +61,9 @@
 #include "socket-util.h"
 #include "shash.h"
 #include "svec.h"
-
-#define THIS_MODULE VLM_netdev_linux
 #include "vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(netdev_linux)
 
 /* These were introduced in Linux 2.6.14, so they might be missing if we have
  * old headers. */
diff --git a/lib/netdev-patch.c b/lib/netdev-patch.c
index ec4d4bd..930c102 100644
--- a/lib/netdev-patch.c
+++ b/lib/netdev-patch.c
@@ -26,10 +26,10 @@
 #include "openvswitch/datapath-protocol.h"
 #include "packets.h"
 #include "socket-util.h"
-
-#define THIS_MODULE VLM_netdev_patch
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(netdev_patch)
+
 struct netdev_dev_patch {
     struct netdev_dev netdev_dev;
 };
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index 58858f9..9683411 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -24,10 +24,10 @@
 #include "openvswitch/datapath-protocol.h"
 #include "shash.h"
 #include "socket-util.h"
-
-#define THIS_MODULE VLM_netdev_vport
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(netdev_vport)
+
 struct netdev_vport_notifier {
     struct netdev_notifier notifier;
     struct list list_node;
diff --git a/lib/netdev.c b/lib/netdev.c
index 38f4dd5..7d834ad 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -37,10 +37,10 @@
 #include "poll-loop.h"
 #include "shash.h"
 #include "svec.h"
-
-#define THIS_MODULE VLM_netdev
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(netdev)
+
 static const struct netdev_class *base_netdev_classes[] = {
 #ifdef HAVE_NETLINK
     &netdev_linux_class,
diff --git a/lib/netlink.c b/lib/netlink.c
index d59f65e..2f7bc0a 100644
--- a/lib/netlink.c
+++ b/lib/netlink.c
@@ -31,9 +31,9 @@
 #include "poll-loop.h"
 #include "timeval.h"
 #include "util.h"
-
 #include "vlog.h"
-#define THIS_MODULE VLM_netlink
+
+VLOG_DEFINE_THIS_MODULE(netlink)
 
 /* Linux header file confusion causes this to be undefined. */
 #ifndef SOL_NETLINK
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 16a3eee..1f42981 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -22,10 +22,10 @@
 #include "ofpbuf.h"
 #include "packets.h"
 #include "random.h"
+#include "vlog.h"
 #include "xtoxll.h"
 
-#define THIS_MODULE VLM_ofp_util
-#include "vlog.h"
+VLOG_DEFINE_THIS_MODULE(ofp_util)
 
 /* Rate limit for OpenFlow message parse errors.  These always indicate a bug
  * in the peer and so there's not much point in showing a lot of them. */
diff --git a/lib/ovsdb-error.c b/lib/ovsdb-error.c
index c57175a..5eb4ec7 100644
--- a/lib/ovsdb-error.c
+++ b/lib/ovsdb-error.c
@@ -25,8 +25,7 @@
 #include "util.h"
 #include "vlog.h"
 
-#define THIS_MODULE VLM_ovsdb_error
-#include "vlog.h"
+VLOG_DEFINE_THIS_MODULE(ovsdb_error)
 
 struct ovsdb_error {
     const char *tag;            /* String for "error" member. */
diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c
index f32fe0e..2a43781 100644
--- a/lib/ovsdb-idl.c
+++ b/lib/ovsdb-idl.c
@@ -34,10 +34,10 @@
 #include "poll-loop.h"
 #include "shash.h"
 #include "util.h"
-
-#define THIS_MODULE VLM_ovsdb_idl
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(ovsdb_idl)
+
 /* An arc from one idl_row to another.  When row A contains a UUID that
  * references row B, this is represented by an arc from A (the source) to B
  * (the destination).
diff --git a/lib/pcap.c b/lib/pcap.c
index 028dd0c..cc15411 100644
--- a/lib/pcap.c
+++ b/lib/pcap.c
@@ -22,10 +22,10 @@
 #include <string.h>
 #include "compiler.h"
 #include "ofpbuf.h"
-
-#define THIS_MODULE VLM_pcap
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(pcap)
+
 struct pcap_hdr {
     uint32_t magic_number;   /* magic number */
     uint16_t version_major;  /* major version number */
diff --git a/lib/poll-loop.c b/lib/poll-loop.c
index 91034b0..70360b9 100644
--- a/lib/poll-loop.c
+++ b/lib/poll-loop.c
@@ -28,10 +28,10 @@
 #include "fatal-signal.h"
 #include "list.h"
 #include "timeval.h"
-
-#define THIS_MODULE VLM_poll_loop
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(poll_loop)
+
 /* An event that will wake the following call to poll_block(). */
 struct poll_waiter {
     /* Set when the waiter is created. */
diff --git a/lib/process.c b/lib/process.c
index af867ef..a201a88 100644
--- a/lib/process.c
+++ b/lib/process.c
@@ -32,10 +32,10 @@
 #include "poll-loop.h"
 #include "socket-util.h"
 #include "util.h"
-
-#define THIS_MODULE VLM_process
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(process)
+
 struct process {
     struct list node;
     char *name;
diff --git a/lib/rconn.c b/lib/rconn.c
index 36828f3..d254356 100644
--- a/lib/rconn.c
+++ b/lib/rconn.c
@@ -30,10 +30,10 @@
 #include "timeval.h"
 #include "util.h"
 #include "vconn.h"
-
-#define THIS_MODULE VLM_rconn
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(rconn)
+
 #define STATES                                  \
     STATE(VOID, 1 << 0)                         \
     STATE(BACKOFF, 1 << 1)                      \
diff --git a/lib/reconnect.c b/lib/reconnect.c
index 372c2eb..169f317 100644
--- a/lib/reconnect.c
+++ b/lib/reconnect.c
@@ -21,10 +21,10 @@
 #include <stdlib.h>
 
 #include "poll-loop.h"
-
-#define THIS_MODULE VLM_reconnect
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(reconnect)
+
 #define STATES                                  \
     STATE(VOID, 1 << 0)                         \
     STATE(BACKOFF, 1 << 1)                      \
diff --git a/lib/rtnetlink.c b/lib/rtnetlink.c
index 1d302ea..f5a6df8 100644
--- a/lib/rtnetlink.c
+++ b/lib/rtnetlink.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Nicira Networks.
+ * Copyright (c) 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.
@@ -27,10 +27,10 @@
 #include "coverage.h"
 #include "netlink.h"
 #include "ofpbuf.h"
-
-#define THIS_MODULE VLM_rtnetlink
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(rtnetlink)
+
 /* rtnetlink socket. */
 static struct nl_sock *notify_sock;
 
diff --git a/lib/socket-util.c b/lib/socket-util.c
index bf563ed..16a321c 100644
--- a/lib/socket-util.c
+++ b/lib/socket-util.c
@@ -32,9 +32,9 @@
 #include <unistd.h>
 #include "fatal-signal.h"
 #include "util.h"
-
 #include "vlog.h"
-#define THIS_MODULE VLM_socket_util
+
+VLOG_DEFINE_THIS_MODULE(socket_util)
 
 /* Sets 'fd' to non-blocking mode.  Returns 0 if successful, otherwise a
  * positive errno value. */
diff --git a/lib/stp.c b/lib/stp.c
index 38885c0..c5c8b3b 100644
--- a/lib/stp.c
+++ b/lib/stp.c
@@ -17,6 +17,8 @@
 /* Based on sample implementation in 802.1D-1998.  Above copyright and license
  * applies to all modifications. */
 
+#include <config.h>
+
 #include "stp.h"
 #include <sys/types.h>
 #include <netinet/in.h>
@@ -27,10 +29,10 @@
 #include "ofpbuf.h"
 #include "packets.h"
 #include "util.h"
+#include "vlog.h"
 #include "xtoxll.h"
 
-#include "vlog.h"
-#define THIS_MODULE VLM_stp
+VLOG_DEFINE_THIS_MODULE(stp)
 
 /* Ethernet address used as the destination for STP frames. */
 const uint8_t stp_eth_addr[ETH_ADDR_LEN]
diff --git a/lib/stream-fd.c b/lib/stream-fd.c
index cc897b3..9410009 100644
--- a/lib/stream-fd.c
+++ b/lib/stream-fd.c
@@ -31,9 +31,9 @@
 #include "util.h"
 #include "stream-provider.h"
 #include "stream.h"
-
 #include "vlog.h"
-#define THIS_MODULE VLM_stream_fd
+
+VLOG_DEFINE_THIS_MODULE(stream_fd)
 
 /* Active file descriptor stream. */
 
diff --git a/lib/stream-ssl.c b/lib/stream-ssl.c
index 1944cb9..851e7a7 100644
--- a/lib/stream-ssl.c
+++ b/lib/stream-ssl.c
@@ -41,9 +41,9 @@
 #include "stream-provider.h"
 #include "stream.h"
 #include "timeval.h"
-
 #include "vlog.h"
-#define THIS_MODULE VLM_stream_ssl
+
+VLOG_DEFINE_THIS_MODULE(stream_ssl)
 
 /* Active SSL. */
 
diff --git a/lib/stream-tcp.c b/lib/stream-tcp.c
index 2f7e798..d004777 100644
--- a/lib/stream-tcp.c
+++ b/lib/stream-tcp.c
@@ -30,9 +30,9 @@
 #include "util.h"
 #include "stream-provider.h"
 #include "stream-fd.h"
-
 #include "vlog.h"
-#define THIS_MODULE VLM_stream_tcp
+
+VLOG_DEFINE_THIS_MODULE(stream_tcp)
 
 /* Active TCP. */
 
diff --git a/lib/stream-unix.c b/lib/stream-unix.c
index 930f548..20aa5b4 100644
--- a/lib/stream-unix.c
+++ b/lib/stream-unix.c
@@ -33,9 +33,9 @@
 #include "util.h"
 #include "stream-provider.h"
 #include "stream-fd.h"
-
 #include "vlog.h"
-#define THIS_MODULE VLM_stream_unix
+
+VLOG_DEFINE_THIS_MODULE(stream_unix)
 
 /* Active UNIX socket. */
 
diff --git a/lib/stream.c b/lib/stream.c
index acbefc2..43c95b6 100644
--- a/lib/stream.c
+++ b/lib/stream.c
@@ -35,10 +35,10 @@
 #include "poll-loop.h"
 #include "random.h"
 #include "util.h"
-
-#define THIS_MODULE VLM_stream
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(stream)
+
 /* State of an active stream.*/
 enum stream_state {
     SCS_CONNECTING,             /* Underlying stream is not connected. */
@@ -769,7 +769,7 @@ stream_content_type_to_string(enum stream_content_type type)
 void
 stream_report_content(const void *data, size_t size,
                       enum stream_content_type expected_type,
-                      enum vlog_module module, const char *stream_name)
+                      struct vlog_module *module, const char *stream_name)
 {
     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
     enum stream_content_type actual_type;
diff --git a/lib/stream.h b/lib/stream.h
index 256667e..5c536c6 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -84,6 +84,6 @@ enum stream_content_type {
 };
 
 void stream_report_content(const void *, size_t, enum stream_content_type,
-                           enum vlog_module, const char *stream_name);
+                           struct vlog_module *, const char *stream_name);
 
 #endif /* stream.h */
diff --git a/lib/svec.c b/lib/svec.c
index bc3df23..79c8355 100644
--- a/lib/svec.c
+++ b/lib/svec.c
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -22,10 +22,10 @@
 #include <string.h>
 #include "dynamic-string.h"
 #include "util.h"
-
-#define THIS_MODULE VLM_svec
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(svec)
+
 void
 svec_init(struct svec *svec)
 {
diff --git a/lib/timeval.c b/lib/timeval.c
index c69799d..4a5eccc 100644
--- a/lib/timeval.c
+++ b/lib/timeval.c
@@ -27,9 +27,9 @@
 #include "coverage.h"
 #include "fatal-signal.h"
 #include "util.h"
-
 #include "vlog.h"
-#define THIS_MODULE VLM_timeval
+
+VLOG_DEFINE_THIS_MODULE(timeval)
 
 /* Initialized? */
 static bool inited;
diff --git a/lib/unixctl.c b/lib/unixctl.c
index 7078568..ac756a8 100644
--- a/lib/unixctl.c
+++ b/lib/unixctl.c
@@ -36,13 +36,13 @@
 #include "socket-util.h"
 #include "svec.h"
 #include "util.h"
+#include "vlog.h"
 
 #ifndef SCM_CREDENTIALS
 #include <time.h>
 #endif
 
-#define THIS_MODULE VLM_unixctl
-#include "vlog.h"
+VLOG_DEFINE_THIS_MODULE(unixctl)
 
 struct unixctl_command {
     unixctl_cb_func *cb;
diff --git a/lib/util.c b/lib/util.c
index 19f13dd..9fc99f0 100644
--- a/lib/util.c
+++ b/lib/util.c
@@ -23,10 +23,10 @@
 #include <string.h>
 #include <unistd.h>
 #include "coverage.h"
-
-#define THIS_MODULE VLM_util
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(util)
+
 const char *program_name;
 
 void
diff --git a/lib/vconn-stream.c b/lib/vconn-stream.c
index df728d5..e6c2946 100644
--- a/lib/vconn-stream.c
+++ b/lib/vconn-stream.c
@@ -32,9 +32,9 @@
 #include "util.h"
 #include "vconn-provider.h"
 #include "vconn.h"
-
 #include "vlog.h"
-#define THIS_MODULE VLM_vconn_stream
+
+VLOG_DEFINE_THIS_MODULE(vconn_stream)
 
 /* Active stream socket vconn. */
 
diff --git a/lib/vconn.c b/lib/vconn.c
index b558f80..99b6e7b 100644
--- a/lib/vconn.c
+++ b/lib/vconn.c
@@ -36,10 +36,10 @@
 #include "poll-loop.h"
 #include "random.h"
 #include "util.h"
-
-#define THIS_MODULE VLM_vconn
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(vconn)
+
 /* State of an active vconn.*/
 enum vconn_state {
     /* This is the ordinary progression of states. */
diff --git a/lib/vlog.c b/lib/vlog.c
index fea60fa..329f656 100644
--- a/lib/vlog.c
+++ b/lib/vlog.c
@@ -33,7 +33,7 @@
 #include "unixctl.h"
 #include "util.h"
 
-#define THIS_MODULE VLM_vlog
+VLOG_DEFINE_THIS_MODULE(vlog)
 
 /* Name for each logging level. */
 static const char *level_names[VLL_N_LEVELS] = {
@@ -49,12 +49,24 @@ static int syslog_levels[VLL_N_LEVELS] = {
 #undef VLOG_LEVEL
 };
 
-/* Name for each logging module */
-static const char *module_names[VLM_N_MODULES] = { 
-#define VLOG_MODULE(NAME) #NAME,
+/* The log modules. */
+#if USE_LINKER_SECTIONS
+extern struct vlog_module *__start_vlog_modules[];
+extern struct vlog_module *__stop_vlog_modules[];
+#define vlog_modules __start_vlog_modules
+#define n_vlog_modules (__stop_vlog_modules - __start_vlog_modules)
+#else
+#define VLOG_MODULE VLOG_DEFINE_MODULE__
+#include "vlog-modules.def"
+#undef VLOG_MODULE
+
+struct vlog_module *vlog_modules[] = {
+#define VLOG_MODULE(NAME) &VLM_##NAME,
 #include "vlog-modules.def"
 #undef VLOG_MODULE
 };
+#define n_vlog_modules ARRAY_SIZE(vlog_modules)
+#endif
 
 /* Information about each facility. */
 struct facility {
@@ -68,21 +80,6 @@ static struct facility facilities[VLF_N_FACILITIES] = {
 #undef VLOG_FACILITY
 };
 
-/* Current log levels. */
-static int levels[VLM_N_MODULES][VLF_N_FACILITIES] = {
-#define VLOG_MODULE(NAME) { VLL_INFO, VLL_INFO, VLL_INFO },
-#include "vlog-modules.def"
-#undef VLOG_MODULE
-};
-
-/* For fast checking whether we're logging anything for a given module and
- * level.*/
-enum vlog_level min_vlog_levels[VLM_N_MODULES] = {
-#define VLOG_MODULE(NAME) VLL_INFO,
-#include "vlog-modules.def"
-#undef VLOG_MODULE
-};
-
 /* Time at which vlog was initialized, in milliseconds. */
 static long long int boot_time;
 
@@ -90,7 +87,7 @@ static long long int boot_time;
 static char *log_file_name;
 static FILE *log_file;
 
-static void format_log_message(enum vlog_module, enum vlog_level,
+static void format_log_message(const struct vlog_module *, enum vlog_level,
                                enum vlog_facility, unsigned int msg_num,
                                const char *message, va_list, struct ds *)
     PRINTF_FORMAT(5, 0);
@@ -151,64 +148,76 @@ vlog_get_facility_val(const char *name)
 }
 
 /* Returns the name for logging module 'module'. */
-const char *vlog_get_module_name(enum vlog_module module) 
+const char *
+vlog_get_module_name(const struct vlog_module *module)
 {
-    assert(module < VLM_N_MODULES);
-    return module_names[module];
+    return module->name;
 }
 
-/* Returns the logging module named 'name', or VLM_N_MODULES if 'name' is not
- * the name of a logging module. */
-enum vlog_module
-vlog_get_module_val(const char *name) 
+/* Returns the logging module named 'name', or NULL if 'name' is not the name
+ * of a logging module. */
+struct vlog_module *
+vlog_module_from_name(const char *name)
 {
-    return search_name_array(name, module_names, ARRAY_SIZE(module_names));
+    struct vlog_module **mp;
+
+    for (mp = vlog_modules; mp < &vlog_modules[n_vlog_modules]; mp++) {
+        if (!strcasecmp(name, (*mp)->name)) {
+            return *mp;
+        }
+    }
+    return NULL;
 }
 
 /* Returns the current logging level for the given 'module' and 'facility'. */
 enum vlog_level
-vlog_get_level(enum vlog_module module, enum vlog_facility facility) 
+vlog_get_level(const struct vlog_module *module, enum vlog_facility facility) 
 {
-    assert(module < VLM_N_MODULES);
     assert(facility < VLF_N_FACILITIES);
-    return levels[module][facility];
+    return module->levels[facility];
 }
 
 static void
-update_min_level(enum vlog_module module)
+update_min_level(struct vlog_module *module)
 {
-    enum vlog_level min_level = VLL_EMER;
     enum vlog_facility facility;
 
+    module->min_level = VLL_EMER;
     for (facility = 0; facility < VLF_N_FACILITIES; facility++) {
         if (log_file || facility != VLF_FILE) {
-            min_level = MAX(min_level, levels[module][facility]); 
+            enum vlog_level level = module->levels[facility];
+            if (level < module->min_level) {
+                module->min_level = level;
+            }
         }
     }
-    min_vlog_levels[module] = min_level;
 }
 
 static void
-set_facility_level(enum vlog_facility facility, enum vlog_module module,
+set_facility_level(enum vlog_facility facility, struct vlog_module *module,
                    enum vlog_level level)
 {
     assert(facility >= 0 && facility < VLF_N_FACILITIES);
     assert(level < VLL_N_LEVELS);
 
-    if (module == VLM_ANY_MODULE) {
-        for (module = 0; module < VLM_N_MODULES; module++) {
-            levels[module][facility] = level;
-            update_min_level(module);
+    if (!module) {
+        struct vlog_module **mp;
+
+        for (mp = vlog_modules; mp < &vlog_modules[n_vlog_modules]; mp++) {
+            (*mp)->levels[facility] = level;
+            update_min_level(*mp);
         }
     } else {
-        levels[module][facility] = level;
+        module->levels[facility] = level;
         update_min_level(module);
     }
 }
 
-/* Sets the logging level for the given 'module' and 'facility' to 'level'. */
+/* Sets the logging level for the given 'module' and 'facility' to 'level'.  A
+ * null 'module' or a 'facility' of VLF_ANY_FACILITY is treated as a wildcard
+ * across all modules or facilities, respectively. */
 void
-vlog_set_levels(enum vlog_module module, enum vlog_facility facility,
+vlog_set_levels(struct vlog_module *module, enum vlog_facility facility,
                 enum vlog_level level) 
 {
     assert(facility < VLF_N_FACILITIES || facility == VLF_ANY_FACILITY);
@@ -264,7 +273,7 @@ int
 vlog_set_log_file(const char *file_name)
 {
     char *old_log_file_name;
-    enum vlog_module module;
+    struct vlog_module **mp;
     int error;
 
     /* Close old log file. */
@@ -286,8 +295,8 @@ vlog_set_log_file(const char *file_name)
     /* Open new log file and update min_levels[] to reflect whether we actually
      * have a log_file. */
     log_file = fopen(log_file_name, "a");
-    for (module = 0; module < VLM_N_MODULES; module++) {
-        update_min_level(module);
+    for (mp = vlog_modules; mp < &vlog_modules[n_vlog_modules]; mp++) {
+        update_min_level(*mp);
     }
 
     /* Log success or failure. */
@@ -328,7 +337,7 @@ vlog_set_levels_from_string(const char *s_)
 
     for (module = strtok_r(s, ": \t", &save_ptr); module != NULL;
          module = strtok_r(NULL, ": \t", &save_ptr)) {
-        enum vlog_module e_module;
+        struct vlog_module *e_module;
         enum vlog_facility e_facility;
 
         facility = strtok_r(NULL, ":", &save_ptr);
@@ -352,10 +361,10 @@ vlog_set_levels_from_string(const char *s_)
             enum vlog_level e_level;
 
             if (!strcmp(module, "ANY")) {
-                e_module = VLM_ANY_MODULE;
+                e_module = NULL;
             } else {
-                e_module = vlog_get_module_val(module);
-                if (e_module >= VLM_N_MODULES) {
+                e_module = vlog_module_from_name(module);
+                if (!e_module) {
                     char *msg = xasprintf("unknown module \"%s\"", module);
                     free(s);
                     return msg;
@@ -388,7 +397,7 @@ vlog_set_verbosity(const char *arg)
             ovs_fatal(0, "processing \"%s\": %s", arg, msg);
         }
     } else {
-        vlog_set_levels(VLM_ANY_MODULE, VLF_ANY_FACILITY, VLL_DBG);
+        vlog_set_levels(NULL, VLF_ANY_FACILITY, VLL_DBG);
     }
 }
 
@@ -464,17 +473,17 @@ char *
 vlog_get_levels(void)
 {
     struct ds s = DS_EMPTY_INITIALIZER;
-    enum vlog_module module;
+    struct vlog_module **mp;
 
     ds_put_format(&s, "                 console    syslog    file\n");
     ds_put_format(&s, "                 -------    ------    ------\n");
 
-    for (module = 0; module < VLM_N_MODULES; module++) {
+    for (mp = vlog_modules; mp < &vlog_modules[n_vlog_modules]; mp++) {
         ds_put_format(&s, "%-16s  %4s       %4s       %4s\n",
-           vlog_get_module_name(module),
-           vlog_get_level_name(vlog_get_level(module, VLF_CONSOLE)),
-           vlog_get_level_name(vlog_get_level(module, VLF_SYSLOG)),
-           vlog_get_level_name(vlog_get_level(module, VLF_FILE)));
+           vlog_get_module_name(*mp),
+           vlog_get_level_name(vlog_get_level(*mp, VLF_CONSOLE)),
+           vlog_get_level_name(vlog_get_level(*mp, VLF_SYSLOG)),
+           vlog_get_level_name(vlog_get_level(*mp, VLF_FILE)));
     }
 
     return ds_cstr(&s);
@@ -484,9 +493,9 @@ vlog_get_levels(void)
  * would cause some log output, false if that module and level are completely
  * disabled. */
 bool
-vlog_is_enabled(enum vlog_module module, enum vlog_level level)
+vlog_is_enabled(const struct vlog_module *module, enum vlog_level level)
 {
-    return min_vlog_levels[module] >= level;
+    return module->min_level >= level;
 }
 
 static const char *
@@ -505,7 +514,7 @@ fetch_braces(const char *p, const char *def, char *out, size_t out_size)
 }
 
 static void
-format_log_message(enum vlog_module module, enum vlog_level level,
+format_log_message(const struct vlog_module *module, enum vlog_level level,
                    enum vlog_facility facility, unsigned int msg_num,
                    const char *message, va_list args_, struct ds *s)
 {
@@ -600,12 +609,12 @@ format_log_message(enum vlog_module module, enum vlog_level level,
  *
  * Guaranteed to preserve errno. */
 void
-vlog_valist(enum vlog_module module, enum vlog_level level,
+vlog_valist(const struct vlog_module *module, enum vlog_level level,
             const char *message, va_list args)
 {
-    bool log_to_console = levels[module][VLF_CONSOLE] >= level;
-    bool log_to_syslog = levels[module][VLF_SYSLOG] >= level;
-    bool log_to_file = levels[module][VLF_FILE] >= level && log_file;
+    bool log_to_console = module->levels[VLF_CONSOLE] >= level;
+    bool log_to_syslog = module->levels[VLF_SYSLOG] >= level;
+    bool log_to_file = module->levels[VLF_FILE] >= level && log_file;
     if (log_to_console || log_to_syslog || log_to_file) {
         int save_errno = errno;
         static unsigned int msg_num;
@@ -649,7 +658,8 @@ vlog_valist(enum vlog_module module, enum vlog_level level,
 }
 
 void
-vlog(enum vlog_module module, enum vlog_level level, const char *message, ...)
+vlog(const struct vlog_module *module, enum vlog_level level,
+     const char *message, ...)
 {
     va_list args;
 
@@ -659,7 +669,7 @@ vlog(enum vlog_module module, enum vlog_level level, const char *message, ...)
 }
 
 bool
-vlog_should_drop(enum vlog_module module, enum vlog_level level,
+vlog_should_drop(const struct vlog_module *module, enum vlog_level level,
                  struct vlog_rate_limit *rl)
 {
     if (!vlog_is_enabled(module, level)) {
@@ -699,7 +709,7 @@ vlog_should_drop(enum vlog_module module, enum vlog_level level,
 }
 
 void
-vlog_rate_limit(enum vlog_module module, enum vlog_level level,
+vlog_rate_limit(const struct vlog_module *module, enum vlog_level level,
                 struct vlog_rate_limit *rl, const char *message, ...)
 {
     if (!vlog_should_drop(module, level, rl)) {
diff --git a/lib/vlog.h b/lib/vlog.h
index f50b76a..f530b92 100644
--- a/lib/vlog.h
+++ b/lib/vlog.h
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -60,16 +60,25 @@ enum vlog_facility {
 const char *vlog_get_facility_name(enum vlog_facility);
 enum vlog_facility vlog_get_facility_val(const char *name);
 
-/* VLM_ constant for each vlog module. */
-enum vlog_module {
-#define VLOG_MODULE(NAME) VLM_##NAME,
-#include "vlog-modules.def"
-    VLM_N_MODULES,
-    VLM_ANY_MODULE = -1
+/* A log module. */
+struct vlog_module {
+    const char *name;             /* User-visible name. */
+    int levels[VLF_N_FACILITIES]; /* Minimum log level for each facility. */
+    int min_level;                /* Minimum log level for any facility. */
 };
 
-const char *vlog_get_module_name(enum vlog_module);
-enum vlog_module vlog_get_module_val(const char *name);
+/* Creates and initializes a global instance of a module named MODULE. */
+#if USE_LINKER_SECTIONS
+#define VLOG_DEFINE_MODULE(MODULE)                                      \
+        VLOG_DEFINE_MODULE__(MODULE)                                    \
+        struct vlog_module *vlog_module_ptr_##MODULE                    \
+            __attribute__((section("vlog_modules"))) = &VLM_##MODULE;
+#else
+#define VLOG_DEFINE_MODULE(MODULE) extern struct vlog_module VLM_##MODULE;
+#endif
+
+const char *vlog_get_module_name(const struct vlog_module *);
+struct vlog_module *vlog_module_from_name(const char *name);
 
 /* Rate-limiter for log messages. */
 struct vlog_rate_limit {
@@ -103,12 +112,13 @@ struct vlog_rate_limit {
         }
 
 /* Configuring how each module logs messages. */
-enum vlog_level vlog_get_level(enum vlog_module, enum vlog_facility);
-void vlog_set_levels(enum vlog_module, enum vlog_facility, enum vlog_level);
+enum vlog_level vlog_get_level(const struct vlog_module *, enum vlog_facility);
+void vlog_set_levels(struct vlog_module *,
+                     enum vlog_facility, enum vlog_level);
 char *vlog_set_levels_from_string(const char *);
 char *vlog_get_levels(void);
-bool vlog_is_enabled(enum vlog_module, enum vlog_level);
-bool vlog_should_drop(enum vlog_module, enum vlog_level,
+bool vlog_is_enabled(const struct vlog_module *, enum vlog_level);
+bool vlog_should_drop(const struct vlog_module *, enum vlog_level,
                       struct vlog_rate_limit *);
 void vlog_set_verbosity(const char *arg);
 
@@ -121,18 +131,26 @@ int vlog_reopen_log_file(void);
 /* Function for actual logging. */
 void vlog_init(void);
 void vlog_exit(void);
-void vlog(enum vlog_module, enum vlog_level, const char *format, ...)
+void vlog(const struct vlog_module *, enum vlog_level, const char *format, ...)
     __attribute__((format(printf, 3, 4)));
-void vlog_valist(enum vlog_module, enum vlog_level, const char *, va_list)
+void vlog_valist(const struct vlog_module *, enum vlog_level,
+                 const char *, va_list)
     __attribute__((format(printf, 3, 0)));
-void vlog_rate_limit(enum vlog_module, enum vlog_level,
+void vlog_rate_limit(const struct vlog_module *, enum vlog_level,
                      struct vlog_rate_limit *, const char *, ...)
     __attribute__((format(printf, 4, 5)));
 
-/* Convenience macros.  To use these, define THIS_MODULE as a macro that
- * expands to the module used by the current source file, e.g.
- *      #include "vlog.h"
- *      #define THIS_MODULE VLM_netlink
+/* Creates and initializes a global instance of a module named MODULE, and
+ * defines a static variable named THIS_MODULE that points to it, for use with
+ * the convenience macros below. */
+#define VLOG_DEFINE_THIS_MODULE(MODULE)                                 \
+        VLOG_DEFINE_MODULE(MODULE)                                      \
+        static struct vlog_module *const THIS_MODULE = &VLM_##MODULE;
+
+/* Convenience macros.  These assume that THIS_MODULE points to a "struct
+ * vlog_module" for the current module, as set up by e.g. the
+ * VLOG_DEFINE_MODULE macro above.
+ * 
  * Guaranteed to preserve errno.
  */
 #define VLOG_EMER(...) VLOG(VLL_EMER, __VA_ARGS__)
@@ -178,20 +196,26 @@ void vlog_rate_limit(enum vlog_module, enum vlog_level,
 void vlog_usage(void);
 
 /* Implementation details. */
-#define VLOG(LEVEL, ...)                                \
-    do {                                                \
-        if (min_vlog_levels[THIS_MODULE] >= LEVEL) {    \
-            vlog(THIS_MODULE, LEVEL, __VA_ARGS__);      \
-        }                                               \
+#define VLOG(LEVEL, ...)                            \
+    do {                                            \
+        if (THIS_MODULE->min_level >= LEVEL) {      \
+            vlog(THIS_MODULE, LEVEL, __VA_ARGS__);  \
+        }                                           \
     } while (0)
 #define VLOG_RL(RL, LEVEL, ...)                                     \
     do {                                                            \
-        if (min_vlog_levels[THIS_MODULE] >= LEVEL) {                \
+        if (THIS_MODULE->min_level >= LEVEL) {                      \
             vlog_rate_limit(THIS_MODULE, LEVEL, RL, __VA_ARGS__);   \
         }                                                           \
     } while (0)
-extern enum vlog_level min_vlog_levels[VLM_N_MODULES];
- 
+#define VLOG_DEFINE_MODULE__(MODULE)                                    \
+        struct vlog_module VLM_##MODULE =                               \
+        {                                                               \
+            #MODULE,                                      /* name */    \
+            { [ 0 ... VLF_N_FACILITIES - 1] = VLL_INFO }, /* levels */  \
+            VLL_INFO,                                     /* min_level */ \
+        };
+
 #ifdef  __cplusplus
 }
 #endif
diff --git a/m4/openvswitch.m4 b/m4/openvswitch.m4
index 0b22f64..6fb8609 100644
--- a/m4/openvswitch.m4
+++ b/m4/openvswitch.m4
@@ -347,3 +347,78 @@ AC_DEFUN([OVS_CHECK_OVSDBMONITOR],
    AC_MSG_CHECKING([whether to build ovsdbmonitor])
    AC_MSG_RESULT([$BUILD_OVSDBMONITOR])
    AM_CONDITIONAL([BUILD_OVSDBMONITOR], [test $BUILD_OVSDBMONITOR = yes])])
+
+# OVS_LINK2_IFELSE(SOURCE1, SOURCE2, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
+# -------------------------------------------------------------
+# Based on AC_LINK_IFELSE, but tries to link both SOURCE1 and SOURCE2
+# into a program.
+#
+# This macro is borrowed from acinclude.m4 in GNU PSPP, which has the
+# following license:
+#
+#     Copyright (C) 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
+#     This file is free software; the Free Software Foundation
+#     gives unlimited permission to copy and/or distribute it,
+#     with or without modifications, as long as this notice is preserved.
+#
+m4_define([OVS_LINK2_IFELSE],
+[m4_ifvaln([$1], [AC_LANG_CONFTEST([$1])])dnl
+mv conftest.$ac_ext conftest1.$ac_ext
+m4_ifvaln([$2], [AC_LANG_CONFTEST([$2])])dnl
+mv conftest.$ac_ext conftest2.$ac_ext
+rm -f conftest1.$ac_objext conftest2.$ac_objext conftest$ac_exeext
+ovs_link2='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest1.$ac_ext conftest2.$ac_ext $LIBS >&5'
+AS_IF([_AC_DO_STDERR($ovs_link2) && {
+	 test -z "$ac_[]_AC_LANG_ABBREV[]_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 AS_TEST_X([conftest$ac_exeext])
+       }],
+      [$3],
+      [echo "$as_me: failed source file 1 of 2 was:" >&5
+sed 's/^/| /' conftest1.$ac_ext >&5
+echo "$as_me: failed source file 2 of 2 was:" >&5
+sed 's/^/| /' conftest2.$ac_ext >&5
+	$4])
+dnl Delete also the IPA/IPO (Inter Procedural Analysis/Optimization)
+dnl information created by the PGI compiler (conftest_ipa8_conftest.oo),
+dnl as it would interfere with the next link command.
+rm -rf conftest.dSYM conftest1.dSYM conftest2.dSYM
+rm -f core conftest.err conftest1.err conftest2.err
+rm -f conftest1.$ac_objext conftest2.$ac_objext conftest*_ipa8_conftest*.oo
+rm -f conftest$ac_exeext
+rm -f m4_ifval([$1], [conftest1.$ac_ext]) m4_ifval([$2], [conftest1.$ac_ext])[]dnl
+])# OVS_LINK2_IFELSE
+
+dnl Defines USE_LINKER_SECTIONS to 1 if the compiler supports putting
+dnl variables in sections with user-defined names and the linker
+dnl automatically defines __start_SECNAME and __stop_SECNAME symbols
+dnl that designate the start and end of the sections.
+AC_DEFUN([OVS_CHECK_LINKER_SECTIONS],
+  [AC_CACHE_CHECK(
+    [for user-defined linker section support],
+    [ovs_cv_use_linker_sections],
+    [OVS_LINK2_IFELSE(
+      [AC_LANG_SOURCE(
+        [int a __attribute__((__section__("mysection"))) = 1;
+         int b __attribute__((__section__("mysection"))) = 2;
+         int c __attribute__((__section__("mysection"))) = 3;])],
+      [AC_LANG_PROGRAM(
+        [#include <stdio.h>
+         extern int __start_mysection;
+         extern int __stop_mysection;],
+        [int n_ints = &__stop_mysection - &__start_mysection;
+         int *i;
+         for (i = &__start_mysection; i < &__start_mysection + n_ints; i++) {
+             printf("%d\n", *i);
+         }])],
+      [ovs_cv_use_linker_sections=yes],
+      [ovs_cv_use_linker_sections=no])])
+   if test $ovs_cv_use_linker_sections = yes; then
+     AC_DEFINE([USE_LINKER_SECTIONS], [1],
+               [Define to 1 if the compiler support putting variables
+                into sections with user-defined names and the linker
+                automatically defines __start_SECNAME and __stop_SECNAME
+                symbols that designate the start and end of the section.])
+   fi])
diff --git a/ofproto/collectors.c b/ofproto/collectors.c
index 0b84c3e..69eed5d 100644
--- a/ofproto/collectors.c
+++ b/ofproto/collectors.c
@@ -26,10 +26,10 @@
 #include "socket-util.h"
 #include "svec.h"
 #include "util.h"
-
-#define THIS_MODULE VLM_collectors
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(collectors)
+
 struct collectors {
     int *fds;                     /* Sockets. */
     size_t n_fds;                 /* Number of sockets. */
diff --git a/ofproto/discovery.c b/ofproto/discovery.c
index 84f092e..008ad62 100644
--- a/ofproto/discovery.c
+++ b/ofproto/discovery.c
@@ -31,10 +31,10 @@
 #include "packets.h"
 #include "status.h"
 #include "stream-ssl.h"
-
-#define THIS_MODULE VLM_discovery
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(discovery)
+
 struct discovery {
     char *dpif_name;
     char *re;
diff --git a/ofproto/fail-open.c b/ofproto/fail-open.c
index a86ee39..04be5ce 100644
--- a/ofproto/fail-open.c
+++ b/ofproto/fail-open.c
@@ -30,10 +30,10 @@
 #include "status.h"
 #include "timeval.h"
 #include "vconn.h"
-
-#define THIS_MODULE VLM_fail_open
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(fail_open)
+
 /*
  * Fail-open mode.
  *
diff --git a/ofproto/in-band.c b/ofproto/in-band.c
index 884cf1d..44bcd72 100644
--- a/ofproto/in-band.c
+++ b/ofproto/in-band.c
@@ -35,10 +35,10 @@
 #include "poll-loop.h"
 #include "status.h"
 #include "timeval.h"
-
-#define THIS_MODULE VLM_in_band
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(in_band)
+
 /* In-band control allows a single network to be used for OpenFlow
  * traffic and other data traffic.  Refer to ovs-vswitchd.conf(5) and 
  * secchan(8) for a description of configuring in-band control.
diff --git a/ofproto/netflow.c b/ofproto/netflow.c
index 67932f0..dd14a8b 100644
--- a/ofproto/netflow.c
+++ b/ofproto/netflow.c
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -30,10 +30,10 @@
 #include "svec.h"
 #include "timeval.h"
 #include "util.h"
+#include "vlog.h"
 #include "xtoxll.h"
 
-#define THIS_MODULE VLM_netflow
-#include "vlog.h"
+VLOG_DEFINE_THIS_MODULE(netflow)
 
 #define NETFLOW_V5_VERSION 5
 
diff --git a/ofproto/ofproto-sflow.c b/ofproto/ofproto-sflow.c
index cc6a693..c74c736 100644
--- a/ofproto/ofproto-sflow.c
+++ b/ofproto/ofproto-sflow.c
@@ -30,10 +30,10 @@
 #include "sflow_api.h"
 #include "socket-util.h"
 #include "timeval.h"
-
-#define THIS_MODULE VLM_sflow
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(sflow)
+
 struct ofproto_sflow_port {
     struct netdev *netdev;      /* Underlying network device, for stats. */
     SFLDataSource_instance dsi; /* sFlow library's notion of port number. */
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index eb62fe8..2a5ad21 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -57,13 +57,13 @@
 #include "timeval.h"
 #include "unixctl.h"
 #include "vconn.h"
+#include "vlog.h"
 #include "xtoxll.h"
 
 #include <linux/types.h>        /* XXX */
 #include <linux/pkt_sched.h>    /* XXX */
 
-#define THIS_MODULE VLM_ofproto
-#include "vlog.h"
+VLOG_DEFINE_THIS_MODULE(ofproto)
 
 #include "sflow_api.h"
 
diff --git a/ofproto/pktbuf.c b/ofproto/pktbuf.c
index b04eb59..49e5c4d 100644
--- a/ofproto/pktbuf.c
+++ b/ofproto/pktbuf.c
@@ -24,10 +24,10 @@
 #include "timeval.h"
 #include "util.h"
 #include "vconn.h"
-
-#define THIS_MODULE VLM_pktbuf
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(pktbuf)
+
 /* Buffers are identified by a 32-bit opaque ID.  We divide the ID
  * into a buffer number (low bits) and a cookie (high bits).  The buffer number
  * is an index into an array of buffers.  The cookie distinguishes between
diff --git a/ofproto/status.c b/ofproto/status.c
index 27dc86c..a8f522d 100644
--- a/ofproto/status.c
+++ b/ofproto/status.c
@@ -33,10 +33,10 @@
 #include "svec.h"
 #include "timeval.h"
 #include "vconn.h"
-
-#define THIS_MODULE VLM_status
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(status)
+
 struct status_category {
     struct list node;
     char *name;
diff --git a/ovsdb/file.c b/ovsdb/file.c
index f0913e9..846f556 100644
--- a/ovsdb/file.c
+++ b/ovsdb/file.c
@@ -36,10 +36,10 @@
 #include "transaction.h"
 #include "uuid.h"
 #include "util.h"
-
-#define THIS_MODULE VLM_ovsdb_file
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(ovsdb_file)
+
 /* Minimum number of milliseconds between database compactions. */
 #define COMPACT_MIN_MSEC        (10 * 60 * 1000) /* 10 minutes. */
 
diff --git a/ovsdb/jsonrpc-server.c b/ovsdb/jsonrpc-server.c
index bc717e4..71a4489 100644
--- a/ovsdb/jsonrpc-server.c
+++ b/ovsdb/jsonrpc-server.c
@@ -34,10 +34,10 @@
 #include "timeval.h"
 #include "transaction.h"
 #include "trigger.h"
-
-#define THIS_MODULE VLM_ovsdb_jsonrpc_server
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(ovsdb_jsonrpc_server)
+
 struct ovsdb_jsonrpc_remote;
 struct ovsdb_jsonrpc_session;
 
diff --git a/ovsdb/log.c b/ovsdb/log.c
index 09b9f1f..b532f7c 100644
--- a/ovsdb/log.c
+++ b/ovsdb/log.c
@@ -33,10 +33,10 @@
 #include "socket-util.h"
 #include "transaction.h"
 #include "util.h"
-
-#define THIS_MODULE VLM_ovsdb_log
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(ovsdb_log)
+
 enum ovsdb_log_mode {
     OVSDB_LOG_READ,
     OVSDB_LOG_WRITE
diff --git a/ovsdb/ovsdb-client.c b/ovsdb/ovsdb-client.c
index fef87d1..14f0759 100644
--- a/ovsdb/ovsdb-client.c
+++ b/ovsdb/ovsdb-client.c
@@ -41,9 +41,9 @@
 #include "table.h"
 #include "timeval.h"
 #include "util.h"
-
 #include "vlog.h"
-#define THIS_MODULE VLM_ovsdb_client
+
+VLOG_DEFINE_THIS_MODULE(ovsdb_client)
 
 /* --format: Output formatting. */
 static enum {
diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c
index 3b71442..7a56707 100644
--- a/ovsdb/ovsdb-server.c
+++ b/ovsdb/ovsdb-server.c
@@ -45,9 +45,9 @@
 #include "trigger.h"
 #include "util.h"
 #include "unixctl.h"
-
 #include "vlog.h"
-#define THIS_MODULE VLM_ovsdb_server
+
+VLOG_DEFINE_THIS_MODULE(ovsdb_server)
 
 #if HAVE_OPENSSL
 /* SSL configuration. */
diff --git a/ovsdb/ovsdb-tool.c b/ovsdb/ovsdb-tool.c
index a68e0f9..8d7e80d 100644
--- a/ovsdb/ovsdb-tool.c
+++ b/ovsdb/ovsdb-tool.c
@@ -34,9 +34,9 @@
 #include "table.h"
 #include "timeval.h"
 #include "util.h"
-
 #include "vlog.h"
-#define THIS_MODULE VLM_ovsdb_tool
+
+VLOG_DEFINE_THIS_MODULE(ovsdb_tool)
 
 /* -m, --more: Verbosity level for "show-log" command output. */
 static int show_log_verbosity;
diff --git a/tests/test-lockfile.c b/tests/test-lockfile.c
index 8b08a66..37daa14 100644
--- a/tests/test-lockfile.c
+++ b/tests/test-lockfile.c
@@ -238,12 +238,13 @@ static const struct test tests[] = {
 int
 main(int argc, char *argv[])
 {
+    extern struct vlog_module VLM_lockfile;
     size_t i;
 
     set_program_name(argv[0]);
     time_init();
     vlog_init();
-    vlog_set_levels(VLM_lockfile, VLF_ANY_FACILITY, VLL_ERR);
+    vlog_set_levels(&VLM_lockfile, VLF_ANY_FACILITY, VLL_ERR);
 
     if (argc != 2) {
         ovs_fatal(0, "exactly one argument required; use \"%s help\" for help",
diff --git a/tests/test-reconnect.c b/tests/test-reconnect.c
index 8bafa00..93b8274 100644
--- a/tests/test-reconnect.c
+++ b/tests/test-reconnect.c
@@ -40,13 +40,14 @@ static void diff_stats(const struct reconnect_stats *old,
 int
 main(void)
 {
+    extern struct vlog_module VLM_reconnect;
     struct reconnect_stats prev;
     unsigned int old_max_tries;
     int old_time;
     char line[128];
 
     vlog_init();
-    vlog_set_levels(VLM_reconnect, VLF_ANY_FACILITY, VLL_EMER);
+    vlog_set_levels(&VLM_reconnect, VLF_ANY_FACILITY, VLL_EMER);
 
     now = 1000;
     reconnect = reconnect_create(now);
diff --git a/tests/test-stp.c b/tests/test-stp.c
index e033cff..3177205 100644
--- a/tests/test-stp.c
+++ b/tests/test-stp.c
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <config.h>
+
 #include "stp.h"
 #include <assert.h>
 #include <ctype.h>
diff --git a/tests/test-vconn.c b/tests/test-vconn.c
index adddc68..01b42a5 100644
--- a/tests/test-vconn.c
+++ b/tests/test-vconn.c
@@ -403,8 +403,8 @@ main(int argc, char *argv[])
     set_program_name(argv[0]);
     time_init();
     vlog_init();
-    vlog_set_levels(VLM_ANY_MODULE, VLF_ANY_FACILITY, VLL_EMER);
-    vlog_set_levels(VLM_ANY_MODULE, VLF_CONSOLE, VLL_DBG);
+    vlog_set_levels(NULL, VLF_ANY_FACILITY, VLL_EMER);
+    vlog_set_levels(NULL, VLF_CONSOLE, VLL_DBG);
     signal(SIGPIPE, SIG_IGN);
 
     time_alarm(10);
diff --git a/utilities/nlmon.c b/utilities/nlmon.c
index d5e743f..c8fe362 100644
--- a/utilities/nlmon.c
+++ b/utilities/nlmon.c
@@ -44,7 +44,7 @@ main(int argc OVS_UNUSED, char *argv[])
     set_program_name(argv[0]);
     time_init();
     vlog_init();
-    vlog_set_levels(VLM_ANY_MODULE, VLF_ANY_FACILITY, VLL_DBG);
+    vlog_set_levels(NULL, VLF_ANY_FACILITY, VLL_DBG);
 
     error = nl_sock_create(NETLINK_ROUTE, RTNLGRP_LINK, 0, 0, &sock);
     if (error) {
diff --git a/utilities/ovs-controller.c b/utilities/ovs-controller.c
index f4358e9..9e2225c 100644
--- a/utilities/ovs-controller.c
+++ b/utilities/ovs-controller.c
@@ -36,9 +36,9 @@
 #include "unixctl.h"
 #include "util.h"
 #include "vconn.h"
-
 #include "vlog.h"
-#define THIS_MODULE VLM_controller
+
+VLOG_DEFINE_THIS_MODULE(controller)
 
 #define MAX_SWITCHES 16
 #define MAX_LISTENERS 16
diff --git a/utilities/ovs-discover.c b/utilities/ovs-discover.c
index 3830e07..038e7fc 100644
--- a/utilities/ovs-discover.c
+++ b/utilities/ovs-discover.c
@@ -33,9 +33,9 @@
 #include "timeval.h"
 #include "unixctl.h"
 #include "util.h"
-
 #include "vlog.h"
-#define THIS_MODULE VLM_ovs_discover
+
+VLOG_DEFINE_THIS_MODULE(ovs_discover)
 
 struct iface {
     const char *name;
diff --git a/utilities/ovs-dpctl.c b/utilities/ovs-dpctl.c
index df76e86..fee4fdb 100644
--- a/utilities/ovs-dpctl.c
+++ b/utilities/ovs-dpctl.c
@@ -40,9 +40,9 @@
 #include "svec.h"
 #include "timeval.h"
 #include "util.h"
-
 #include "vlog.h"
-#define THIS_MODULE VLM_dpctl
+
+VLOG_DEFINE_THIS_MODULE(dpctl)
 
 static const struct command all_commands[];
 
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index c0b7628..37d4b84 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -50,10 +50,10 @@
 #include "timeval.h"
 #include "util.h"
 #include "vconn.h"
+#include "vlog.h"
 #include "xtoxll.h"
 
-#include "vlog.h"
-#define THIS_MODULE VLM_ofctl
+VLOG_DEFINE_THIS_MODULE(ofctl)
 
 #define DEFAULT_IDLE_TIMEOUT 60
 
diff --git a/utilities/ovs-openflowd.c b/utilities/ovs-openflowd.c
index ebfc3c3..f8c04c4 100644
--- a/utilities/ovs-openflowd.c
+++ b/utilities/ovs-openflowd.c
@@ -44,9 +44,9 @@
 #include "unixctl.h"
 #include "util.h"
 #include "vconn.h"
-
 #include "vlog.h"
-#define THIS_MODULE VLM_openflowd
+
+VLOG_DEFINE_THIS_MODULE(openflowd)
 
 /* Settings that may be configured by the user. */
 struct ofsettings {
diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c
index b5ab253..5116305 100644
--- a/utilities/ovs-vsctl.c
+++ b/utilities/ovs-vsctl.c
@@ -41,9 +41,9 @@
 #include "vswitchd/vswitch-idl.h"
 #include "timeval.h"
 #include "util.h"
-
 #include "vlog.h"
-#define THIS_MODULE VLM_vsctl
+
+VLOG_DEFINE_THIS_MODULE(vsctl)
 
 /* vsctl_fatal() also logs the error, so it is preferred in this file. */
 #define ovs_fatal please_use_vsctl_fatal_instead_of_ovs_fatal
@@ -118,6 +118,7 @@ static void set_column(const struct vsctl_table_class *,
 int
 main(int argc, char *argv[])
 {
+    extern struct vlog_module VLM_reconnect;
     struct ovsdb_idl *idl;
     struct vsctl_command *commands;
     size_t n_commands;
@@ -127,8 +128,8 @@ main(int argc, char *argv[])
     signal(SIGPIPE, SIG_IGN);
     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);
     ovsrec_init();
 
     /* Log our arguments.  This is often valuable for debugging systems. */
@@ -203,7 +204,7 @@ parse_options(int argc, char *argv[])
             break;
 
         case OPT_NO_SYSLOG:
-            vlog_set_levels(VLM_vsctl, VLF_SYSLOG, VLL_WARN);
+            vlog_set_levels(&VLM_vsctl, VLF_SYSLOG, VLL_WARN);
             break;
 
         case OPT_NO_WAIT:
@@ -385,7 +386,7 @@ vsctl_fatal(const char *format, ...)
     message = xvasprintf(format, args);
     va_end(args);
 
-    vlog_set_levels(VLM_vsctl, VLF_CONSOLE, VLL_EMER);
+    vlog_set_levels(&VLM_vsctl, VLF_CONSOLE, VLL_EMER);
     VLOG_ERR("%s", message);
     ovs_error(0, "%s", message);
     vsctl_exit(EXIT_FAILURE);
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index e4d9cb7..be0e875 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -63,11 +63,11 @@
 #include "vconn.h"
 #include "vswitchd/vswitch-idl.h"
 #include "xenserver.h"
+#include "vlog.h"
 #include "xtoxll.h"
 #include "sflow_api.h"
 
-#define THIS_MODULE VLM_bridge
-#include "vlog.h"
+VLOG_DEFINE_THIS_MODULE(bridge)
 
 struct dst {
     uint16_t vlan;
diff --git a/vswitchd/ovs-brcompatd.c b/vswitchd/ovs-brcompatd.c
index 7f96028..f8f2639 100644
--- a/vswitchd/ovs-brcompatd.c
+++ b/vswitchd/ovs-brcompatd.c
@@ -54,10 +54,10 @@
 #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? */
@@ -1287,6 +1287,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;
@@ -1296,8 +1297,8 @@ main(int argc, char *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);
diff --git a/vswitchd/ovs-vswitchd.c b/vswitchd/ovs-vswitchd.c
index e2473dc..102d69d 100644
--- a/vswitchd/ovs-vswitchd.c
+++ b/vswitchd/ovs-vswitchd.c
@@ -45,10 +45,10 @@
 #include "unixctl.h"
 #include "util.h"
 #include "vconn.h"
+#include "vlog.h"
 #include "vswitchd/vswitch-idl.h"
 
-#include "vlog.h"
-#define THIS_MODULE VLM_vswitchd
+VLOG_DEFINE_THIS_MODULE(vswitchd)
 
 static unixctl_cb_func ovs_vswitchd_exit;
 
diff --git a/vswitchd/proc-net-compat.c b/vswitchd/proc-net-compat.c
index 106a7c3..6a8f875 100644
--- a/vswitchd/proc-net-compat.c
+++ b/vswitchd/proc-net-compat.c
@@ -31,10 +31,10 @@
 #include "hmap.h"
 #include "shash.h"
 #include "svec.h"
-
-#define THIS_MODULE VLM_proc_net_compat
 #include "vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(proc_net_compat)
+
 /* Netlink socket to bridge compatibility kernel module. */
 static struct nl_sock *brc_sock;
 
diff --git a/vswitchd/xenserver.c b/vswitchd/xenserver.c
index 03c4955..976d716 100644
--- a/vswitchd/xenserver.c
+++ b/vswitchd/xenserver.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009 Nicira Networks
+/* Copyright (c) 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.
@@ -22,9 +22,9 @@
 #include <unistd.h>
 #include "dynamic-string.h"
 #include "process.h"
-
 #include "vlog.h"
-#define THIS_MODULE VLM_xenserver
+
+VLOG_DEFINE_THIS_MODULE(xenserver)
 
 static char *
 read_host_uuid(void)
-- 
1.7.1





More information about the dev mailing list