[ovs-dev] [PATCH] v2 openvswitch: Remove Linux bridge compatibility.

Pravin B Shelar pshelar at nicira.com
Mon Dec 3 18:53:02 UTC 2012


Fixed according to comments from Ben.

v1-v2:
 - Fixed ovs-ctl.8 numbering.
 - Fixed FAQ.
 - removed genetlink.inc
 - Fixed bridge mutual exclusion.

--8<--------------------------cut here-------------------------->8--
Currently brcompat does not on master due to recent
datapath changes. We have decided to remove it as it is
not used very widely.

Signed-off-by: Pravin B Shelar <pshelar at nicira.com>
---
 FAQ                                                |    9 -
 INSTALL.Libvirt                                    |    4 +-
 INSTALL.bridge                                     |   61 --
 Makefile.am                                        |    1 -
 NEWS                                               |    1 +
 README                                             |    8 -
 configure.ac                                       |    1 -
 datapath/Modules.mk                                |    6 -
 datapath/brcompat_main.c                           |  582 ------------
 datapath/compat.h                                  |   20 -
 datapath/datapath.c                                |  115 +--
 datapath/datapath.h                                |    4 -
 datapath/dp_notify.c                               |    6 -
 datapath/dp_sysfs.h                                |   38 -
 datapath/dp_sysfs_dp.c                             |  419 ---------
 datapath/dp_sysfs_if.c                             |  275 ------
 datapath/linux/.gitignore                          |    2 -
 datapath/linux/Makefile.main.in                    |    1 -
 datapath/linux/Modules.mk                          |    9 +-
 datapath/linux/compat/genetlink-brcompat.c         |   10 -
 datapath/linux/compat/genetlink-openvswitch.c      |  147 ++-
 datapath/linux/compat/genetlink.inc                |  148 ---
 datapath/vport-internal_dev.c                      |   11 -
 datapath/vport-netdev.c                            |   21 +-
 datapath/vport.c                                   |   21 +-
 datapath/vport.h                                   |    2 -
 debian/.gitignore                                  |    1 -
 debian/automake.mk                                 |    4 -
 debian/control                                     |   22 -
 debian/copyright.in                                |    1 -
 debian/dkms.conf.in                                |    3 -
 debian/openvswitch-brcompat.install                |    1 -
 debian/openvswitch-brcompat.manpages               |    1 -
 debian/openvswitch-brcompat.postinst               |   17 -
 debian/openvswitch-brcompat.postrm                 |   43 -
 debian/openvswitch-switch.init                     |    8 -
 debian/openvswitch-switch.template                 |    4 -
 include/openvswitch/automake.mk                    |    1 -
 include/openvswitch/brcompat-netlink.h             |  100 ---
 m4/openvswitch.m4                                  |   20 -
 manpages.mk                                        |   12 -
 rhel/etc_init.d_openvswitch                        |    3 -
 rhel/openvswitch-fedora.spec.in                    |    2 -
 rhel/openvswitch-kmod-fedora.spec.in               |    1 -
 rhel/openvswitch.spec.in                           |    2 -
 ...sr_share_openvswitch_scripts_sysconfig.template |    3 -
 utilities/bugtool/ovs-bugtool.in                   |    4 +-
 utilities/ovs-ctl.8                                |   50 +-
 utilities/ovs-ctl.in                               |   41 -
 vswitchd/.gitignore                                |    2 -
 vswitchd/automake.mk                               |   16 +-
 vswitchd/ovs-brcompatd.8.in                        |   46 -
 vswitchd/ovs-brcompatd.c                           |  943 --------------------
 vswitchd/ovs-vswitchd.8.in                         |    1 -
 xenserver/openvswitch-xen.spec.in                  |    6 +-
 55 files changed, 179 insertions(+), 3101 deletions(-)
 delete mode 100644 INSTALL.bridge
 delete mode 100644 datapath/brcompat_main.c
 delete mode 100644 datapath/dp_sysfs.h
 delete mode 100644 datapath/dp_sysfs_dp.c
 delete mode 100644 datapath/dp_sysfs_if.c
 delete mode 100644 datapath/linux/compat/genetlink-brcompat.c
 delete mode 100644 datapath/linux/compat/genetlink.inc
 delete mode 100644 debian/openvswitch-brcompat.install
 delete mode 100644 debian/openvswitch-brcompat.manpages
 delete mode 100755 debian/openvswitch-brcompat.postinst
 delete mode 100755 debian/openvswitch-brcompat.postrm
 delete mode 100644 include/openvswitch/brcompat-netlink.h
 delete mode 100644 vswitchd/ovs-brcompatd.8.in
 delete mode 100644 vswitchd/ovs-brcompatd.c

diff --git a/FAQ b/FAQ
index 9bb9ffa..c8a1689 100644
--- a/FAQ
+++ b/FAQ
@@ -134,15 +134,6 @@ Q: What features are not available in the Open vSwitch kernel datapath
 A: The kernel module in upstream Linux 3.3 and later does not include
    the following features:
 
-       - Bridge compatibility, that is, support for the ovs-brcompatd
-         daemon that (if you enable it) lets "brctl" and other Linux
-         bridge tools transparently work with Open vSwitch instead.
-
-         We do not expect bridge compatibility to ever be available in
-         upstream Linux.  If you need bridge compatibility, use the
-         kernel module from the Open vSwitch distribution instead of the
-         upstream Linux kernel module.
-
        - Tunnel virtual ports, that is, interfaces with type "gre",
          "ipsec_gre", "capwap".  It is possible to create tunnels in
          Linux and attach them to Open vSwitch as system devices.
diff --git a/INSTALL.Libvirt b/INSTALL.Libvirt
index 1bc45d5..fc5575c 100644
--- a/INSTALL.Libvirt
+++ b/INSTALL.Libvirt
@@ -2,9 +2,7 @@
                  ====================================
 
 This document describes how to use Open vSwitch with Libvirt 0.9.11 or
-later. The Open vSwitch support in Libvirt 0.9.11 eliminates the need to
-use OVS Linux Bridge compatibility layer (brcompatd) and interface up/down
-scripts. This document assumes that you followed INSTALL or installed
+later. This document assumes that you followed INSTALL or installed
 Open vSwitch from distribution packaging such as a .deb or .rpm. The Open
 vSwitch support is included by default in Libvirt 0.9.11. Consult
 www.libvirt.org for instructions on how to build the latest Libvirt, if your
diff --git a/INSTALL.bridge b/INSTALL.bridge
deleted file mode 100644
index af20bff..0000000
--- a/INSTALL.bridge
+++ /dev/null
@@ -1,61 +0,0 @@
-              Replacing a Linux Bridge with Open vSwitch
-              ==========================================
-
-This file documents how Open vSwitch may be used as a drop-in
-replacement for a Linux kernel bridge in an environment that includes
-elements that are tightly tied to the Linux bridge tools
-(e.g. "brctl") and architecture.  We recommend directly using the
-management tools provided with Open vSwitch rather than these
-compatibility hooks for environments that are not tightly tied to the
-Linux bridging tools; they are more efficient and better reflect the
-actual operation and status.
-
-Installation Procedure
-----------------------
-
-The procedure below explains how to use the Open vSwitch bridge
-compatibility support.  This procedure is written from the perspective
-of a system administrator manually loading and starting Open vSwitch
-in bridge compatibility mode, but of course in practice one would want
-to update system scripts to follow these steps.  If you do edit your
-system configuration files to start Open vSwitch at boot time, make
-sure that it starts up before any bridge configuration (e.g. before
-any calls to "brctl" or "ifup" of any bridge interfaces), to ensure
-that the Open vSwitch kernel modules are loaded before the Linux
-kernel bridge module.
-
-1. Build, install, and start up the Open vSwitch kernel modules and
-   userspace programs as described in INSTALL.
-
-   It is important to run "make install", because some Open vSwitch
-   programs expect to find files in locations selected at installation
-   time.  The instructions below assume that files are installed in
-   their default locations, under /usr/local.
-
-2. Load the brcompat kernel module (which was built in step 1), e.g.:
-
-      % insmod datapath/linux/brcompat.ko
-
-   (openvswitch.ko should already have been loaded.)
-
-3. Start ovs-brcompatd:
-
-      % ovs-brcompatd --pidfile --detach
-
-   (ovsdb-server and ovs-vswitchd should already have been loaded.)
-
-4. Now you should be able to manage the Open vSwitch using brctl and
-   related tools.  For example, you can create an Open vSwitch bridge,
-   add interfaces to it, then print information about bridges with the
-   commands:
-
-      % brctl addbr br0
-      % brctl addif br0 eth0
-      % brctl addif br0 eth1
-      % brctl show
-
-   Each of these commands actually uses or modifies the Open vSwitch
-   configuration database, then notifies the ovs-vswitchd daemon of
-   the change.  For example, after executing the commands above
-   starting from an empty configuration file, "ovs-vsctl list-ports
-   br0" should show that bridge br0 contains two ports, eth0 and eth1.
diff --git a/Makefile.am b/Makefile.am
index b71ca1f..85f9cf3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -49,7 +49,6 @@ EXTRA_DIST = \
 	INSTALL.RHEL \
 	INSTALL.SSL \
 	INSTALL.XenServer \
-	INSTALL.bridge \
 	INSTALL.userspace \
 	IntegrationGuide \
 	NOTICE \
diff --git a/NEWS b/NEWS
index bb80beb..ac56e3e 100644
--- a/NEWS
+++ b/NEWS
@@ -67,6 +67,7 @@ v1.9.0 - xx xxx xxxx
         - CAPWAP tunnel support.
     - The data in the RARP packets can now be matched in the same way as the
       data in ARP packets.
+    - Bridge compatibility is removed.
 
 v1.8.0 - xx xxx xxxx
 ------------------------
diff --git a/README b/README
index 7c680d4..0959473 100644
--- a/README
+++ b/README
@@ -52,11 +52,6 @@ The main components of this distribution are:
     * ovsdb-server, a lightweight database server that ovs-vswitchd
       queries to obtain its configuration.
 
-    * ovs-brcompatd, a daemon that allows ovs-vswitchd to act as a
-      drop-in replacement for the Linux bridge in many environments, 
-      along with a companion Linux kernel module to intercept bridge 
-      ioctls.
-
     * ovs-dpctl, a tool for configuring the switch kernel module.
 
     * Scripts and specs for building RPMs for Citrix XenServer and Red
@@ -92,9 +87,6 @@ To install Open vSwitch on a regular Linux machine, read INSTALL.
 
 For answers to common questions, read FAQ.
 
-To use Open vSwitch as a drop-in replacement for the Linux bridge,
-read INSTALL.bridge.
-
 To build RPMs for installing Open vSwitch on a Citrix XenServer host
 or resource pool, read INSTALL.XenServer.
 
diff --git a/configure.ac b/configure.ac
index 32940a5..539d5e3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -73,7 +73,6 @@ OVS_CHECK_SOCKET_LIBS
 OVS_CHECK_LINKER_SECTIONS
 OVS_CHECK_XENSERVER_VERSION
 OVS_CHECK_GROFF
-OVS_CHECK_BRCOMPAT
 OVS_CHECK_GNU_MAKE
 OVS_CHECK_CACHE_TIME
 
diff --git a/datapath/Modules.mk b/datapath/Modules.mk
index 24c1075..8753bef 100644
--- a/datapath/Modules.mk
+++ b/datapath/Modules.mk
@@ -1,8 +1,5 @@
 # Some modules should be built and distributed, e.g. openvswitch.
 #
-# Some modules should be distributed but not built, e.g. we do not build
-# brcompat if configured without it
-#
 # Some modules should be built but not distributed, e.g. third-party
 # hwtable modules.
 both_modules = openvswitch
@@ -14,8 +11,6 @@ openvswitch_sources = \
 	checksum.c \
 	datapath.c \
 	dp_notify.c \
-	dp_sysfs_dp.c \
-	dp_sysfs_if.c \
 	flow.c \
 	genl_exec.c \
 	tunnel.c \
@@ -32,7 +27,6 @@ openvswitch_headers = \
 	checksum.h \
 	compat.h \
 	datapath.h \
-	dp_sysfs.h \
 	flow.h \
 	genl_exec.h \
 	tunnel.h \
diff --git a/datapath/brcompat_main.c b/datapath/brcompat_main.c
deleted file mode 100644
index 1671b90..0000000
--- a/datapath/brcompat_main.c
+++ /dev/null
@@ -1,582 +0,0 @@
-/*
- * Copyright (c) 2007-2012 Nicira, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/uaccess.h>
-#include <linux/completion.h>
-#include <linux/etherdevice.h>
-#include <linux/if_bridge.h>
-#include <linux/netdevice.h>
-#include <linux/rtnetlink.h>
-#include <net/genetlink.h>
-
-#include "openvswitch/brcompat-netlink.h"
-#include "datapath.h"
-
-static struct genl_family brc_genl_family;
-static struct genl_multicast_group brc_mc_group;
-
-/* Time to wait for ovs-vswitchd to respond to a datapath action, in
- * jiffies. */
-#define BRC_TIMEOUT (HZ * 5)
-
-/* Mutex to serialize ovs-brcompatd callbacks.  (Some callbacks naturally hold
- * br_ioctl_mutex, others hold rtnl_lock, but we can't take the former
- * ourselves and we don't want to hold the latter over a potentially long
- * period of time.) */
-static DEFINE_MUTEX(brc_serial);
-
-/* Userspace communication. */
-static DEFINE_SPINLOCK(brc_lock);    /* Ensure atomic access to these vars. */
-static DECLARE_COMPLETION(brc_done); /* Userspace signaled operation done? */
-static struct sk_buff *brc_reply;    /* Reply from userspace. */
-static u32 brc_seq;		     /* Sequence number for current op. */
-
-static struct sk_buff *brc_send_command(struct net *,
-					struct sk_buff *,
-					struct nlattr **attrs);
-static int brc_send_simple_command(struct net *, struct sk_buff *);
-
-static struct sk_buff *brc_make_request(int op, const char *bridge,
-					const char *port)
-{
-	struct sk_buff *skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
-	if (!skb)
-		goto error;
-
-	genlmsg_put(skb, 0, 0, &brc_genl_family, 0, op);
-
-	if (bridge && nla_put_string(skb, BRC_GENL_A_DP_NAME, bridge))
-		goto nla_put_failure;
-	if (port && nla_put_string(skb, BRC_GENL_A_PORT_NAME, port))
-		goto nla_put_failure;
-
-	return skb;
-
-nla_put_failure:
-	kfree_skb(skb);
-error:
-	return NULL;
-}
-
-static int brc_send_simple_command(struct net *net, struct sk_buff *request)
-{
-	struct nlattr *attrs[BRC_GENL_A_MAX + 1];
-	struct sk_buff *reply;
-	int error;
-
-	reply = brc_send_command(net, request, attrs);
-	if (IS_ERR(reply))
-		return PTR_ERR(reply);
-
-	error = nla_get_u32(attrs[BRC_GENL_A_ERR_CODE]);
-	kfree_skb(reply);
-	return -error;
-}
-
-static int brc_add_del_bridge(struct net *net, char __user *uname, int add)
-{
-	struct sk_buff *request;
-	char name[IFNAMSIZ];
-
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
-	if (copy_from_user(name, uname, IFNAMSIZ))
-		return -EFAULT;
-
-	name[IFNAMSIZ - 1] = 0;
-	request = brc_make_request(add ? BRC_GENL_C_DP_ADD : BRC_GENL_C_DP_DEL,
-				   name, NULL);
-	if (!request)
-		return -ENOMEM;
-
-	return brc_send_simple_command(net, request);
-}
-
-static int brc_get_indices(struct net *net,
-			   int op, const char *br_name,
-			   int __user *uindices, int n)
-{
-	struct nlattr *attrs[BRC_GENL_A_MAX + 1];
-	struct sk_buff *request, *reply;
-	int *indices;
-	int ret;
-	int len;
-
-	if (n < 0)
-		return -EINVAL;
-	if (n >= 2048)
-		return -ENOMEM;
-
-	request = brc_make_request(op, br_name, NULL);
-	if (!request)
-		return -ENOMEM;
-
-	reply = brc_send_command(net, request, attrs);
-	ret = PTR_ERR(reply);
-	if (IS_ERR(reply))
-		goto exit;
-
-	ret = -nla_get_u32(attrs[BRC_GENL_A_ERR_CODE]);
-	if (ret < 0)
-		goto exit_free_skb;
-
-	ret = -EINVAL;
-	if (!attrs[BRC_GENL_A_IFINDEXES])
-		goto exit_free_skb;
-
-	len = nla_len(attrs[BRC_GENL_A_IFINDEXES]);
-	indices = nla_data(attrs[BRC_GENL_A_IFINDEXES]);
-	if (len % sizeof(int))
-		goto exit_free_skb;
-
-	n = min_t(int, n, len / sizeof(int));
-	ret = copy_to_user(uindices, indices, n * sizeof(int)) ? -EFAULT : n;
-
-exit_free_skb:
-	kfree_skb(reply);
-exit:
-	return ret;
-}
-
-/* Called with br_ioctl_mutex. */
-static int brc_get_bridges(struct net *net, int __user *uindices, int n)
-{
-	return brc_get_indices(net, BRC_GENL_C_GET_BRIDGES, NULL, uindices, n);
-}
-
-/* Legacy deviceless bridge ioctl's.  Called with br_ioctl_mutex. */
-static int old_deviceless(struct net *net, void __user *uarg)
-{
-	unsigned long args[3];
-
-	if (copy_from_user(args, uarg, sizeof(args)))
-		return -EFAULT;
-
-	switch (args[0]) {
-	case BRCTL_GET_BRIDGES:
-		return brc_get_bridges(net, (int __user *)args[1], args[2]);
-
-	case BRCTL_ADD_BRIDGE:
-		return brc_add_del_bridge(net, (void __user *)args[1], 1);
-	case BRCTL_DEL_BRIDGE:
-		return brc_add_del_bridge(net, (void __user *)args[1], 0);
-	}
-
-	return -EOPNOTSUPP;
-}
-
-/* Called with the br_ioctl_mutex. */
-static int
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
-brc_ioctl_deviceless_stub(unsigned int cmd, void __user *uarg)
-{
-	struct net *net = NULL;
-#else
-brc_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *uarg)
-{
-#endif
-	switch (cmd) {
-	case SIOCGIFBR:
-	case SIOCSIFBR:
-		return old_deviceless(net, uarg);
-
-	case SIOCBRADDBR:
-		return brc_add_del_bridge(net, uarg, 1);
-	case SIOCBRDELBR:
-		return brc_add_del_bridge(net, uarg, 0);
-	}
-
-	return -EOPNOTSUPP;
-}
-
-static int brc_add_del_port(struct net_device *dev, int port_ifindex, int add)
-{
-	struct sk_buff *request;
-	struct net_device *port;
-	int err;
-
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
-	port = __dev_get_by_index(dev_net(dev), port_ifindex);
-	if (!port)
-		return -EINVAL;
-
-	/* Save name of dev and port because there's a race between the
-	 * rtnl_unlock() and the brc_send_simple_command(). */
-	request = brc_make_request(add ? BRC_GENL_C_PORT_ADD : BRC_GENL_C_PORT_DEL,
-				   dev->name, port->name);
-	if (!request)
-		return -ENOMEM;
-
-	rtnl_unlock();
-	err = brc_send_simple_command(dev_net(dev), request);
-	rtnl_lock();
-
-	return err;
-}
-
-static int brc_get_bridge_info(struct net_device *dev,
-			       struct __bridge_info __user *ub)
-{
-	struct __bridge_info b;
-
-	memset(&b, 0, sizeof(struct __bridge_info));
-
-	/* First two bytes are the priority, which we should skip.  This comes
-	 * from struct bridge_id in br_private.h, which is unavailable to us.
-	 */
-	memcpy((u8 *)&b.bridge_id + 2, dev->dev_addr, ETH_ALEN);
-	b.stp_enabled = 0;
-
-	if (copy_to_user(ub, &b, sizeof(struct __bridge_info)))
-		return -EFAULT;
-
-	return 0;
-}
-
-static int brc_get_port_list(struct net_device *dev, int __user *uindices,
-			     int num)
-{
-	int retval;
-
-	rtnl_unlock();
-	retval = brc_get_indices(dev_net(dev), BRC_GENL_C_GET_PORTS, dev->name,
-				 uindices, num);
-	rtnl_lock();
-
-	return retval;
-}
-
-/*
- * Format up to a page worth of forwarding table entries
- * userbuf -- where to copy result
- * maxnum  -- maximum number of entries desired
- *            (limited to a page for sanity)
- * offset  -- number of records to skip
- */
-static int brc_get_fdb_entries(struct net_device *dev, void __user *userbuf,
-			       unsigned long maxnum, unsigned long offset)
-{
-	struct nlattr *attrs[BRC_GENL_A_MAX + 1];
-	struct sk_buff *request, *reply;
-	int retval;
-	int len;
-
-	/* Clamp size to PAGE_SIZE, test maxnum to avoid overflow */
-	if (maxnum > PAGE_SIZE/sizeof(struct __fdb_entry))
-		maxnum = PAGE_SIZE/sizeof(struct __fdb_entry);
-
-	request = brc_make_request(BRC_GENL_C_FDB_QUERY, dev->name, NULL);
-	if (!request)
-		return -ENOMEM;
-	if (nla_put_u64(request, BRC_GENL_A_FDB_COUNT, maxnum) ||
-	    nla_put_u64(request, BRC_GENL_A_FDB_SKIP, offset))
-		goto nla_put_failure;
-
-	rtnl_unlock();
-	reply = brc_send_command(dev_net(dev), request, attrs);
-	retval = PTR_ERR(reply);
-	if (IS_ERR(reply))
-		goto exit;
-
-	retval = -nla_get_u32(attrs[BRC_GENL_A_ERR_CODE]);
-	if (retval < 0)
-		goto exit_free_skb;
-
-	retval = -EINVAL;
-	if (!attrs[BRC_GENL_A_FDB_DATA])
-		goto exit_free_skb;
-	len = nla_len(attrs[BRC_GENL_A_FDB_DATA]);
-	if (len % sizeof(struct __fdb_entry) ||
-	    len / sizeof(struct __fdb_entry) > maxnum)
-		goto exit_free_skb;
-
-	retval = len / sizeof(struct __fdb_entry);
-	if (copy_to_user(userbuf, nla_data(attrs[BRC_GENL_A_FDB_DATA]), len))
-		retval = -EFAULT;
-
-exit_free_skb:
-	kfree_skb(reply);
-exit:
-	rtnl_lock();
-	return retval;
-
-nla_put_failure:
-	kfree_skb(request);
-	return -ENOMEM;
-}
-
-/* Legacy ioctl's through SIOCDEVPRIVATE.  Called with rtnl_lock. */
-static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	unsigned long args[4];
-
-	if (copy_from_user(args, rq->ifr_data, sizeof(args)))
-		return -EFAULT;
-
-	switch (args[0]) {
-	case BRCTL_ADD_IF:
-		return brc_add_del_port(dev, args[1], 1);
-	case BRCTL_DEL_IF:
-		return brc_add_del_port(dev, args[1], 0);
-
-	case BRCTL_GET_BRIDGE_INFO:
-		return brc_get_bridge_info(dev, (struct __bridge_info __user *)args[1]);
-
-	case BRCTL_GET_PORT_LIST:
-		return brc_get_port_list(dev, (int __user *)args[1], args[2]);
-
-	case BRCTL_GET_FDB_ENTRIES:
-		return brc_get_fdb_entries(dev, (void __user *)args[1],
-					   args[2], args[3]);
-	}
-
-	return -EOPNOTSUPP;
-}
-
-/* Called with the rtnl_lock. */
-static int brc_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	int err;
-
-	switch (cmd) {
-	case SIOCDEVPRIVATE:
-		err = old_dev_ioctl(dev, rq, cmd);
-		break;
-
-	case SIOCBRADDIF:
-		return brc_add_del_port(dev, rq->ifr_ifindex, 1);
-	case SIOCBRDELIF:
-		return brc_add_del_port(dev, rq->ifr_ifindex, 0);
-
-	default:
-		err = -EOPNOTSUPP;
-		break;
-	}
-
-	return err;
-}
-
-
-static struct genl_family brc_genl_family = {
-	.id = GENL_ID_GENERATE,
-	.hdrsize = 0,
-	.name = BRC_GENL_FAMILY_NAME,
-	.version = 1,
-	.maxattr = BRC_GENL_A_MAX,
-	 SET_NETNSOK
-};
-
-static int brc_genl_query(struct sk_buff *skb, struct genl_info *info)
-{
-	int err = -EINVAL;
-	struct sk_buff *ans_skb;
-	void *data;
-
-	ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-	if (!ans_skb)
-		return -ENOMEM;
-
-	data = genlmsg_put_reply(ans_skb, info, &brc_genl_family,
-				 0, BRC_GENL_C_QUERY_MC);
-	if (data == NULL) {
-		err = -ENOMEM;
-		goto err;
-	}
-	if (nla_put_u32(ans_skb, BRC_GENL_A_MC_GROUP, brc_mc_group.id))
-		goto nla_put_failure;
-
-	genlmsg_end(ans_skb, data);
-	return genlmsg_reply(ans_skb, info);
-
-err:
-nla_put_failure:
-	kfree_skb(ans_skb);
-	return err;
-}
-
-/* Attribute policy: what each attribute may contain.  */
-static struct nla_policy brc_genl_policy[BRC_GENL_A_MAX + 1] = {
-	[BRC_GENL_A_ERR_CODE] = { .type = NLA_U32 },
-	[BRC_GENL_A_FDB_DATA] = { .type = NLA_UNSPEC },
-};
-
-static int brc_genl_dp_result(struct sk_buff *skb, struct genl_info *info)
-{
-	unsigned long int flags;
-	int err;
-
-	if (!info->attrs[BRC_GENL_A_ERR_CODE])
-		return -EINVAL;
-
-	skb = skb_clone(skb, GFP_KERNEL);
-	if (!skb)
-		return -ENOMEM;
-
-	spin_lock_irqsave(&brc_lock, flags);
-	if (brc_seq == info->snd_seq) {
-		brc_seq++;
-
-		kfree_skb(brc_reply);
-		brc_reply = skb;
-
-		complete(&brc_done);
-		err = 0;
-	} else {
-		kfree_skb(skb);
-		err = -ESTALE;
-	}
-	spin_unlock_irqrestore(&brc_lock, flags);
-
-	return err;
-}
-
-static struct genl_ops brc_genl_ops[] = {
-	{ .cmd = BRC_GENL_C_QUERY_MC,
-	  .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privelege. */
-	  .policy = NULL,
-	  .doit = brc_genl_query,
-	},
-	{ .cmd = BRC_GENL_C_DP_RESULT,
-	  .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privelege. */
-	  .policy = brc_genl_policy,
-	  .doit = brc_genl_dp_result,
-	},
-};
-
-static struct sk_buff *brc_send_command(struct net *net,
-					struct sk_buff *request,
-					struct nlattr **attrs)
-{
-	unsigned long int flags;
-	struct sk_buff *reply;
-	int error;
-
-	mutex_lock(&brc_serial);
-
-	/* Increment sequence number first, so that we ignore any replies
-	 * to stale requests. */
-	spin_lock_irqsave(&brc_lock, flags);
-	nlmsg_hdr(request)->nlmsg_seq = ++brc_seq;
-	INIT_COMPLETION(brc_done);
-	spin_unlock_irqrestore(&brc_lock, flags);
-
-	nlmsg_end(request, nlmsg_hdr(request));
-
-	/* Send message. */
-	error = genlmsg_multicast_netns(net, request, 0,
-					brc_mc_group.id, GFP_KERNEL);
-	if (error < 0)
-		goto error;
-
-	/* Wait for reply. */
-	error = -ETIMEDOUT;
-	if (!wait_for_completion_timeout(&brc_done, BRC_TIMEOUT)) {
-		pr_warn("timed out waiting for userspace\n");
-		goto error;
-	}
-
-	/* Grab reply. */
-	spin_lock_irqsave(&brc_lock, flags);
-	reply = brc_reply;
-	brc_reply = NULL;
-	spin_unlock_irqrestore(&brc_lock, flags);
-
-	mutex_unlock(&brc_serial);
-
-	/* Re-parse message.  Can't fail, since it parsed correctly once
-	 * already. */
-	error = nlmsg_parse(nlmsg_hdr(reply), GENL_HDRLEN,
-			    attrs, BRC_GENL_A_MAX, brc_genl_policy);
-	WARN_ON(error);
-
-	return reply;
-
-error:
-	mutex_unlock(&brc_serial);
-	return ERR_PTR(error);
-}
-
-static int __init brc_init(void)
-{
-	int err;
-
-	pr_info("Open vSwitch Bridge Compatibility, built "__DATE__" "__TIME__"\n");
-
-	/* Set the bridge ioctl handler */
-	brioctl_set(brc_ioctl_deviceless_stub);
-
-	/* Set the openvswitch device ioctl handler */
-	ovs_dp_ioctl_hook = brc_dev_ioctl;
-
-	/* Randomize the initial sequence number.  This is not a security
-	 * feature; it only helps avoid crossed wires between userspace and
-	 * the kernel when the module is unloaded and reloaded. */
-	brc_seq = net_random();
-
-	/* Register generic netlink family to communicate changes to
-	 * userspace. */
-	err = genl_register_family_with_ops(&brc_genl_family,
-					    brc_genl_ops, ARRAY_SIZE(brc_genl_ops));
-	if (err)
-		goto error;
-
-	strcpy(brc_mc_group.name, "brcompat");
-	err = genl_register_mc_group(&brc_genl_family, &brc_mc_group);
-	if (err < 0)
-		goto err_unregister;
-
-	return 0;
-
-err_unregister:
-	genl_unregister_family(&brc_genl_family);
-error:
-	pr_emerg("failed to install!\n");
-	return err;
-}
-
-static void brc_cleanup(void)
-{
-	/* Unregister ioctl hooks */
-	ovs_dp_ioctl_hook = NULL;
-	brioctl_set(NULL);
-
-	genl_unregister_family(&brc_genl_family);
-}
-
-module_init(brc_init);
-module_exit(brc_cleanup);
-
-MODULE_DESCRIPTION("Open vSwitch bridge compatibility");
-MODULE_AUTHOR("Nicira, Inc.");
-MODULE_LICENSE("GPL");
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
-/*
- * In kernels 2.6.36 and later, Open vSwitch can safely coexist with
- * the Linux bridge module, but it does not make sense to load both bridge and
- * brcompat, so this prevents it.
- */
-BRIDGE_MUTUAL_EXCLUSION;
-#endif
diff --git a/datapath/compat.h b/datapath/compat.h
index 3b8d577..c7fd225 100644
--- a/datapath/compat.h
+++ b/datapath/compat.h
@@ -53,26 +53,6 @@ static inline void skb_clear_rxhash(struct sk_buff *skb)
 #endif
 }
 
-/*
- * Enforces, mutual exclusion with the Linux bridge module, by declaring and
- * exporting br_should_route_hook.  Because the bridge module also exports the
- * same symbol, the module loader will refuse to load both modules at the same
- * time (e.g. "bridge: exports duplicate symbol br_should_route_hook (owned by
- * openvswitch)").
- *
- * Before Linux 2.6.36, Open vSwitch cannot safely coexist with the Linux
- * bridge module, so openvswitch uses this macro in those versions.  In
- * Linux 2.6.36 and later, Open vSwitch can coexist with the bridge module,
- * but it makes no sense to load both bridge and brcompat, so brcompat uses
- * this macro in those versions.
- *
- * The use of "typeof" here avoids the need to track changes in the type of
- * br_should_route_hook over various kernel versions.
- */
-#define BRIDGE_MUTUAL_EXCLUSION					\
-	typeof(br_should_route_hook) br_should_route_hook;	\
-	EXPORT_SYMBOL(br_should_route_hook)
-
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
 #define GENL_SOCK(net) (genl_sock)
 #define SET_NETNSOK
diff --git a/datapath/datapath.c b/datapath/datapath.c
index f990b73..e2358af 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -71,9 +71,6 @@ static DECLARE_DELAYED_WORK(rehash_flow_wq, rehash_flow_table);
 
 int ovs_net_id __read_mostly;
 
-int (*ovs_dp_ioctl_hook)(struct net_device *dev, struct ifreq *rq, int cmd);
-EXPORT_SYMBOL(ovs_dp_ioctl_hook);
-
 /**
  * DOC: Locking:
  *
@@ -141,101 +138,6 @@ static int get_dpifindex(struct datapath *dp)
 	return ifindex;
 }
 
-static size_t br_nlmsg_size(void)
-{
-	return NLMSG_ALIGN(sizeof(struct ifinfomsg))
-	       + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
-	       + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
-	       + nla_total_size(4) /* IFLA_MASTER */
-	       + nla_total_size(4) /* IFLA_MTU */
-	       + nla_total_size(1); /* IFLA_OPERSTATE */
-}
-
-/* Caller must hold RTNL lock. */
-static int dp_fill_ifinfo(struct sk_buff *skb,
-			  const struct vport *port,
-			  int event, unsigned int flags)
-{
-	struct datapath *dp = port->dp;
-	struct ifinfomsg *hdr;
-	struct nlmsghdr *nlh;
-
-	if (!port->ops->get_ifindex)
-		return -ENODEV;
-
-	nlh = nlmsg_put(skb, 0, 0, event, sizeof(*hdr), flags);
-	if (nlh == NULL)
-		return -EMSGSIZE;
-
-	hdr = nlmsg_data(nlh);
-	hdr->ifi_family = AF_BRIDGE;
-	hdr->__ifi_pad = 0;
-	hdr->ifi_type = ARPHRD_ETHER;
-	hdr->ifi_index = port->ops->get_ifindex(port);
-	hdr->ifi_flags = port->ops->get_dev_flags(port);
-	hdr->ifi_change = 0;
-
-	if (nla_put_string(skb, IFLA_IFNAME, port->ops->get_name(port)) ||
-	    nla_put_u32(skb, IFLA_MASTER, get_dpifindex(dp)) ||
-	    nla_put_u32(skb, IFLA_MTU, port->ops->get_mtu(port)) ||
-#ifdef IFLA_OPERSTATE
-	    nla_put_u8(skb, IFLA_OPERSTATE,
-		       port->ops->is_running(port) ?
-				port->ops->get_operstate(port) :
-				IF_OPER_DOWN) ||
-#endif
-	    nla_put(skb, IFLA_ADDRESS, ETH_ALEN, port->ops->get_addr(port)))
-		goto nla_put_failure;
-
-	return nlmsg_end(skb, nlh);
-
-nla_put_failure:
-	nlmsg_cancel(skb, nlh);
-	return -EMSGSIZE;
-}
-
-/* Caller must hold RTNL lock. */
-static void dp_ifinfo_notify(int event, struct vport *port)
-{
-	struct sk_buff *skb;
-	int err;
-
-	skb = nlmsg_new(br_nlmsg_size(), GFP_KERNEL);
-	if (!skb) {
-		err = -ENOBUFS;
-		goto err;
-	}
-
-	err = dp_fill_ifinfo(skb, port, event, 0);
-	if (err < 0) {
-		if (err == -ENODEV) {
-			goto out;
-		} else {
-			/* -EMSGSIZE implies BUG in br_nlmsg_size() */
-			WARN_ON(err == -EMSGSIZE);
-			goto err;
-		}
-	}
-
-	rtnl_notify(skb, ovs_dp_get_net(port->dp), 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
-
-	return;
-err:
-	rtnl_set_sk_err(ovs_dp_get_net(port->dp), RTNLGRP_LINK, err);
-out:
-	kfree_skb(skb);
-}
-
-static void release_dp(struct kobject *kobj)
-{
-	struct datapath *dp = container_of(kobj, struct datapath, ifobj);
-	kfree(dp);
-}
-
-static struct kobj_type dp_ktype = {
-	.release = release_dp
-};
-
 static void destroy_dp_rcu(struct rcu_head *rcu)
 {
 	struct datapath *dp = container_of(rcu, struct datapath, rcu);
@@ -244,7 +146,7 @@ static void destroy_dp_rcu(struct rcu_head *rcu)
 	free_percpu(dp->stats_percpu);
 	release_net(ovs_dp_get_net(dp));
 	kfree(dp->ports);
-	kobject_put(&dp->ifobj);
+	kfree(dp);
 }
 
 static struct hlist_head *vport_hash_bucket(const struct datapath *dp,
@@ -278,7 +180,6 @@ static struct vport *new_vport(const struct vport_parms *parms)
 		struct hlist_head *head = vport_hash_bucket(dp, vport->port_no);
 
 		hlist_add_head_rcu(&vport->dp_hash_node, head);
-		dp_ifinfo_notify(RTM_NEWLINK, vport);
 	}
 	return vport;
 }
@@ -288,11 +189,6 @@ void ovs_dp_detach_port(struct vport *p)
 {
 	ASSERT_RTNL();
 
-	if (p->port_no != OVSP_LOCAL)
-		ovs_dp_sysfs_del_if(p);
-
-	dp_ifinfo_notify(RTM_DELLINK, p);
-
 	/* First drop references to device. */
 	hlist_del_rcu(&p->dp_hash_node);
 
@@ -1430,11 +1326,6 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
 	if (dp == NULL)
 		goto err_unlock_rtnl;
 
-	/* Initialize kobject for bridge.  This will be added as
-	 * /sys/class/net/<devname>/brif later, if sysfs is enabled. */
-	dp->ifobj.kset = NULL;
-	kobject_init(&dp->ifobj, &dp_ktype);
-
 	ovs_dp_set_net(dp, hold_net(sock_net(skb->sk)));
 
 	/* Allocate table. */
@@ -1484,7 +1375,6 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
 
 	ovs_net = net_generic(ovs_dp_get_net(dp), ovs_net_id);
 	list_add_tail(&dp->list_node, &ovs_net->dps);
-	ovs_dp_sysfs_add_dp(dp);
 
 	rtnl_unlock();
 
@@ -1526,7 +1416,6 @@ static void __dp_destroy(struct datapath *dp)
 				ovs_dp_detach_port(vport);
 	}
 
-	ovs_dp_sysfs_del_dp(dp);
 	list_del(&dp->list_node);
 	ovs_dp_detach_port(ovs_vport_rtnl(dp, OVSP_LOCAL));
 
@@ -1872,8 +1761,6 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
 	if (IS_ERR(vport))
 		goto exit_unlock;
 
-	ovs_dp_sysfs_add_if(vport);
-
 	err = change_vport(vport, a);
 	if (!err) {
 		reply = ovs_vport_cmd_build_info(vport, info->snd_pid,
diff --git a/datapath/datapath.h b/datapath/datapath.h
index c5df12d..7cc7643 100644
--- a/datapath/datapath.h
+++ b/datapath/datapath.h
@@ -28,7 +28,6 @@
 
 #include "checksum.h"
 #include "compat.h"
-#include "dp_sysfs.h"
 #include "flow.h"
 #include "tunnel.h"
 #include "vlan.h"
@@ -62,7 +61,6 @@ struct dp_stats_percpu {
  * struct datapath - datapath for flow-based packet switching
  * @rcu: RCU callback head for deferred destruction.
  * @list_node: Element in global 'dps' list.
- * @ifobj: Represents /sys/class/net/<devname>/brif.  Protected by RTNL.
  * @n_flows: Number of flows currently in flow table.
  * @table: Current flow table.  Protected by genl_lock and RCU.
  * @ports: Hash table for ports.  %OVSP_LOCAL port always exists.  Protected by
@@ -76,7 +74,6 @@ struct dp_stats_percpu {
 struct datapath {
 	struct rcu_head rcu;
 	struct list_head list_node;
-	struct kobject ifobj;
 
 	/* Flow table. */
 	struct flow_table __rcu *table;
@@ -181,7 +178,6 @@ static inline struct vport *ovs_vport_rtnl(const struct datapath *dp, int port_n
 
 extern struct notifier_block ovs_dp_device_notifier;
 extern struct genl_multicast_group ovs_dp_vport_multicast_group;
-extern int (*ovs_dp_ioctl_hook)(struct net_device *dev, struct ifreq *rq, int cmd);
 
 void ovs_dp_process_received_packet(struct vport *, struct sk_buff *);
 void ovs_dp_detach_port(struct vport *);
diff --git a/datapath/dp_notify.c b/datapath/dp_notify.c
index 13085d6..c9eeafe 100644
--- a/datapath/dp_notify.c
+++ b/datapath/dp_notify.c
@@ -59,12 +59,6 @@ static int dp_device_event(struct notifier_block *unused, unsigned long event,
 		}
 		break;
 
-	case NETDEV_CHANGENAME:
-		if (vport->port_no != OVSP_LOCAL) {
-			ovs_dp_sysfs_del_if(vport);
-			ovs_dp_sysfs_add_if(vport);
-		}
-		break;
 	}
 
 	return NOTIFY_DONE;
diff --git a/datapath/dp_sysfs.h b/datapath/dp_sysfs.h
deleted file mode 100644
index 526b0a1..0000000
--- a/datapath/dp_sysfs.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2007-2011 Nicira, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- */
-
-#ifndef DP_SYSFS_H
-#define DP_SYSFS_H 1
-
-struct datapath;
-struct vport;
-
-/* dp_sysfs_dp.c */
-int ovs_dp_sysfs_add_dp(struct datapath *dp);
-int ovs_dp_sysfs_del_dp(struct datapath *dp);
-
-/* dp_sysfs_if.c */
-int ovs_dp_sysfs_add_if(struct vport *p);
-int ovs_dp_sysfs_del_if(struct vport *p);
-
-#ifdef CONFIG_SYSFS
-extern struct sysfs_ops ovs_brport_sysfs_ops;
-#endif
-
-#endif /* dp_sysfs.h */
-
diff --git a/datapath/dp_sysfs_dp.c b/datapath/dp_sysfs_dp.c
deleted file mode 100644
index 3ecacd7..0000000
--- a/datapath/dp_sysfs_dp.c
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * Copyright (c) 2007-2012 Nicira, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/version.h>
-
-/*
- *	Sysfs attributes of bridge for Open vSwitch
- *
- *  This has been shamelessly copied from the kernel sources.
- */
-
-#include <linux/capability.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/if_bridge.h>
-#include <linux/rtnetlink.h>
-#include <linux/version.h>
-
-#include "dp_sysfs.h"
-#include "datapath.h"
-#include "vport-internal_dev.h"
-
-#ifdef CONFIG_SYSFS
-
-/* Hack to attempt to build on more platforms. */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)
-#define INTERNAL_DEVICE_ATTR CLASS_DEVICE_ATTR
-#define DEVICE_PARAMS struct class_device *d
-#define DEVICE_ARGS d
-#define DEV_ATTR(NAME) class_device_attr_##NAME
-#else
-#define INTERNAL_DEVICE_ATTR DEVICE_ATTR
-#define DEVICE_PARAMS struct device *d, struct device_attribute *attr
-#define DEVICE_ARGS d, attr
-#define DEV_ATTR(NAME) dev_attr_##NAME
-#endif
-
-static struct datapath *sysfs_get_dp(struct net_device *netdev)
-{
-	struct vport *vport = ovs_internal_dev_get_vport(netdev);
-	return vport ? vport->dp : NULL;
-}
-/*
- * Common code for storing bridge parameters.
- */
-static ssize_t store_bridge_parm(DEVICE_PARAMS,
-				 const char *buf, size_t len,
-				 void (*set)(struct datapath *, unsigned long))
-{
-	char *endp;
-	unsigned long val;
-	ssize_t result = len;
-
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
-	val = simple_strtoul(buf, &endp, 0);
-	if (endp == buf)
-		return -EINVAL;
-
-	/* xxx We use a default value of 0 for all fields.  If the caller is
-	 * xxx attempting to set the value to our default, just silently
-	 * xxx ignore the request.
-	 */
-	if (val != 0) {
-		struct datapath *dp;
-
-		rcu_read_lock();
-
-		dp = sysfs_get_dp(to_net_dev(d));
-		if (dp)
-			pr_warning("%s: xxx writing dp parms not supported yet!\n",
-			       ovs_dp_name(dp));
-		else
-			result = -ENODEV;
-
-		rcu_read_unlock();
-	}
-
-	return result;
-}
-
-
-static ssize_t show_forward_delay(DEVICE_PARAMS, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-
-static void set_forward_delay(struct datapath *dp, unsigned long val)
-{
-	pr_info("%s: xxx attempt to set_forward_delay()\n", ovs_dp_name(dp));
-}
-
-static ssize_t store_forward_delay(DEVICE_PARAMS,
-				   const char *buf, size_t len)
-{
-	return store_bridge_parm(DEVICE_ARGS, buf, len, set_forward_delay);
-}
-static INTERNAL_DEVICE_ATTR(forward_delay, S_IRUGO | S_IWUSR,
-		   show_forward_delay, store_forward_delay);
-
-static ssize_t show_hello_time(DEVICE_PARAMS, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-
-static void set_hello_time(struct datapath *dp, unsigned long val)
-{
-	pr_info("%s: xxx attempt to set_hello_time()\n", ovs_dp_name(dp));
-}
-
-static ssize_t store_hello_time(DEVICE_PARAMS,
-				const char *buf,
-				size_t len)
-{
-	return store_bridge_parm(DEVICE_ARGS, buf, len, set_hello_time);
-}
-static INTERNAL_DEVICE_ATTR(hello_time, S_IRUGO | S_IWUSR, show_hello_time,
-		   store_hello_time);
-
-static ssize_t show_max_age(DEVICE_PARAMS, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-
-static void set_max_age(struct datapath *dp, unsigned long val)
-{
-	pr_info("%s: xxx attempt to set_max_age()\n", ovs_dp_name(dp));
-}
-
-static ssize_t store_max_age(DEVICE_PARAMS,
-			     const char *buf, size_t len)
-{
-	return store_bridge_parm(DEVICE_ARGS, buf, len, set_max_age);
-}
-static INTERNAL_DEVICE_ATTR(max_age, S_IRUGO | S_IWUSR, show_max_age, store_max_age);
-
-static ssize_t show_ageing_time(DEVICE_PARAMS, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-
-static void set_ageing_time(struct datapath *dp, unsigned long val)
-{
-	pr_info("%s: xxx attempt to set_ageing_time()\n", ovs_dp_name(dp));
-}
-
-static ssize_t store_ageing_time(DEVICE_PARAMS,
-				 const char *buf, size_t len)
-{
-	return store_bridge_parm(DEVICE_ARGS, buf, len, set_ageing_time);
-}
-static INTERNAL_DEVICE_ATTR(ageing_time, S_IRUGO | S_IWUSR, show_ageing_time,
-		   store_ageing_time);
-
-static ssize_t show_stp_state(DEVICE_PARAMS, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-
-
-static ssize_t store_stp_state(DEVICE_PARAMS,
-			       const char *buf,
-			       size_t len)
-{
-	struct datapath *dp;
-	ssize_t result = len;
-
-	rcu_read_lock();
-
-	dp = sysfs_get_dp(to_net_dev(d));
-	if (dp)
-		pr_info("%s: xxx attempt to set_stp_state()\n", ovs_dp_name(dp));
-	else
-		result = -ENODEV;
-
-	rcu_read_unlock();
-
-	return result;
-}
-static INTERNAL_DEVICE_ATTR(stp_state, S_IRUGO | S_IWUSR, show_stp_state,
-		   store_stp_state);
-
-static ssize_t show_priority(DEVICE_PARAMS, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-
-static void set_priority(struct datapath *dp, unsigned long val)
-{
-	pr_info("%s: xxx attempt to set_priority()\n", ovs_dp_name(dp));
-}
-
-static ssize_t store_priority(DEVICE_PARAMS,
-			       const char *buf, size_t len)
-{
-	return store_bridge_parm(DEVICE_ARGS, buf, len, set_priority);
-}
-static INTERNAL_DEVICE_ATTR(priority, S_IRUGO | S_IWUSR, show_priority, store_priority);
-
-static ssize_t show_root_id(DEVICE_PARAMS, char *buf)
-{
-	return sprintf(buf, "0000.010203040506\n");
-}
-static INTERNAL_DEVICE_ATTR(root_id, S_IRUGO, show_root_id, NULL);
-
-static ssize_t show_bridge_id(DEVICE_PARAMS, char *buf)
-{
-	struct vport *vport;
-	ssize_t result;
-
-	rcu_read_lock();
-
-	vport = ovs_internal_dev_get_vport(to_net_dev(d));
-	if (vport) {
-		const unsigned char *addr;
-
-		addr = vport->ops->get_addr(vport);
-		result = sprintf(buf, "%.2x%.2x.%.2x%.2x%.2x%.2x%.2x%.2x\n",
-				 0, 0, addr[0], addr[1], addr[2], addr[3],
-				 addr[4], addr[5]);
-	} else
-		result = -ENODEV;
-
-	rcu_read_unlock();
-
-	return result;
-}
-static INTERNAL_DEVICE_ATTR(bridge_id, S_IRUGO, show_bridge_id, NULL);
-
-static ssize_t show_root_port(DEVICE_PARAMS, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-static INTERNAL_DEVICE_ATTR(root_port, S_IRUGO, show_root_port, NULL);
-
-static ssize_t show_root_path_cost(DEVICE_PARAMS, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-static INTERNAL_DEVICE_ATTR(root_path_cost, S_IRUGO, show_root_path_cost, NULL);
-
-static ssize_t show_topology_change(DEVICE_PARAMS, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-static INTERNAL_DEVICE_ATTR(topology_change, S_IRUGO, show_topology_change, NULL);
-
-static ssize_t show_topology_change_detected(DEVICE_PARAMS, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-static INTERNAL_DEVICE_ATTR(topology_change_detected, S_IRUGO,
-		   show_topology_change_detected, NULL);
-
-static ssize_t show_hello_timer(DEVICE_PARAMS, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-static INTERNAL_DEVICE_ATTR(hello_timer, S_IRUGO, show_hello_timer, NULL);
-
-static ssize_t show_tcn_timer(DEVICE_PARAMS, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-static INTERNAL_DEVICE_ATTR(tcn_timer, S_IRUGO, show_tcn_timer, NULL);
-
-static ssize_t show_topology_change_timer(DEVICE_PARAMS, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-static INTERNAL_DEVICE_ATTR(topology_change_timer, S_IRUGO, show_topology_change_timer,
-		   NULL);
-
-static ssize_t show_gc_timer(DEVICE_PARAMS, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-static INTERNAL_DEVICE_ATTR(gc_timer, S_IRUGO, show_gc_timer, NULL);
-
-static ssize_t show_group_addr(DEVICE_PARAMS, char *buf)
-{
-	return sprintf(buf, "00:01:02:03:04:05\n");
-}
-
-static ssize_t store_group_addr(DEVICE_PARAMS,
-				const char *buf, size_t len)
-{
-	struct datapath *dp;
-	ssize_t result = len;
-
-	rcu_read_lock();
-
-	dp = sysfs_get_dp(to_net_dev(d));
-	if (dp)
-		pr_info("%s: xxx attempt to store_group_addr()\n",
-		       ovs_dp_name(dp));
-	else
-		result = -ENODEV;
-
-	rcu_read_unlock();
-
-	return result;
-}
-
-static INTERNAL_DEVICE_ATTR(group_addr, S_IRUGO | S_IWUSR,
-		   show_group_addr, store_group_addr);
-
-static struct attribute *bridge_attrs[] = {
-	&DEV_ATTR(forward_delay).attr,
-	&DEV_ATTR(hello_time).attr,
-	&DEV_ATTR(max_age).attr,
-	&DEV_ATTR(ageing_time).attr,
-	&DEV_ATTR(stp_state).attr,
-	&DEV_ATTR(priority).attr,
-	&DEV_ATTR(bridge_id).attr,
-	&DEV_ATTR(root_id).attr,
-	&DEV_ATTR(root_path_cost).attr,
-	&DEV_ATTR(root_port).attr,
-	&DEV_ATTR(topology_change).attr,
-	&DEV_ATTR(topology_change_detected).attr,
-	&DEV_ATTR(hello_timer).attr,
-	&DEV_ATTR(tcn_timer).attr,
-	&DEV_ATTR(topology_change_timer).attr,
-	&DEV_ATTR(gc_timer).attr,
-	&DEV_ATTR(group_addr).attr,
-	NULL
-};
-
-static struct attribute_group bridge_group = {
-	.name = SYSFS_BRIDGE_ATTR, /* "bridge" */
-	.attrs = bridge_attrs,
-};
-
-/*
- * Add entries in sysfs onto the existing network class device
- * for the bridge.
- *   Adds a attribute group "bridge" containing tuning parameters.
- *   Sub directory to hold links to interfaces.
- *
- * Note: the ifobj exists only to be a subdirectory
- *   to hold links.  The ifobj exists in the same data structure
- *   as its parent the bridge so reference counting works.
- */
-int ovs_dp_sysfs_add_dp(struct datapath *dp)
-{
-	struct vport *vport = ovs_vport_rtnl(dp, OVSP_LOCAL);
-	struct kobject *kobj = vport->ops->get_kobj(vport);
-	int err;
-
-#ifdef CONFIG_NET_NS
-	/* Due to bug in 2.6.32 kernel, sysfs_create_group() could panic
-	 * in other namespace than init_net. Following check is to avoid it. */
-	if (!kobj->sd)
-		return -ENOENT;
-#endif
-	/* Create /sys/class/net/<devname>/bridge directory. */
-	err = sysfs_create_group(kobj, &bridge_group);
-	if (err) {
-		pr_info("%s: can't create group %s/%s\n",
-			__func__, ovs_dp_name(dp), bridge_group.name);
-		goto out1;
-	}
-
-	/* Create /sys/class/net/<devname>/brif directory. */
-	err = kobject_add(&dp->ifobj, kobj, SYSFS_BRIDGE_PORT_SUBDIR);
-	if (err) {
-		pr_info("%s: can't add kobject (directory) %s/%s\n",
-			__func__, ovs_dp_name(dp), kobject_name(&dp->ifobj));
-		goto out2;
-	}
-	kobject_uevent(&dp->ifobj, KOBJ_ADD);
-	return 0;
-
- out2:
-	sysfs_remove_group(kobj, &bridge_group);
- out1:
-	return err;
-}
-
-int ovs_dp_sysfs_del_dp(struct datapath *dp)
-{
-	struct vport *vport = ovs_vport_rtnl(dp, OVSP_LOCAL);
-	struct kobject *kobj = vport->ops->get_kobj(vport);
-
-#ifdef CONFIG_NET_NS
-	if (!kobj->sd)
-		return 0;
-#endif
-
-	kobject_del(&dp->ifobj);
-	sysfs_remove_group(kobj, &bridge_group);
-
-	return 0;
-}
-#else /* !CONFIG_SYSFS */
-int ovs_dp_sysfs_add_dp(struct datapath *dp) { return 0; }
-int ovs_dp_sysfs_del_dp(struct datapath *dp) { return 0; }
-int dp_sysfs_add_if(struct vport *p) { return 0; }
-int dp_sysfs_del_if(struct vport *p) { return 0; }
-#endif /* !CONFIG_SYSFS */
diff --git a/datapath/dp_sysfs_if.c b/datapath/dp_sysfs_if.c
deleted file mode 100644
index 219a260..0000000
--- a/datapath/dp_sysfs_if.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright (c) 2007-2012 Nicira, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/capability.h>
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/if_bridge.h>
-#include <linux/rtnetlink.h>
-
-#include "datapath.h"
-#include "dp_sysfs.h"
-#include "vport.h"
-
-#ifdef CONFIG_SYSFS
-
-struct brport_attribute {
-	struct attribute	attr;
-	ssize_t (*show)(struct vport *, char *);
-	ssize_t (*store)(struct vport *, unsigned long);
-};
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
-#define BRPORT_ATTR(_name, _mode, _show, _store)		\
-struct brport_attribute brport_attr_##_name = {		        \
-	.attr = {.name = __stringify(_name),			\
-		 .mode = _mode },				\
-	.show	= _show,					\
-	.store	= _store,					\
-};
-#else
-#define BRPORT_ATTR(_name, _mode, _show, _store)		\
-struct brport_attribute brport_attr_##_name = {			\
-	.attr = {.name = __stringify(_name),			\
-		 .mode = _mode,					\
-		 .owner = THIS_MODULE, },			\
-	.show	= _show,					\
-	.store	= _store,					\
-};
-#endif
-
-static ssize_t show_path_cost(struct vport *p, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-static ssize_t store_path_cost(struct vport *p, unsigned long v)
-{
-	return 0;
-}
-static BRPORT_ATTR(path_cost, S_IRUGO | S_IWUSR,
-		   show_path_cost, store_path_cost);
-
-static ssize_t show_priority(struct vport *p, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-static ssize_t store_priority(struct vport *p, unsigned long v)
-{
-	return 0;
-}
-static BRPORT_ATTR(priority, S_IRUGO | S_IWUSR,
-			 show_priority, store_priority);
-
-static ssize_t show_designated_root(struct vport *p, char *buf)
-{
-	return sprintf(buf, "0000.010203040506\n");
-}
-static BRPORT_ATTR(designated_root, S_IRUGO, show_designated_root, NULL);
-
-static ssize_t show_designated_bridge(struct vport *p, char *buf)
-{
-	return sprintf(buf, "0000.060504030201\n");
-}
-static BRPORT_ATTR(designated_bridge, S_IRUGO, show_designated_bridge, NULL);
-
-static ssize_t show_designated_port(struct vport *p, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-static BRPORT_ATTR(designated_port, S_IRUGO, show_designated_port, NULL);
-
-static ssize_t show_designated_cost(struct vport *p, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-static BRPORT_ATTR(designated_cost, S_IRUGO, show_designated_cost, NULL);
-
-static ssize_t show_port_id(struct vport *p, char *buf)
-{
-	return sprintf(buf, "0x%x\n", 0);
-}
-static BRPORT_ATTR(port_id, S_IRUGO, show_port_id, NULL);
-
-static ssize_t show_port_no(struct vport *p, char *buf)
-{
-	return sprintf(buf, "0x%x\n", p->port_no);
-}
-
-static BRPORT_ATTR(port_no, S_IRUGO, show_port_no, NULL);
-
-static ssize_t show_change_ack(struct vport *p, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-static BRPORT_ATTR(change_ack, S_IRUGO, show_change_ack, NULL);
-
-static ssize_t show_config_pending(struct vport *p, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-static BRPORT_ATTR(config_pending, S_IRUGO, show_config_pending, NULL);
-
-static ssize_t show_port_state(struct vport *p, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-static BRPORT_ATTR(state, S_IRUGO, show_port_state, NULL);
-
-static ssize_t show_message_age_timer(struct vport *p, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-static BRPORT_ATTR(message_age_timer, S_IRUGO, show_message_age_timer, NULL);
-
-static ssize_t show_forward_delay_timer(struct vport *p, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-static BRPORT_ATTR(forward_delay_timer, S_IRUGO, show_forward_delay_timer, NULL);
-
-static ssize_t show_hold_timer(struct vport *p, char *buf)
-{
-	return sprintf(buf, "%d\n", 0);
-}
-static BRPORT_ATTR(hold_timer, S_IRUGO, show_hold_timer, NULL);
-
-static struct brport_attribute *brport_attrs[] = {
-	&brport_attr_path_cost,
-	&brport_attr_priority,
-	&brport_attr_port_id,
-	&brport_attr_port_no,
-	&brport_attr_designated_root,
-	&brport_attr_designated_bridge,
-	&brport_attr_designated_port,
-	&brport_attr_designated_cost,
-	&brport_attr_state,
-	&brport_attr_change_ack,
-	&brport_attr_config_pending,
-	&brport_attr_message_age_timer,
-	&brport_attr_forward_delay_timer,
-	&brport_attr_hold_timer,
-	NULL
-};
-
-#define to_vport_attr(_at) container_of(_at, struct brport_attribute, attr)
-#define to_vport(obj)	container_of(obj, struct vport, kobj)
-
-static ssize_t brport_show(struct kobject *kobj,
-			   struct attribute *attr, char *buf)
-{
-	struct brport_attribute *brport_attr = to_vport_attr(attr);
-	struct vport *p = to_vport(kobj);
-
-	return brport_attr->show(p, buf);
-}
-
-static ssize_t brport_store(struct kobject *kobj,
-			    struct attribute *attr,
-			    const char *buf, size_t count)
-{
-	struct vport *p = to_vport(kobj);
-	ssize_t ret = -EINVAL;
-
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
-	pr_warning("%s: xxx writing port parms not supported yet!\n",
-		   ovs_dp_name(p->dp));
-
-	return ret;
-}
-
-struct sysfs_ops ovs_brport_sysfs_ops = {
-	.show = brport_show,
-	.store = brport_store,
-};
-
-/*
- * Add sysfs entries to ethernet device added to a bridge.
- * Creates a brport subdirectory with bridge attributes.
- * Puts symlink in bridge's brport subdirectory
- */
-int ovs_dp_sysfs_add_if(struct vport *p)
-{
-	struct datapath *dp = p->dp;
-	struct vport *local_port = ovs_vport_rtnl(dp, OVSP_LOCAL);
-	struct brport_attribute **a;
-	int err;
-
-	/* Create /sys/class/net/<devname>/brport directory. */
-	if (!p->ops->get_kobj)
-		return -ENOENT;
-
-#ifdef CONFIG_NET_NS
-	/* Due to bug in 2.6.32 kernel, sysfs_create_group() could panic
-	 * in other namespace than init_net. Following check is to avoid it. */
-
-	if (!p->kobj.sd)
-		return -ENOENT;
-#endif
-
-	err = kobject_add(&p->kobj, p->ops->get_kobj(p),
-			  SYSFS_BRIDGE_PORT_ATTR);
-	if (err)
-		goto err;
-
-	/* Create symlink from /sys/class/net/<devname>/brport/bridge to
-	 * /sys/class/net/<bridgename>. */
-	err = sysfs_create_link(&p->kobj, local_port->ops->get_kobj(local_port),
-		SYSFS_BRIDGE_PORT_LINK); /* "bridge" */
-	if (err)
-		goto err_del;
-
-	/* Populate /sys/class/net/<devname>/brport directory with files. */
-	for (a = brport_attrs; *a; ++a) {
-		err = sysfs_create_file(&p->kobj, &((*a)->attr));
-		if (err)
-			goto err_del;
-	}
-
-	/* Create symlink from /sys/class/net/<bridgename>/brif/<devname> to
-	 * /sys/class/net/<devname>/brport.  */
-	err = sysfs_create_link(&dp->ifobj, &p->kobj, p->ops->get_name(p));
-	if (err)
-		goto err_del;
-	strcpy(p->linkname, p->ops->get_name(p));
-
-	kobject_uevent(&p->kobj, KOBJ_ADD);
-
-	return 0;
-
-err_del:
-	kobject_del(&p->kobj);
-err:
-	p->linkname[0] = 0;
-	return err;
-}
-
-int ovs_dp_sysfs_del_if(struct vport *p)
-{
-	if (p->linkname[0]) {
-		sysfs_remove_link(&p->dp->ifobj, p->linkname);
-		kobject_uevent(&p->kobj, KOBJ_REMOVE);
-		kobject_del(&p->kobj);
-		p->linkname[0] = '\0';
-	}
-	return 0;
-}
-#endif /* CONFIG_SYSFS */
diff --git a/datapath/linux/.gitignore b/datapath/linux/.gitignore
index d6de397..74c7314 100644
--- a/datapath/linux/.gitignore
+++ b/datapath/linux/.gitignore
@@ -4,7 +4,6 @@
 /Module.markers
 /actions.c
 /addrconf_core-openvswitch.c
-/brcompat_main.c
 /checksum.c
 /dev-openvswitch.c
 /dp_sysfs_dp.c
@@ -15,7 +14,6 @@
 /exthdrs_core.c
 /flex_array.c
 /flow.c
-/genetlink-brcompat.c
 /genetlink-openvswitch.c
 /genl_exec.c
 /ip_output-openvswitch.c
diff --git a/datapath/linux/Makefile.main.in b/datapath/linux/Makefile.main.in
index 6b46c0c..b55fc95 100644
--- a/datapath/linux/Makefile.main.in
+++ b/datapath/linux/Makefile.main.in
@@ -4,7 +4,6 @@ export srcdir = @abs_srcdir@
 export top_srcdir = @abs_top_srcdir@
 export KSRC = @KBUILD@
 export VERSION = @VERSION@
-export BUILD_BRCOMPAT = @BUILD_BRCOMPAT@
 
 include $(srcdir)/../Modules.mk
 include $(srcdir)/Modules.mk
diff --git a/datapath/linux/Modules.mk b/datapath/linux/Modules.mk
index 81556d5..c49dd2d 100644
--- a/datapath/linux/Modules.mk
+++ b/datapath/linux/Modules.mk
@@ -68,11 +68,4 @@ openvswitch_headers += \
 	linux/compat/include/net/protocol.h \
 	linux/compat/include/net/route.h \
 	linux/compat/include/net/sock.h \
-	linux/compat/include/net/netns/generic.h \
-	linux/compat/genetlink.inc
-
-# always distribute brcompat source regardless of local build configuration
-dist_modules += brcompat
-build_modules += $(if $(BUILD_BRCOMPAT),brcompat)
-brcompat_sources = linux/compat/genetlink-brcompat.c brcompat_main.c
-brcompat_headers =
+	linux/compat/include/net/netns/generic.h
diff --git a/datapath/linux/compat/genetlink-brcompat.c b/datapath/linux/compat/genetlink-brcompat.c
deleted file mode 100644
index ed3a4bb..0000000
--- a/datapath/linux/compat/genetlink-brcompat.c
+++ /dev/null
@@ -1,10 +0,0 @@
-/* We fix grp->id to 32 so that it doesn't collide with any of the multicast
- * groups selected by openvswitch, which uses groups 16 through 31.
- * Collision isn't fatal--multicast listeners should check that the family is
- * the one that they want and discard others--but it wastes time and memory to
- * receive unwanted messages. */
-
-#define GENL_FIRST_MCGROUP 32
-#define GENL_LAST_MCGROUP  32
-
-#include "genetlink.inc"
diff --git a/datapath/linux/compat/genetlink-openvswitch.c b/datapath/linux/compat/genetlink-openvswitch.c
index 3e687b7..1403d30 100644
--- a/datapath/linux/compat/genetlink-openvswitch.c
+++ b/datapath/linux/compat/genetlink-openvswitch.c
@@ -1,4 +1,149 @@
+#include <net/genetlink.h>
+#include <linux/version.h>
+
 #define GENL_FIRST_MCGROUP 16
 #define GENL_LAST_MCGROUP  31
 
-#include "genetlink.inc"
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+#include <linux/mutex.h>
+#include <linux/openvswitch.h>
+
+#include "openvswitch/datapath-compat.h"
+
+static DEFINE_MUTEX(mc_group_mutex);
+
+int genl_register_mc_group(struct genl_family *family,
+			   struct genl_multicast_group *grp)
+{
+	static int next_group = GENL_FIRST_MCGROUP;
+
+	grp->family = family;
+
+	if (!strcmp(grp->name, OVS_VPORT_MCGROUP)) {
+		grp->id = OVS_VPORT_MCGROUP_FALLBACK_ID;
+		return 0;
+	}
+
+	mutex_lock(&mc_group_mutex);
+	grp->id = next_group;
+
+	if (++next_group > GENL_LAST_MCGROUP)
+		next_group = GENL_FIRST_MCGROUP;
+	mutex_unlock(&mc_group_mutex);
+
+	return 0;
+}
+#endif /* kernel < 2.6.23 */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
+/**
+ * genl_register_family_with_ops - register a generic netlink family
+ * @family: generic netlink family
+ * @ops: operations to be registered
+ * @n_ops: number of elements to register
+ *
+ * Registers the specified family and operations from the specified table.
+ * Only one family may be registered with the same family name or identifier.
+ *
+ * The family id may equal GENL_ID_GENERATE causing an unique id to
+ * be automatically generated and assigned.
+ *
+ * Either a doit or dumpit callback must be specified for every registered
+ * operation or the function will fail. Only one operation structure per
+ * command identifier may be registered.
+ *
+ * See include/net/genetlink.h for more documenation on the operations
+ * structure.
+ *
+ * This is equivalent to calling genl_register_family() followed by
+ * genl_register_ops() for every operation entry in the table taking
+ * care to unregister the family on error path.
+ *
+ * Return 0 on success or a negative error code.
+ */
+int genl_register_family_with_ops(struct genl_family *family,
+	struct genl_ops *ops, size_t n_ops)
+{
+	int err, i;
+
+	err = genl_register_family(family);
+	if (err)
+		return err;
+
+	for (i = 0; i < n_ops; ++i, ++ops) {
+		err = genl_register_ops(family, ops);
+		if (err)
+			goto err_out;
+	}
+	return 0;
+err_out:
+	genl_unregister_family(family);
+	return err;
+}
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+/**
+ * nlmsg_notify - send a notification netlink message
+ * @sk: netlink socket to use
+ * @skb: notification message
+ * @pid: destination netlink pid for reports or 0
+ * @group: destination multicast group or 0
+ * @report: 1 to report back, 0 to disable
+ * @flags: allocation flags
+ */
+int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 pid,
+		 unsigned int group, int report, gfp_t flags)
+{
+	int err = 0;
+
+	if (group) {
+		int exclude_pid = 0;
+
+		if (report) {
+			atomic_inc(&skb->users);
+			exclude_pid = pid;
+		}
+
+		/* errors reported via destination sk->sk_err, but propagate
+		 * delivery errors if NETLINK_BROADCAST_ERROR flag is set */
+		err = nlmsg_multicast(sk, skb, exclude_pid, group, flags);
+	}
+
+	if (report) {
+		int err2;
+
+		err2 = nlmsg_unicast(sk, skb, pid);
+		if (!err || err == -ESRCH)
+			err = err2;
+	}
+
+	return err;
+}
+#endif
+
+/* This is analogous to rtnl_notify() but uses genl_sock instead of rtnl.
+ *
+ * This is not (yet) in any upstream kernel. */
+void genl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group,
+		 struct nlmsghdr *nlh, gfp_t flags)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
+	struct sock *sk = net->genl_sock;
+#else
+	struct sock *sk = genl_sock;
+#endif
+	int report = 0;
+
+	if (nlh)
+		report = nlmsg_report(nlh);
+
+	nlmsg_notify(sk, skb, pid, group, report, flags);
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
+/* This function wasn't exported before 2.6.30.  Lose! */
+void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
+{
+}
+#endif
diff --git a/datapath/linux/compat/genetlink.inc b/datapath/linux/compat/genetlink.inc
deleted file mode 100644
index bf96980..0000000
--- a/datapath/linux/compat/genetlink.inc
+++ /dev/null
@@ -1,148 +0,0 @@
-/* -*- c -*- */
-
-#include <net/genetlink.h>
-#include <linux/version.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
-#include <linux/mutex.h>
-#include <linux/openvswitch.h>
-
-#include "openvswitch/datapath-compat.h"
-
-static DEFINE_MUTEX(mc_group_mutex);
-
-int genl_register_mc_group(struct genl_family *family,
-			   struct genl_multicast_group *grp)
-{
-	static int next_group = GENL_FIRST_MCGROUP;
-
-	grp->family = family;
-
-	if (!strcmp(grp->name, OVS_VPORT_MCGROUP)) {
-		grp->id = OVS_VPORT_MCGROUP_FALLBACK_ID;
-		return 0;
-	}
-
-	mutex_lock(&mc_group_mutex);
-	grp->id = next_group;
-
-	if (++next_group > GENL_LAST_MCGROUP)
-		next_group = GENL_FIRST_MCGROUP;
-	mutex_unlock(&mc_group_mutex);
-
-	return 0;
-}
-#endif /* kernel < 2.6.23 */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
-/**
- * genl_register_family_with_ops - register a generic netlink family
- * @family: generic netlink family
- * @ops: operations to be registered
- * @n_ops: number of elements to register
- *
- * Registers the specified family and operations from the specified table.
- * Only one family may be registered with the same family name or identifier.
- *
- * The family id may equal GENL_ID_GENERATE causing an unique id to
- * be automatically generated and assigned.
- *
- * Either a doit or dumpit callback must be specified for every registered
- * operation or the function will fail. Only one operation structure per
- * command identifier may be registered.
- *
- * See include/net/genetlink.h for more documenation on the operations
- * structure.
- *
- * This is equivalent to calling genl_register_family() followed by
- * genl_register_ops() for every operation entry in the table taking
- * care to unregister the family on error path.
- *
- * Return 0 on success or a negative error code.
- */
-int genl_register_family_with_ops(struct genl_family *family,
-	struct genl_ops *ops, size_t n_ops)
-{
-	int err, i;
-
-	err = genl_register_family(family);
-	if (err)
-		return err;
-
-	for (i = 0; i < n_ops; ++i, ++ops) {
-		err = genl_register_ops(family, ops);
-		if (err)
-			goto err_out;
-	}
-	return 0;
-err_out:
-	genl_unregister_family(family);
-	return err;
-}
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
-/**
- * nlmsg_notify - send a notification netlink message
- * @sk: netlink socket to use
- * @skb: notification message
- * @pid: destination netlink pid for reports or 0
- * @group: destination multicast group or 0
- * @report: 1 to report back, 0 to disable
- * @flags: allocation flags
- */
-int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 pid,
-		 unsigned int group, int report, gfp_t flags)
-{
-	int err = 0;
-
-	if (group) {
-		int exclude_pid = 0;
-
-		if (report) {
-			atomic_inc(&skb->users);
-			exclude_pid = pid;
-		}
-
-		/* errors reported via destination sk->sk_err, but propagate
-		 * delivery errors if NETLINK_BROADCAST_ERROR flag is set */
-		err = nlmsg_multicast(sk, skb, exclude_pid, group, flags);
-	}
-
-	if (report) {
-		int err2;
-
-		err2 = nlmsg_unicast(sk, skb, pid);
-		if (!err || err == -ESRCH)
-			err = err2;
-	}
-
-	return err;
-}
-#endif
-
-/* This is analogous to rtnl_notify() but uses genl_sock instead of rtnl.
- *
- * This is not (yet) in any upstream kernel. */
-void genl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group,
-		 struct nlmsghdr *nlh, gfp_t flags)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
-	struct sock *sk = net->genl_sock;
-#else
-	struct sock *sk = genl_sock;
-#endif
-	int report = 0;
-
-	if (nlh)
-		report = nlmsg_report(nlh);
-
-	nlmsg_notify(sk, skb, pid, group, report, flags);
-}
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
-/* This function wasn't exported before 2.6.30.  Lose! */
-void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
-{
-}
-#endif
diff --git a/datapath/vport-internal_dev.c b/datapath/vport-internal_dev.c
index 4dc2eb4..fb581a3 100644
--- a/datapath/vport-internal_dev.c
+++ b/datapath/vport-internal_dev.c
@@ -154,15 +154,6 @@ static int internal_dev_change_mtu(struct net_device *netdev, int new_mtu)
 	return 0;
 }
 
-static int internal_dev_do_ioctl(struct net_device *dev,
-				 struct ifreq *ifr, int cmd)
-{
-	if (ovs_dp_ioctl_hook)
-		return ovs_dp_ioctl_hook(dev, ifr, cmd);
-
-	return -EOPNOTSUPP;
-}
-
 static void internal_dev_destructor(struct net_device *dev)
 {
 	struct vport *vport = ovs_internal_dev_get_vport(dev);
@@ -177,7 +168,6 @@ static const struct net_device_ops internal_dev_netdev_ops = {
 	.ndo_stop = internal_dev_stop,
 	.ndo_start_xmit = internal_dev_xmit,
 	.ndo_set_mac_address = internal_dev_mac_addr,
-	.ndo_do_ioctl = internal_dev_do_ioctl,
 	.ndo_change_mtu = internal_dev_change_mtu,
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
 	.ndo_get_stats64 = internal_dev_get_stats,
@@ -194,7 +184,6 @@ static void do_setup(struct net_device *netdev)
 #ifdef HAVE_NET_DEVICE_OPS
 	netdev->netdev_ops = &internal_dev_netdev_ops;
 #else
-	netdev->do_ioctl = internal_dev_do_ioctl;
 	netdev->get_stats = internal_dev_sys_stats;
 	netdev->hard_start_xmit = internal_dev_xmit;
 	netdev->open = internal_dev_open;
diff --git a/datapath/vport-netdev.c b/datapath/vport-netdev.c
index 5f437d3..6701838 100644
--- a/datapath/vport-netdev.c
+++ b/datapath/vport-netdev.c
@@ -426,10 +426,21 @@ const struct vport_ops ovs_netdev_vport_ops = {
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
 /*
- * In kernels earlier than 2.6.36, Open vSwitch cannot safely coexist with the
- * Linux bridge module, because there is only a single bridge hook function and
- * only a single br_port member in struct net_device, so this prevents loading
- * both bridge and openvswitch at the same time.
+ * Enforces, mutual exclusion with the Linux bridge module, by declaring and
+ * exporting br_should_route_hook.  Because the bridge module also exports the
+ * same symbol, the module loader will refuse to load both modules at the same
+ * time (e.g. "bridge: exports duplicate symbol br_should_route_hook (owned by
+ * openvswitch)").
+ *
+ * Before Linux 2.6.36, Open vSwitch cannot safely coexist with the Linux
+ * bridge module, so openvswitch uses this macro in those versions.  In
+ * Linux 2.6.36 and later, Open vSwitch can coexist with the bridge module,
+ * but it makes no sense to load both bridge and brcompat, so brcompat uses
+ * this macro in those versions.
+ *
+ * The use of "typeof" here avoids the need to track changes in the type of
+ * br_should_route_hook over various kernel versions.
  */
-BRIDGE_MUTUAL_EXCLUSION;
+typeof(br_should_route_hook) br_should_route_hook;
+EXPORT_SYMBOL(br_should_route_hook);
 #endif
diff --git a/datapath/vport.c b/datapath/vport.c
index 4934ac1..0e04045 100644
--- a/datapath/vport.c
+++ b/datapath/vport.c
@@ -150,19 +150,6 @@ struct vport *ovs_vport_locate(struct net *net, const char *name)
 	return NULL;
 }
 
-static void release_vport(struct kobject *kobj)
-{
-	struct vport *p = container_of(kobj, struct vport, kobj);
-	kfree(p);
-}
-
-static struct kobj_type brport_ktype = {
-#ifdef CONFIG_SYSFS
-	.sysfs_ops = &ovs_brport_sysfs_ops,
-#endif
-	.release = release_vport
-};
-
 /**
  *	ovs_vport_alloc - allocate and initialize new vport
  *
@@ -196,11 +183,6 @@ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops,
 	vport->ops = ops;
 	INIT_HLIST_NODE(&vport->dp_hash_node);
 
-	/* Initialize kobject for bridge.  This will be added as
-	 * /sys/class/net/<devname>/brport later, if sysfs is enabled. */
-	vport->kobj.kset = NULL;
-	kobject_init(&vport->kobj, &brport_ktype);
-
 	vport->percpu_stats = alloc_percpu(struct vport_percpu_stats);
 	if (!vport->percpu_stats) {
 		kfree(vport);
@@ -225,8 +207,7 @@ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops,
 void ovs_vport_free(struct vport *vport)
 {
 	free_percpu(vport->percpu_stats);
-
-	kobject_put(&vport->kobj);
+	kfree(vport);
 }
 
 /**
diff --git a/datapath/vport.h b/datapath/vport.h
index 5a7caf5..852b2b0 100644
--- a/datapath/vport.h
+++ b/datapath/vport.h
@@ -76,7 +76,6 @@ struct vport_err_stats {
  * @rcu: RCU callback head for deferred destruction.
  * @port_no: Index into @dp's @ports array.
  * @dp: Datapath to which this port belongs.
- * @kobj: Represents /sys/class/net/<devname>/brport.
  * @linkname: The name of the link from /sys/class/net/<datapath>/brif to this
  * &struct vport.  (We keep this around so that we can delete it if the
  * device gets renamed.)  Set to the null string when no link exists.
@@ -95,7 +94,6 @@ struct vport {
 	struct rcu_head rcu;
 	u16 port_no;
 	struct datapath	*dp;
-	struct kobject kobj;
 	char linkname[IFNAMSIZ];
 	u32 upcall_pid;
 
diff --git a/debian/.gitignore b/debian/.gitignore
index 3e1373a..1c5e09f 100644
--- a/debian/.gitignore
+++ b/debian/.gitignore
@@ -6,7 +6,6 @@
 /files
 /nicira-switch
 /openvswitch
-/openvswitch-brcompat
 /openvswitch-common
 /openvswitch-common.copyright
 /openvswitch-controller
diff --git a/debian/automake.mk b/debian/automake.mk
index b6cb12e..35c5a9e 100644
--- a/debian/automake.mk
+++ b/debian/automake.mk
@@ -7,10 +7,6 @@ EXTRA_DIST += \
 	debian/copyright.in \
 	debian/dkms.conf.in \
 	debian/dirs \
-	debian/openvswitch-brcompat.install \
-	debian/openvswitch-brcompat.manpages \
-	debian/openvswitch-brcompat.postinst \
-	debian/openvswitch-brcompat.postrm \
 	debian/openvswitch-common.dirs \
 	debian/openvswitch-common.docs \
 	debian/openvswitch-common.install \
diff --git a/debian/control b/debian/control
index 15ca3eb..ae88be2 100644
--- a/debian/control
+++ b/debian/control
@@ -135,28 +135,6 @@ Description: Open vSwitch controller implementation
  The Open vSwitch controller enables OpenFlow switches that connect to it
  to act as MAC-learning Ethernet switches.
 
-Package: openvswitch-brcompat
-Architecture: linux-any
-Depends:
- ${shlibs:Depends}, openvswitch-switch (= ${binary:Version}), ${misc:Depends}
-Recommends: bridge-utils
-Description: Open vSwitch bridge compatibility support
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
- .
- openvswitch-brcompat provides a way for applications that use the
- Linux bridge to gradually migrate to Open vSwitch.  Programs that
- ordinarily control the Linux bridge module, such as "brctl", instead
- control the Open vSwitch kernel-based switch.
- .
- Once this package is installed, adding BRCOMPAT=yes in
- /etc/default/openvswitch-switch enables bridge compatibility.
-
 Package: openvswitch-dbg
 Section: debug
 Architecture: linux-any
diff --git a/debian/copyright.in b/debian/copyright.in
index 16e5559..7d5b7b7 100644
--- a/debian/copyright.in
+++ b/debian/copyright.in
@@ -76,7 +76,6 @@ License:
   GNU General Public License version 2 and the Apache License Version 2.0.
 
 	include/linux/openvswitch.h
-	include/openvswitch/brcompat-netlink.h
 	include/openvswitch/datapath-compat.h
 	include/openvswitch/tunnel.h
 
diff --git a/debian/dkms.conf.in b/debian/dkms.conf.in
index 0d3db76..a477761 100644
--- a/debian/dkms.conf.in
+++ b/debian/dkms.conf.in
@@ -2,9 +2,6 @@ PACKAGE_NAME="openvswitch"
 PACKAGE_VERSION="__VERSION__"
 MAKE="./configure --with-linux='${kernel_source_dir}' && make -C datapath/linux"
 BUILT_MODULE_NAME[0]=openvswitch
-BUILT_MODULE_NAME[1]=brcompat
 BUILT_MODULE_LOCATION[0]=datapath/linux/
-BUILT_MODULE_LOCATION[1]=datapath/linux/
 DEST_MODULE_LOCATION[0]=/kernel/drivers/net/openvswitch/
-DEST_MODULE_LOCATION[1]=/kernel/drivers/net/openvswitch/
 AUTOINSTALL=yes
diff --git a/debian/openvswitch-brcompat.install b/debian/openvswitch-brcompat.install
deleted file mode 100644
index fad09f1..0000000
--- a/debian/openvswitch-brcompat.install
+++ /dev/null
@@ -1 +0,0 @@
-_debian/vswitchd/ovs-brcompatd usr/sbin
diff --git a/debian/openvswitch-brcompat.manpages b/debian/openvswitch-brcompat.manpages
deleted file mode 100644
index 2fc0180..0000000
--- a/debian/openvswitch-brcompat.manpages
+++ /dev/null
@@ -1 +0,0 @@
-_debian/vswitchd/ovs-brcompatd.8
diff --git a/debian/openvswitch-brcompat.postinst b/debian/openvswitch-brcompat.postinst
deleted file mode 100755
index 12e3b05..0000000
--- a/debian/openvswitch-brcompat.postinst
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/sh
-
-set -e
-
-# If openvswitch-switch is installed, and then later openvswitch-brcompat is
-# installed, make sure that ovs-brcompatd starts.
-if test X"$1" = Xconfigure && \
-   test -x /etc/init.d/openvswitch-switch && \
-   test -e /var/run/openvswitch/ovs-vswitchd.pid; then
-    invoke-rc.d openvswitch-switch start || exit $?
-fi
-
-#DEBHELPER#
-
-exit 0
-
-
diff --git a/debian/openvswitch-brcompat.postrm b/debian/openvswitch-brcompat.postrm
deleted file mode 100755
index e21b002..0000000
--- a/debian/openvswitch-brcompat.postrm
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/sh
-# postrm script for openvswitch-brcompat
-#
-# see: dh_installdeb(1)
-
-set -e
-
-# summary of how this script can be called:
-#        * <postrm> `remove'
-#        * <postrm> `purge'
-#        * <old-postrm> `upgrade' <new-version>
-#        * <new-postrm> `failed-upgrade' <old-version>
-#        * <new-postrm> `abort-install'
-#        * <new-postrm> `abort-install' <old-version>
-#        * <new-postrm> `abort-upgrade' <old-version>
-#        * <disappearer's-postrm> `disappear' <overwriter>
-#          <overwriter-version>
-# for details, see http://www.debian.org/doc/debian-policy/ or
-# the debian-policy package
-
-
-case "$1" in
-    purge)
-        rm -f /var/log/openvswitch/ovs-brcompatd.log* || true
-        ;;
-
-    remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
-        ;;
-
-    *)
-        echo "postrm called with unknown argument \`$1'" >&2
-        exit 1
-        ;;
-esac
-
-# dh_installdeb will replace this with shell code automatically
-# generated by other debhelper scripts.
-
-#DEBHELPER#
-
-exit 0
-
-
diff --git a/debian/openvswitch-switch.init b/debian/openvswitch-switch.init
index 301bc73..d296d8b 100755
--- a/debian/openvswitch-switch.init
+++ b/debian/openvswitch-switch.init
@@ -30,16 +30,8 @@
 . /usr/share/openvswitch/scripts/ovs-lib
 test -e /etc/default/openvswitch-switch && . /etc/default/openvswitch-switch
 
-if test X"$BRCOMPAT" = Xyes && test ! -x /usr/sbin/ovs-brcompatd; then
-    BRCOMPAT=no
-    log_warning_msg "ovs-brcompatd missing, disabling bridge compatibility"
-fi
-
 ovs_ctl () {
     set /usr/share/openvswitch/scripts/ovs-ctl "$@"
-    if test X"$BRCOMPAT" = Xyes; then
-        set "$@" --brcompat
-    fi
     "$@"
 }
 
diff --git a/debian/openvswitch-switch.template b/debian/openvswitch-switch.template
index afa5dd3..d7c7796 100644
--- a/debian/openvswitch-switch.template
+++ b/debian/openvswitch-switch.template
@@ -3,10 +3,6 @@
 # FORCE_COREFILES: If 'yes' then core files will be enabled.
 # FORCE_COREFILES=yes
 
-# BRCOMPAT: If 'yes' and the openvswitch-brcompat package is installed, then
-# Linux bridge compatibility will be enabled.
-# BRCOMPAT=no
-
 # OVS_CTL_OPTS: Extra options to pass to ovs-ctl.  This is, for example,
 # a suitable place to specify --ovs-vswitchd-wrapper=valgrind.
 # OVS_CTL_OPTS=
diff --git a/include/openvswitch/automake.mk b/include/openvswitch/automake.mk
index 757c765..6cd6192 100644
--- a/include/openvswitch/automake.mk
+++ b/include/openvswitch/automake.mk
@@ -1,5 +1,4 @@
 noinst_HEADERS += \
-	include/openvswitch/brcompat-netlink.h \
 	include/openvswitch/datapath-compat.h \
 	include/openvswitch/tunnel.h \
 	include/openvswitch/types.h
diff --git a/include/openvswitch/brcompat-netlink.h b/include/openvswitch/brcompat-netlink.h
deleted file mode 100644
index 7e5845a..0000000
--- a/include/openvswitch/brcompat-netlink.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, 2011 Nicira, Inc.
- *
- * This file is offered under your choice of two licenses: Apache 2.0 or GNU
- * GPL 2.0 or later.  The permission statements for each of these licenses is
- * given below.  You may license your modifications to this file under either
- * of these licenses or both.  If you wish to license your modifications under
- * only one of these licenses, delete the permission text for the other
- * license.
- *
- * ----------------------------------------------------------------------
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ----------------------------------------------------------------------
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- * ----------------------------------------------------------------------
- */
-
-#ifndef OPENVSWITCH_BRCOMPAT_NETLINK_H
-#define OPENVSWITCH_BRCOMPAT_NETLINK_H 1
-
-#define BRC_GENL_FAMILY_NAME "brcompat"
-
-/* Attributes that can be attached to the datapath's netlink messages. */
-enum {
-	BRC_GENL_A_UNSPEC,
-
-	/*
-	 * "K:" attributes appear in messages from the kernel to userspace.
-	 * "U:" attributes appear in messages from userspace to the kernel.
-	 */
-
-	/* BRC_GENL_C_DP_ADD, BRC_GENL_C_DP_DEL. */
-	BRC_GENL_A_DP_NAME,		/* K: Datapath name. */
-
-	/* BRC_GENL_C_DP_ADD, BRC_GENL_C_DP_DEL,
-	   BRC_GENL_C_PORT_ADD, BRC_GENL_C_PORT_DEL. */
-	BRC_GENL_A_PORT_NAME,	/* K: Interface name. */
-
-	/* BRC_GENL_C_DP_RESULT. */
-	BRC_GENL_A_ERR_CODE,	/* U: Positive error code. */
-
-	/* BRC_GENL_C_QUERY_MC. */
-	BRC_GENL_A_MC_GROUP,	/* K: Generic netlink multicast group. */
-
-	/* BRC_GENL_C_FDB_QUERY. */
-	BRC_GENL_A_FDB_COUNT,	/* K: Number of FDB entries to read. */
-	BRC_GENL_A_FDB_SKIP,	/* K: Record offset into FDB to start reading. */
-
-	/* BRC_GENL_C_DP_RESULT. */
-	BRC_GENL_A_FDB_DATA,    /* U: FDB records. */
-	BRC_GENL_A_IFINDEXES,   /* U: "int" ifindexes of bridges or ports. */
-
-	__BRC_GENL_A_MAX,
-	BRC_GENL_A_MAX = __BRC_GENL_A_MAX - 1
-};
-
-/* Commands that can be executed on the datapath's netlink interface. */
-enum brc_genl_command {
-	BRC_GENL_C_UNSPEC,
-
-	/*
-	 * "K:" messages are sent by the kernel to userspace.
-	 * "U:" messages are sent by userspace to the kernel.
-	 */
-	BRC_GENL_C_DP_ADD,		/* K: Datapath created. */
-	BRC_GENL_C_DP_DEL,		/* K: Datapath destroyed. */
-	BRC_GENL_C_DP_RESULT,	/* U: Return code from ovs-brcompatd. */
-	BRC_GENL_C_PORT_ADD,	/* K: Port added to datapath. */
-	BRC_GENL_C_PORT_DEL,	/* K: Port removed from datapath. */
-	BRC_GENL_C_QUERY_MC,	/* U: Get multicast group for brcompat. */
-	BRC_GENL_C_FDB_QUERY,	/* K: Read records from forwarding database. */
-	BRC_GENL_C_GET_BRIDGES, /* K: Get ifindexes of all bridges. */
-	BRC_GENL_C_GET_PORTS,   /* K: Get ifindexes of all ports on a bridge. */
-
-	__BRC_GENL_C_MAX,
-	BRC_GENL_C_MAX = __BRC_GENL_C_MAX - 1
-};
-#endif /* openvswitch/brcompat-netlink.h */
diff --git a/m4/openvswitch.m4 b/m4/openvswitch.m4
index 7469011..59cc933 100644
--- a/m4/openvswitch.m4
+++ b/m4/openvswitch.m4
@@ -390,23 +390,3 @@ AC_DEFUN([OVS_CHECK_GROFF],
        ovs_cv_groff=no
      fi])
    AM_CONDITIONAL([HAVE_GROFF], [test "$ovs_cv_groff" = yes])])
-
-dnl Checks for --disable-brcompat and undefines BUILD_BRCOMPAT if it is specified.
-AC_DEFUN([OVS_CHECK_BRCOMPAT],
-  [AC_ARG_ENABLE(
-     [brcompat],
-     [AC_HELP_STRING([--disable-brcompat],
-                     [Disable building brcompat])],
-     [case "${enableval}" in
-        (yes) brcompat=true ;;
-        (no)  brcompat=false ;;
-        (*) AC_MSG_ERROR([bad value ${enableval} for --enable-brcompat]) ;;
-      esac],
-     [brcompat=true])
-   if test x$brcompat = xtrue; then
-      BUILD_BRCOMPAT=yes
-   else
-      BUILD_BRCOMPAT=""
-   fi
-   AC_SUBST([BUILD_BRCOMPAT])
-   AM_CONDITIONAL([BUILD_BRCOMPAT], [test x$brcompat = xtrue])])
diff --git a/manpages.mk b/manpages.mk
index 925912d..785bbd8 100644
--- a/manpages.mk
+++ b/manpages.mk
@@ -220,18 +220,6 @@ ovsdb/remote-active.man:
 ovsdb/remote-passive.man:
 ovsdb/remote-passive.man:
 
-vswitchd/ovs-brcompatd.8: \
-	vswitchd/ovs-brcompatd.8.in \
-	lib/common.man \
-	lib/daemon.man \
-	lib/leak-checker.man \
-	lib/vlog.man
-vswitchd/ovs-brcompatd.8.in:
-lib/common.man:
-lib/daemon.man:
-lib/leak-checker.man:
-lib/vlog.man:
-
 vswitchd/ovs-vswitchd.8: \
 	vswitchd/ovs-vswitchd.8.in \
 	lib/common.man \
diff --git a/rhel/etc_init.d_openvswitch b/rhel/etc_init.d_openvswitch
index af332c0..a25e624 100755
--- a/rhel/etc_init.d_openvswitch
+++ b/rhel/etc_init.d_openvswitch
@@ -45,9 +45,6 @@ start () {
     if test X"$VSWITCHD_MLOCKALL" != X; then
 	set "$@" --mlockall="$VSWITCHD_MLOCKALL"
     fi
-    if test X"$BRCOMPAT" = Xyes; then
-	set "$@" --brcompat
-    fi
     set "$@" $OVS_CTL_OPTS
     "$@"
 
diff --git a/rhel/openvswitch-fedora.spec.in b/rhel/openvswitch-fedora.spec.in
index 7918fd5..6c225f7 100644
--- a/rhel/openvswitch-fedora.spec.in
+++ b/rhel/openvswitch-fedora.spec.in
@@ -145,7 +145,6 @@ systemctl start openvswitch.service
 /usr/share/openvswitch/scripts/ovs-check-dead-ifs
 /usr/share/openvswitch/scripts/ovs-lib
 %config /usr/share/openvswitch/vswitch.ovsschema
-/usr/sbin/ovs-brcompatd
 /usr/sbin/ovs-bugtool
 /usr/sbin/ovs-vswitchd
 /usr/sbin/ovsdb-server
@@ -167,7 +166,6 @@ systemctl start openvswitch.service
 %doc /usr/share/man/man5/ovs-vswitchd.conf.db.5.gz
 %doc /usr/share/man/man8/ovs-appctl.8.gz
 %doc /usr/share/man/man8/ovs-bugtool.8.gz
-%doc /usr/share/man/man8/ovs-brcompatd.8.gz
 %doc /usr/share/man/man8/ovs-dpctl.8.gz
 %doc /usr/share/man/man8/ovs-ofctl.8.gz
 %doc /usr/share/man/man8/ovs-parse-backtrace.8.gz
diff --git a/rhel/openvswitch-kmod-fedora.spec.in b/rhel/openvswitch-kmod-fedora.spec.in
index af75ddd..16a8c73 100644
--- a/rhel/openvswitch-kmod-fedora.spec.in
+++ b/rhel/openvswitch-kmod-fedora.spec.in
@@ -56,7 +56,6 @@ depmod %{kernel}
 %files
 %defattr(-,root,root)
 /lib/modules/%{kernel}/kernel/extra/openvswitch/openvswitch.ko
-/lib/modules/%{kernel}/kernel/extra/openvswitch/brcompat.ko
 
 %changelog
 * Wed Sep 21 2011 Kyle Mestery <kmestery at cisco.com>
diff --git a/rhel/openvswitch.spec.in b/rhel/openvswitch.spec.in
index ff598b9..9f40881 100644
--- a/rhel/openvswitch.spec.in
+++ b/rhel/openvswitch.spec.in
@@ -124,7 +124,6 @@ exit 0
 /usr/bin/ovs-vsctl
 /usr/bin/ovsdb-client
 /usr/bin/ovsdb-tool
-/usr/sbin/ovs-brcompatd
 /usr/sbin/ovs-bugtool
 /usr/sbin/ovs-vswitchd
 /usr/sbin/ovsdb-server
@@ -136,7 +135,6 @@ exit 0
 /usr/share/man/man1/ovsdb-tool.1.gz
 /usr/share/man/man5/ovs-vswitchd.conf.db.5.gz
 /usr/share/man/man8/ovs-appctl.8.gz
-/usr/share/man/man8/ovs-brcompatd.8.gz
 /usr/share/man/man8/ovs-bugtool.8.gz
 /usr/share/man/man8/ovs-ctl.8.gz
 /usr/share/man/man8/ovs-dpctl.8.gz
diff --git a/rhel/usr_share_openvswitch_scripts_sysconfig.template b/rhel/usr_share_openvswitch_scripts_sysconfig.template
index cad1f53..2c08452 100644
--- a/rhel/usr_share_openvswitch_scripts_sysconfig.template
+++ b/rhel/usr_share_openvswitch_scripts_sysconfig.template
@@ -19,9 +19,6 @@
 #     concurrent VM import operations.
 # VSWITCHD_MLOCKALL=yes
 
-# BRCOMPAT: If 'yes' compatibility mode will be enabled.
-# BRCOMPAT=yes
-
 # OVS_CTL_OPTS: Extra options to pass to ovs-ctl.  This is, for example,
 # a suitable place to specify --ovs-vswitchd-wrapper=valgrind.
 # OVS_CTL_OPTS=
diff --git a/utilities/bugtool/ovs-bugtool.in b/utilities/bugtool/ovs-bugtool.in
index 2074e23..f91a3b3 100755
--- a/utilities/bugtool/ovs-bugtool.in
+++ b/utilities/bugtool/ovs-bugtool.in
@@ -135,7 +135,6 @@ KRB5_CONF = '/etc/krb5.conf'
 
 os.environ['PATH'] = '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:@pkgdatadir@/scripts'
 ARP = 'arp'
-BRCTL = 'brctl'
 CAT = 'cat'
 CHKCONFIG = 'chkconfig'
 DF = 'df'
@@ -584,7 +583,6 @@ exclude those logs from the archive.
     cmd_output(CAP_NETWORK_STATUS, [NETSTAT, '-an'])
     for dir in DHCP_LEASE_DIR:
         tree_output(CAP_NETWORK_STATUS, dir)
-    cmd_output(CAP_NETWORK_STATUS, [BRCTL, 'show'])
     cmd_output(CAP_NETWORK_STATUS, [IPTABLES, '-nL'])
     for p in os.listdir('/sys/class/net/'):
         try:
@@ -634,7 +632,7 @@ exclude those logs from the archive.
              [ 'crit.log', 'kern.log', 'daemon.log', 'user.log',
              'syslog', 'messages', 'secure', 'debug', 'dmesg', 'boot' ]]
             + [ OPENVSWITCH_LOG_DIR + x for x in
-                [ 'ovs-vswitchd.log', 'ovs-brcompatd.log', 'ovsdb-server.log',
+                [ 'ovs-vswitchd.log', 'ovsdb-server.log',
                   'ovs-xapi-sync.log', 'ovs-monitor-ipsec.log' ]])
     file_output(CAP_SYSTEM_LOGS, logs)
     file_output(CAP_SYSTEM_LOGS,
diff --git a/utilities/ovs-ctl.8 b/utilities/ovs-ctl.8
index 04c2930..7e1057a 100644
--- a/utilities/ovs-ctl.8
+++ b/utilities/ovs-ctl.8
@@ -69,41 +69,30 @@ bridge module and tries loading the Open vSwitch kernel module again.
 (This is because the Open vSwitch kernel module cannot coexist with
 the Linux bridge module before 2.6.37.)
 .
-.IP 2.
-If \fB\-\-brcompat\fR was specified, loads the Open vSwitch bridge
-compatibility module.
-.
 .PP
 The \fBstart\fR command skips the following steps if
 \fBovsdb\-server\fR is already running:
-.IP 3.
+.IP 2.
 If the Open vSwitch database file does not exist, it creates it.
 If the database does exist, but it has an obsolete version, it
 upgrades it to the latest schema.
 .
-.IP 4.
+.IP 3.
 Starts \fBovsdb-server\fR.
 .
-.IP 5.
+.IP 4.
 Initializes a few values inside the database.
 .
-.IP 6.
+.IP 5.
 If the \fB\-\-delete\-bridges\fR option was used, deletes all of the
 bridges from the database.
 .
 .PP
 The \fBstart\fR command skips the following step if
 \fBovs\-vswitchd\fR is already running:
-.IP 7.
+.IP 6.
 Starts \fBovs\-vswitchd\fR.
 .
-.PP
-The \fBstart\fR command skips the following step if
-\fBovs\-brcompatd\fR is already running or if \fB\-\-brcompat\fR is
-not specified:
-.IP 8.
-Starts \fBovs\-brcompatd\fR.
-.
 .SS "Options"
 .PP
 Several command-line options influence the \fBstart\fR command's
@@ -179,13 +168,11 @@ suppresses that behavior.
 .
 .IP "\fB\-\-ovsdb\-server\-priority=\fIniceness\fR"
 .IQ "\fB\-\-ovs\-vswitchd\-priority=\fIniceness\fR"
-.IQ "\fB\-\-ovs\-brcompatd\-priority=\fIniceness\fR"
 Sets the \fBnice\fR(1) level used for each daemon.  All of them
 default to \fB\-10\fR.
 .
 .IP "\fB\-\-ovsdb\-server\-wrapper=\fIwrapper\fR"
 .IQ "\fB\-\-ovs\-vswitchd\-wrapper=\fIwrapper\fR"
-.IQ "\fB\-\-ovs\-brcompatd\-wrapper=\fIwrapper\fR"
 .
 Configures the specified daemon to run under \fIwrapper\fR, which is
 one of the following:
@@ -238,11 +225,6 @@ taken as relative to \fIdbdir\fR.
 .SH "The ``stop'' command"
 .
 .PP
-The \fBstop\fR command shuts down Open vSwitch.  It kills any running
-\fBovs\-brcompatd\fR, \fBovs\-vswitchd\fR, or \fBovsdb\-server\fR
-daemons and waits for them to terminate.
-.
-.PP
 The \fBstop\fR command does not unload the Open vSwitch kernel
 modules.
 .
@@ -263,16 +245,14 @@ individual bridge.
 .PP
 The \fBstatus\fR command checks whether the OVS daemons
 \fBovs-vswitchd\fR and \fBovsdb\-server\fR are running and prints
-messages with that information.  If \fB\-\-brcompat\fR is specified,
-it also checks for \fBovs\-brcompatd\fR.  It exits with status 0 if
+messages with that information.  It exits with status 0 if
 the daemons are running, 1 otherwise.
 .
 .SH "The ``version'' command"
 .
 .PP
 The \fBversion\fR command runs \fBovsdb\-server \-\-version\fR and
-\fBovs\-vswitchd \-\-version\fR.  If \fB\-\-brcompat\fR is specified,
-it also runs \fBovs\-brcompatd \-\-version\fR.
+\fBovs\-vswitchd \-\-version\fR.
 .
 .SH "The ``force\-reload\-kmod'' command"
 .
@@ -304,8 +284,7 @@ compatibility module if it is loaded).
 .
 .IP 6.
 Starts OVS back up, as if by a call to \fBovs\-ctl start\fR.  This
-reloads the kernel module, restarts the OVS daemons (including
-\fBovs\-brcompatd\fR, if \fB\-\-brcompat\fR is specified) and finally
+reloads the kernel module, restarts the OVS daemons and finally
 restores the saved Openflow flows.
 .
 .IP 7.
@@ -336,8 +315,7 @@ from other errors that may occur when running the \fBstart\fR command.
 .
 .PP
 By default the \fBload\-kmod\fR command attempts to load the
-openvswitch kernel module. If the \fB\-\-brcompat\fR option is
-specified then the brcompat kernel module is also loaded.
+openvswitch kernel module.
 .
 .SH "The ``enable\-protocol'' command"
 .
@@ -390,16 +368,6 @@ Prints a usage message and exits successfully.
 In addition to the options listed for each command above, this option
 controls the behavior of several of \fBovs\-ctl\fR's commands.
 .
-.IP "\fB\-\-brcompat\fR"
-By default, \fBovs\-ctl\fR does not load the Open vSwitch bridge
-compatibility module and does not start or check the status or report
-the version of the \fBovs\-brcompatd\fR daemon.  This option enables
-all of those behaviors.
-.
-.IP
-The \fBstop\fR command always stops \fBovs\-brcompatd\fR, if it is
-running, regardless of this option.
-.
 .SH "EXIT STATUS"
 .
 \fBovs\-ctl\fR exits with status 0 on success and nonzero on failure.
diff --git a/utilities/ovs-ctl.in b/utilities/ovs-ctl.in
index d770f42..3c27e5b 100755
--- a/utilities/ovs-ctl.in
+++ b/utilities/ovs-ctl.in
@@ -52,25 +52,8 @@ insert_openvswitch_mod_if_required () {
     action "Inserting openvswitch module" modprobe openvswitch
 }
 
-insert_brcompat_mod_if_required () {
-    if test -e /sys/module/bridge; then
-        log_warning_msg "bridge module is loaded, not loading brcompat"
-        return 1
-    fi
-    test -e /sys/module/brcompat -o -e /sys/module/brcompat_mod && return 0
-    action "Inserting brcompat module" modprobe brcompat
-}
-
 insert_mod_if_required () {
     insert_openvswitch_mod_if_required || return 1
-    if test X"$BRCOMPAT" = Xyes; then
-        if insert_brcompat_mod_if_required; then
-            :
-        else
-            log_warning_msg "could not load brcompat module, disabling bridge compatibility"
-            BRCOMPAT=no
-        fi
-    fi
 }
 
 ovs_vsctl () {
@@ -245,14 +228,6 @@ start_forwarding () {
 	    fi
 	    start_daemon "$OVS_VSWITCHD_PRIORITY" "$OVS_VSWITCHD_WRAPPER" "$@"
     fi
-
-    if daemon_is_running ovs-brcompatd; then
-	    log_success_msg "ovs-brcompatd is already running"
-    elif test X"$BRCOMPAT" = Xyes; then
-        set ovs-brcompatd
-	    set "$@" -vconsole:emer -vsyslog:err -vfile:info
-	    start_daemon "$OVS_BRCOMPATD_PRIORITY" "$OVS_BRCOMPATD_WRAPPER" "$@"
-    fi
 }
 
 ## ---- ##
@@ -264,7 +239,6 @@ stop_ovsdb () {
 }
 
 stop_forwarding () {
-    stop_daemon ovs-brcompatd
     stop_daemon ovs-vswitchd
 }
 
@@ -346,11 +320,6 @@ force_reload_kmod () {
     done
 
     # try both old and new names in case this is post upgrade
-    if test -e /sys/module/brcompat_mod; then
-        action "Removing brcompat module" rmmod brcompat_mod
-    elif test -e /sys/module/brcompat; then
-        action "Removing brcompat module" rmmod brcompat
-    fi
     if test -e /sys/module/openvswitch_mod; then
         action "Removing openvswitch module" rmmod openvswitch_mod
     elif test -e /sys/module/openvswitch; then
@@ -453,17 +422,14 @@ set_defaults () {
     SYSTEM_ID=
 
     DELETE_BRIDGES=no
-    BRCOMPAT=no
 
     DAEMON_CWD=/
     FORCE_COREFILES=yes
     MLOCKALL=yes
     OVSDB_SERVER_PRIORITY=-10
     OVS_VSWITCHD_PRIORITY=-10
-    OVS_BRCOMPATD_PRIORITY=-10
     OVSDB_SERVER_WRAPPER=
     OVS_VSWITCHD_WRAPPER=
-    OVS_BRCOMPATD_WRAPPER=
 
     DB_FILE=$dbdir/conf.db
     DB_SOCK=$rundir/db.sock
@@ -529,7 +495,6 @@ Less important options for "start", "restart" and "force-reload-kmod":
   --no-mlockall                  do not lock all of ovs-vswitchd into memory
   --ovsdb-server-priority=NICE   set ovsdb-server's niceness (default: $OVSDB_SERVER_PRIORITY)
   --ovs-vswitchd-priority=NICE   set ovs-vswitchd's niceness (default: $OVS_VSWITCHD_PRIORITY)
-  --ovs-brcompatd-priority=NICE  set ovs-brcompatd's niceness (default: $OVS_BRCOMPATD_PRIORITY)
 
 Debugging options for "start", "restart" and "force-reload-kmod":
   --ovsdb-server-wrapper=WRAPPER
@@ -537,9 +502,6 @@ Debugging options for "start", "restart" and "force-reload-kmod":
   --ovs-vswitchd-wrapper=WRAPPER
      run specified daemon under WRAPPER (either 'valgrind' or 'strace')
 
-Options for "start", "restart", "force-reload-kmod", "load-kmod", "status", and "version":
-  --brcompat         enable Linux bridge compatibility module and daemon
-
 File location options:
   --db-file=FILE     database file name (default: $DB_FILE)
   --db-sock=SOCKET   JSON-RPC socket name (default: $DB_SOCK)
@@ -584,9 +546,6 @@ set_option () {
 
 daemons () {
     echo ovsdb-server ovs-vswitchd
-    if test X"$BRCOMPAT" = Xyes; then
-        echo ovs-brcompatd
-    fi
 }
 
 set_defaults
diff --git a/vswitchd/.gitignore b/vswitchd/.gitignore
index d5c239b..afdff20 100644
--- a/vswitchd/.gitignore
+++ b/vswitchd/.gitignore
@@ -1,7 +1,5 @@
 /Makefile
 /Makefile.in
-/ovs-brcompatd
-/ovs-brcompatd.8
 /ovs-vswitchd
 /ovs-vswitchd.8
 /ovs-vswitchd.conf.db.5
diff --git a/vswitchd/automake.mk b/vswitchd/automake.mk
index fe513ac..62ace69 100644
--- a/vswitchd/automake.mk
+++ b/vswitchd/automake.mk
@@ -1,11 +1,7 @@
 sbin_PROGRAMS += vswitchd/ovs-vswitchd
 man_MANS += vswitchd/ovs-vswitchd.8
-if BUILD_BRCOMPAT
-  man_MANS += vswitchd/ovs-brcompatd.8
-endif
 DISTCLEANFILES += \
-	vswitchd/ovs-vswitchd.8 \
-	vswitchd/ovs-brcompatd.8
+	vswitchd/ovs-vswitchd.8
 
 vswitchd_ovs_vswitchd_SOURCES = \
 	vswitchd/bridge.c \
@@ -23,16 +19,6 @@ vswitchd_ovs_vswitchd_LDADD = \
 EXTRA_DIST += vswitchd/INTERNALS
 MAN_ROOTS += vswitchd/ovs-vswitchd.8.in
 
-if BUILD_BRCOMPAT
-if LINUX_DATAPATH
-sbin_PROGRAMS += vswitchd/ovs-brcompatd
-vswitchd_ovs_brcompatd_SOURCES = \
-	vswitchd/ovs-brcompatd.c
-vswitchd_ovs_brcompatd_LDADD = lib/libopenvswitch.a $(SSL_LIBS)
-endif
-MAN_ROOTS += vswitchd/ovs-brcompatd.8.in
-endif
-
 # vswitch schema and IDL
 EXTRA_DIST += vswitchd/vswitch.ovsschema
 pkgdata_DATA += vswitchd/vswitch.ovsschema
diff --git a/vswitchd/ovs-brcompatd.8.in b/vswitchd/ovs-brcompatd.8.in
deleted file mode 100644
index fdce042..0000000
--- a/vswitchd/ovs-brcompatd.8.in
+++ /dev/null
@@ -1,46 +0,0 @@
-.TH ovs\-brcompatd 8 "March 2009" "Open vSwitch" "Open vSwitch Manual"
-.ds PN ovs\-brcompatd
-.
-.SH NAME
-ovs\-brcompatd \- Bridge compatibility front-end for ovs\-vswitchd
-.
-.SH SYNOPSIS
-.B ovs\-brcompatd
-[\fIoptions\fR]
-.
-.SH DESCRIPTION
-A daemon that provides a legacy bridge front-end for \fBovs\-vswitchd\fR.  It
-does this by listening for bridge ioctl commands (e.g., those generated by
-the \fBbrctl\fR program) to add or remove datapaths and the interfaces
-that attach to them.
-.PP
-.SH OPTIONS
-.IP "\fB\-\-appctl=\fIprogram\fR"
-Sets the name to the program that \fBovs\-brcompatd\fR runs to
-communicate with \fBovs\-vswitchd\fR.  The default is
-\fBovs\-appctl\fR.  Unless \fIprogram\fR contains \fB/\fR,
-\fBovs\-brcompatd\fR will search the \fBPATH\fR environment variable
-to find it.
-.
-.IP "\fB\-\-vsctl=\fIprogram\fR"
-Sets the name to the program that \fBovs\-brcompatd\fR runs to
-communicate with \fBovsdb\-server\fR.  The default is
-\fBovs\-vsctl\fR.  Unless \fIprogram\fR contains \fB/\fR,
-\fBovs\-brcompatd\fR will search the \fBPATH\fR environment variable
-to find it.
-.
-.ds DD
-.so lib/daemon.man
-.so lib/vlog.man
-.so lib/common.man
-.so lib/leak-checker.man
-.
-.SH NOTES
-\fBovs\-brcompatd\fR requires the \fBbrcompat.ko\fR kernel module to be
-loaded.
-.SH "SEE ALSO"
-.BR ovs\-appctl (8),
-.BR ovs\-vsctl (8),
-.BR ovs\-vswitchd (8),
-.BR ovsdb\-server (1),
-\fBINSTALL.bridge\fR in the Open vSwitch distribution.
diff --git a/vswitchd/ovs-brcompatd.c b/vswitchd/ovs-brcompatd.c
deleted file mode 100644
index df9332f..0000000
--- a/vswitchd/ovs-brcompatd.c
+++ /dev/null
@@ -1,943 +0,0 @@
-/* Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <config.h>
-
-#include <asm/param.h>
-#include <assert.h>
-#include <errno.h>
-#include <getopt.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <net/if.h>
-#include <linux/genetlink.h>
-#include <linux/rtnetlink.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <time.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "command-line.h"
-#include "coverage.h"
-#include "daemon.h"
-#include "dirs.h"
-#include "dynamic-string.h"
-#include "fatal-signal.h"
-#include "json.h"
-#include "leak-checker.h"
-#include "netdev.h"
-#include "netlink.h"
-#include "netlink-notifier.h"
-#include "netlink-socket.h"
-#include "ofpbuf.h"
-#include "openvswitch/brcompat-netlink.h"
-#include "packets.h"
-#include "poll-loop.h"
-#include "process.h"
-#include "rtnetlink-link.h"
-#include "signals.h"
-#include "sset.h"
-#include "svec.h"
-#include "timeval.h"
-#include "unixctl.h"
-#include "util.h"
-#include "vlog.h"
-
-VLOG_DEFINE_THIS_MODULE(brcompatd);
-
-/* xxx Just hangs if datapath is rmmod/insmod.  Learn to reconnect? */
-
-static void parse_options(int argc, char *argv[]);
-static void usage(void) NO_RETURN;
-
-static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 60);
-
-/* --appctl: Absolute path to ovs-appctl. */
-static char *appctl_program;
-
-/* --vsctl: Absolute path to ovs-vsctl. */
-static char *vsctl_program;
-
-/* Options that we should generally pass to ovs-vsctl. */
-#define VSCTL_OPTIONS "--timeout=5", "-vconsole:warn"
-
-/* Netlink socket to bridge compatibility kernel module. */
-static struct nl_sock *brc_sock;
-
-/* The Generic Netlink family number used for bridge compatibility. */
-static int brc_family;
-
-static const struct nl_policy brc_multicast_policy[] = {
-    [BRC_GENL_A_MC_GROUP] = {.type = NL_A_U32 }
-};
-
-static char *
-capture_vsctl_valist(const char *arg0, va_list args)
-{
-    char *stdout_log, *stderr_log;
-    enum vlog_level log_level;
-    struct svec argv;
-    int status;
-    char *msg;
-
-    /* Compose arguments. */
-    svec_init(&argv);
-    svec_add(&argv, arg0);
-    for (;;) {
-        const char *arg = va_arg(args, const char *);
-        if (!arg) {
-            break;
-        }
-        svec_add(&argv, arg);
-    }
-    svec_terminate(&argv);
-
-    /* Run process. */
-    if (process_run_capture(argv.names, &stdout_log, &stderr_log, SIZE_MAX,
-                            &status)) {
-        svec_destroy(&argv);
-        return NULL;
-    }
-
-    /* Log results. */
-    if (WIFEXITED(status)) {
-        int code = WEXITSTATUS(status);
-        log_level = code == 0 ? VLL_DBG : code == 1 ? VLL_WARN : VLL_ERR;
-    } else {
-        log_level = VLL_ERR;
-    }
-    msg = process_status_msg(status);
-    VLOG(log_level, "ovs-vsctl exited (%s)", msg);
-    if (stdout_log && *stdout_log) {
-        VLOG(log_level, "ovs-vsctl wrote to stdout:\n%s\n", stdout_log);
-    }
-    if (stderr_log && *stderr_log) {
-        VLOG(log_level, "ovs-vsctl wrote to stderr:\n%s\n", stderr_log);
-    }
-    free(msg);
-
-    svec_destroy(&argv);
-
-    free(stderr_log);
-    if (WIFEXITED(status) && !WEXITSTATUS(status)) {
-        return stdout_log;
-    } else {
-        free(stdout_log);
-        return NULL;
-    }
-}
-
-static char * SENTINEL(0)
-capture_vsctl(const char *arg0, ...)
-{
-    char *stdout_log;
-    va_list args;
-
-    va_start(args, arg0);
-    stdout_log = capture_vsctl_valist(arg0, args);
-    va_end(args);
-
-    return stdout_log;
-}
-
-static bool SENTINEL(0)
-run_vsctl(const char *arg0, ...)
-{
-    char *stdout_log;
-    va_list args;
-    bool ok;
-
-    va_start(args, arg0);
-    stdout_log = capture_vsctl_valist(arg0, args);
-    va_end(args);
-
-    ok = stdout_log != NULL;
-    free(stdout_log);
-    return ok;
-}
-
-static int
-lookup_brc_multicast_group(int *multicast_group)
-{
-    struct nl_sock *sock;
-    struct ofpbuf request, *reply;
-    struct nlattr *attrs[ARRAY_SIZE(brc_multicast_policy)];
-    int retval;
-
-    retval = nl_sock_create(NETLINK_GENERIC, &sock);
-    if (retval) {
-        return retval;
-    }
-    ofpbuf_init(&request, 0);
-    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);
-    if (retval) {
-        nl_sock_destroy(sock);
-        return retval;
-    }
-    if (!nl_policy_parse(reply, NLMSG_HDRLEN + GENL_HDRLEN,
-                         brc_multicast_policy, attrs,
-                         ARRAY_SIZE(brc_multicast_policy))) {
-        nl_sock_destroy(sock);
-        ofpbuf_delete(reply);
-        return EPROTO;
-    }
-    *multicast_group = nl_attr_get_u32(attrs[BRC_GENL_A_MC_GROUP]);
-    nl_sock_destroy(sock);
-    ofpbuf_delete(reply);
-
-    return 0;
-}
-
-/* Opens a socket for brcompat notifications.  Returns 0 if successful,
- * otherwise a positive errno value. */
-static int
-brc_open(struct nl_sock **sock)
-{
-    int multicast_group = 0;
-    int retval;
-
-    retval = nl_lookup_genl_family(BRC_GENL_FAMILY_NAME, &brc_family);
-    if (retval) {
-        return retval;
-    }
-
-    retval = lookup_brc_multicast_group(&multicast_group);
-    if (retval) {
-        return retval;
-    }
-
-    retval = nl_sock_create(NETLINK_GENERIC, sock);
-    if (retval) {
-        return retval;
-    }
-
-    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[] = {
-    [BRC_GENL_A_DP_NAME] = { .type = NL_A_STRING },
-};
-
-static int
-parse_command(struct ofpbuf *buffer, uint32_t *seq, const char **br_name,
-              const char **port_name, uint64_t *count, uint64_t *skip)
-{
-    static const struct nl_policy policy[] = {
-        [BRC_GENL_A_DP_NAME] = { .type = NL_A_STRING, .optional = true },
-        [BRC_GENL_A_PORT_NAME] = { .type = NL_A_STRING, .optional = true },
-        [BRC_GENL_A_FDB_COUNT] = { .type = NL_A_U64, .optional = true },
-        [BRC_GENL_A_FDB_SKIP] = { .type = NL_A_U64, .optional = true },
-    };
-    struct nlattr *attrs[ARRAY_SIZE(policy)];
-
-    if (!nl_policy_parse(buffer, NLMSG_HDRLEN + GENL_HDRLEN, policy,
-                         attrs, ARRAY_SIZE(policy))
-        || (br_name && !attrs[BRC_GENL_A_DP_NAME])
-        || (port_name && !attrs[BRC_GENL_A_PORT_NAME])
-        || (count && !attrs[BRC_GENL_A_FDB_COUNT])
-        || (skip && !attrs[BRC_GENL_A_FDB_SKIP])) {
-        return EINVAL;
-    }
-
-    *seq = ((struct nlmsghdr *) buffer->data)->nlmsg_seq;
-    if (br_name) {
-        *br_name = nl_attr_get_string(attrs[BRC_GENL_A_DP_NAME]);
-    }
-    if (port_name) {
-        *port_name = nl_attr_get_string(attrs[BRC_GENL_A_PORT_NAME]);
-    }
-    if (count) {
-        *count = nl_attr_get_u64(attrs[BRC_GENL_A_FDB_COUNT]);
-    }
-    if (skip) {
-        *skip = nl_attr_get_u64(attrs[BRC_GENL_A_FDB_SKIP]);
-    }
-    return 0;
-}
-
-/* Composes and returns a reply to a request made by the datapath with error
- * code 'error'.  The caller may add additional attributes to the message, then
- * it may send it with send_reply(). */
-static struct ofpbuf *
-compose_reply(int error)
-{
-    struct ofpbuf *reply = ofpbuf_new(4096);
-    nl_msg_put_genlmsghdr(reply, 32, brc_family, NLM_F_REQUEST,
-                          BRC_GENL_C_DP_RESULT, 1);
-    nl_msg_put_u32(reply, BRC_GENL_A_ERR_CODE, error);
-    return reply;
-}
-
-/* Sends 'reply' to the datapath, using sequence number 'nlmsg_seq', and frees
- * it. */
-static void
-send_reply(struct ofpbuf *reply, uint32_t nlmsg_seq)
-{
-    int retval = nl_sock_send_seq(brc_sock, reply, nlmsg_seq, false);
-    if (retval) {
-        VLOG_WARN_RL(&rl, "replying to brcompat request: %s",
-                     strerror(retval));
-    }
-    ofpbuf_delete(reply);
-}
-
-/* Composes and sends a reply to a request made by the datapath with Netlink
- * sequence number 'seq' and error code 'error'. */
-static void
-send_simple_reply(uint32_t seq, int error)
-{
-    send_reply(compose_reply(error), seq);
-}
-
-static int
-handle_bridge_cmd(struct ofpbuf *buffer, bool add)
-{
-    const char *br_name;
-    uint32_t seq;
-    int error;
-
-    error = parse_command(buffer, &seq, &br_name, NULL, NULL, NULL);
-    if (!error) {
-        const char *vsctl_cmd = add ? "add-br" : "del-br";
-        const char *brctl_cmd = add ? "addbr" : "delbr";
-        if (!run_vsctl(vsctl_program, VSCTL_OPTIONS,
-                       "--", vsctl_cmd, br_name,
-                       "--", "comment", "ovs-brcompatd:", brctl_cmd, br_name,
-                       (char *) NULL)) {
-            error = add ? EEXIST : ENXIO;
-        }
-        send_simple_reply(seq, error);
-    }
-    return error;
-}
-
-static const struct nl_policy brc_port_policy[] = {
-    [BRC_GENL_A_DP_NAME] = { .type = NL_A_STRING },
-    [BRC_GENL_A_PORT_NAME] = { .type = NL_A_STRING },
-};
-
-static int
-handle_port_cmd(struct ofpbuf *buffer, bool add)
-{
-    const char *br_name, *port_name;
-    uint32_t seq;
-    int error;
-
-    error = parse_command(buffer, &seq, &br_name, &port_name, NULL, NULL);
-    if (!error) {
-        const char *vsctl_cmd = add ? "add-port" : "del-port";
-        const char *brctl_cmd = add ? "addif" : "delif";
-        if (!run_vsctl(vsctl_program, VSCTL_OPTIONS,
-                       "--", vsctl_cmd, br_name, port_name,
-                       "--", "comment", "ovs-brcompatd:", brctl_cmd,
-                       br_name, port_name, (char *) NULL)) {
-            error = EINVAL;
-        }
-        send_simple_reply(seq, error);
-    }
-    return error;
-}
-
-static char *
-linux_bridge_to_ovs_bridge(const char *linux_name, int *br_vlanp)
-{
-    char *save_ptr = NULL;
-    const char *br_name, *br_vlan;
-    char *br_name_copy;
-    char *output;
-
-    output = capture_vsctl(vsctl_program, VSCTL_OPTIONS,
-                           "--", "br-to-parent", linux_name,
-                           "--", "br-to-vlan", linux_name,
-                           (char *) NULL);
-    if (!output) {
-        return NULL;
-    }
-
-    br_name = strtok_r(output, " \t\r\n", &save_ptr);
-    br_vlan = strtok_r(NULL, " \t\r\n", &save_ptr);
-    if (!br_name || !br_vlan) {
-        free(output);
-        return NULL;
-    }
-    br_name_copy = xstrdup(br_name);
-    *br_vlanp = atoi(br_vlan);
-
-    free(output);
-
-    return br_name_copy;
-}
-
-static void
-get_bridge_ifaces(const char *br_name, struct sset *ifaces)
-{
-    char *save_ptr = NULL;
-    char *output;
-    char *iface;
-
-    output = capture_vsctl(vsctl_program, VSCTL_OPTIONS, "list-ifaces",
-                           br_name, (char *) NULL);
-    if (!output) {
-        return;
-    }
-
-    for (iface = strtok_r(output, " \t\r\n", &save_ptr); iface;
-         iface = strtok_r(NULL, " \t\r\n", &save_ptr)) {
-        sset_add(ifaces, iface);
-    }
-    free(output);
-}
-
-static int
-handle_fdb_query_cmd(struct ofpbuf *buffer)
-{
-    /* This structure is copied directly from the Linux 2.6.30 header files.
-     * It would be more straightforward to #include <linux/if_bridge.h>, but
-     * the 'port_hi' member was only introduced in Linux 2.6.26 and so systems
-     * with old header files won't have it. */
-    struct __fdb_entry {
-        __u8 mac_addr[6];
-        __u8 port_no;
-        __u8 is_local;
-        __u32 ageing_timer_value;
-        __u8 port_hi;
-        __u8 pad0;
-        __u16 unused;
-    };
-
-    struct mac {
-        uint8_t addr[6];
-    };
-    struct mac *local_macs;
-    int n_local_macs;
-    int i;
-
-    /* Impedance matching between the vswitchd and Linux kernel notions of what
-     * a bridge is.  The kernel only handles a single VLAN per bridge, but
-     * vswitchd can deal with all the VLANs on a single bridge.  We have to
-     * pretend that the former is the case even though the latter is the
-     * implementation. */
-    const char *linux_name;   /* Name used by brctl. */
-    int br_vlan;                /* VLAN tag. */
-    struct sset ifaces;
-
-    struct ofpbuf query_data;
-    const char *iface_name;
-    struct ofpbuf *reply;
-    uint64_t count, skip;
-    char *br_name;
-    char *output;
-    char *save_ptr;
-    uint32_t seq;
-    int error;
-
-    /* Parse the command received from brcompat. */
-    error = parse_command(buffer, &seq, &linux_name, NULL, &count, &skip);
-    if (error) {
-        return error;
-    }
-
-    /* Figure out vswitchd bridge and VLAN. */
-    br_name = linux_bridge_to_ovs_bridge(linux_name, &br_vlan);
-    if (!br_name) {
-        error = EINVAL;
-        send_simple_reply(seq, error);
-        return error;
-    }
-
-    /* Fetch the forwarding database using ovs-appctl. */
-    output = capture_vsctl(appctl_program, "fdb/show", br_name,
-                           (char *) NULL);
-    if (!output) {
-        error = ECHILD;
-        send_simple_reply(seq, error);
-        return error;
-    }
-
-    /* Fetch the MAC address for each interface on the bridge, so that we can
-     * fill in the is_local field in the response. */
-    sset_init(&ifaces);
-    get_bridge_ifaces(linux_name, &ifaces);
-    local_macs = xmalloc(sset_count(&ifaces) * sizeof *local_macs);
-    n_local_macs = 0;
-    SSET_FOR_EACH (iface_name, &ifaces) {
-        struct mac *mac = &local_macs[n_local_macs];
-        struct netdev *netdev;
-
-        error = netdev_open(iface_name, "system", &netdev);
-        if (!error) {
-            if (!netdev_get_etheraddr(netdev, mac->addr)) {
-                n_local_macs++;
-            }
-            netdev_close(netdev);
-        }
-    }
-    sset_destroy(&ifaces);
-
-    /* Parse the response from ovs-appctl and convert it to binary format to
-     * pass back to the kernel. */
-    ofpbuf_init(&query_data, sizeof(struct __fdb_entry) * 8);
-    save_ptr = NULL;
-    strtok_r(output, "\n", &save_ptr); /* Skip header line. */
-    while (count > 0) {
-        struct __fdb_entry *entry;
-        int port, vlan, age;
-        uint8_t mac[ETH_ADDR_LEN];
-        char *line;
-        bool is_local;
-
-        line = strtok_r(NULL, "\n", &save_ptr);
-        if (!line) {
-            break;
-        }
-
-        if (sscanf(line, "%d %d "ETH_ADDR_SCAN_FMT" %d",
-                   &port, &vlan, ETH_ADDR_SCAN_ARGS(mac), &age)
-            != 2 + ETH_ADDR_SCAN_COUNT + 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;
-        }
-
-        if (vlan != br_vlan) {
-            continue;
-        }
-
-        if (skip > 0) {
-            skip--;
-            continue;
-        }
-
-        /* Is this the MAC address of an interface on the bridge? */
-        is_local = false;
-        for (i = 0; i < n_local_macs; i++) {
-            if (eth_addr_equals(local_macs[i].addr, mac)) {
-                is_local = true;
-                break;
-            }
-        }
-
-        entry = ofpbuf_put_uninit(&query_data, sizeof *entry);
-        memcpy(entry->mac_addr, mac, ETH_ADDR_LEN);
-        entry->port_no = port & 0xff;
-        entry->is_local = is_local;
-        entry->ageing_timer_value = age * HZ;
-        entry->port_hi = (port & 0xff00) >> 8;
-        entry->pad0 = 0;
-        entry->unused = 0;
-        count--;
-    }
-    free(output);
-
-    /* Compose and send reply to datapath. */
-    reply = compose_reply(0);
-    nl_msg_put_unspec(reply, BRC_GENL_A_FDB_DATA,
-                      query_data.data, query_data.size);
-    send_reply(reply, seq);
-
-    /* Free memory. */
-    ofpbuf_uninit(&query_data);
-    free(local_macs);
-
-    return 0;
-}
-
-static void
-send_ifindex_reply(uint32_t seq, char *output)
-{
-    size_t allocated_indices;
-    char *save_ptr = NULL;
-    struct ofpbuf *reply;
-    const char *iface;
-    size_t n_indices;
-    int *indices;
-
-    indices = NULL;
-    n_indices = allocated_indices = 0;
-    for (iface = strtok_r(output, " \t\r\n", &save_ptr); iface;
-         iface = strtok_r(NULL, " \t\r\n", &save_ptr)) {
-        int ifindex;
-
-        if (n_indices >= allocated_indices) {
-            indices = x2nrealloc(indices, &allocated_indices, sizeof *indices);
-        }
-
-        ifindex = if_nametoindex(iface);
-        if (ifindex) {
-            indices[n_indices++] = ifindex;
-        }
-    }
-
-    /* Compose and send reply. */
-    reply = compose_reply(0);
-    nl_msg_put_unspec(reply, BRC_GENL_A_IFINDEXES,
-                      indices, n_indices * sizeof *indices);
-    send_reply(reply, seq);
-
-    /* Free memory. */
-    free(indices);
-}
-
-static int
-handle_get_bridges_cmd(struct ofpbuf *buffer)
-{
-    char *output;
-    uint32_t seq;
-    int error;
-
-    /* Parse Netlink command.
-     *
-     * The command doesn't actually have any arguments, but we need the
-     * sequence number to send the reply. */
-    error = parse_command(buffer, &seq, NULL, NULL, NULL, NULL);
-    if (error) {
-        return error;
-    }
-
-    output = capture_vsctl(vsctl_program, VSCTL_OPTIONS, "list-br", (char *) NULL);
-    if (!output) {
-        return ENODEV;
-    }
-
-    send_ifindex_reply(seq, output);
-    free(output);
-    return 0;
-}
-
-static int
-handle_get_ports_cmd(struct ofpbuf *buffer)
-{
-    const char *linux_name;
-    uint32_t seq;
-    char *output;
-    int error;
-
-    /* Parse Netlink command. */
-    error = parse_command(buffer, &seq, &linux_name, NULL, NULL, NULL);
-    if (error) {
-        return error;
-    }
-
-    output = capture_vsctl(vsctl_program, VSCTL_OPTIONS, "list-ports", linux_name,
-                           (char *) NULL);
-    if (!output) {
-        return ENODEV;
-    }
-
-    send_ifindex_reply(seq, output);
-    free(output);
-    return 0;
-}
-
-static bool
-brc_recv_update__(struct ofpbuf *buffer)
-{
-    for (;;) {
-        int 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 true;
-
-        case ENOBUFS:
-            break;
-
-        case EAGAIN:
-            return false;
-
-        default:
-            VLOG_WARN_RL(&rl, "brc_recv_update: %s", strerror(retval));
-            return false;
-        }
-    }
-}
-
-static void
-brc_recv_update(void)
-{
-    struct genlmsghdr *genlmsghdr;
-    uint64_t buffer_stub[1024 / 8];
-    struct ofpbuf buffer;
-
-    ofpbuf_use_stub(&buffer, buffer_stub, sizeof buffer_stub);
-    if (!brc_recv_update__(&buffer)) {
-        goto error;
-    }
-
-    genlmsghdr = nl_msg_genlmsghdr(&buffer);
-    if (!genlmsghdr) {
-        VLOG_WARN_RL(&rl, "received packet too short for generic NetLink");
-        goto error;
-    }
-
-    if (nl_msg_nlmsghdr(&buffer)->nlmsg_type != brc_family) {
-        VLOG_DBG_RL(&rl, "received type (%"PRIu16") != brcompat family (%d)",
-                nl_msg_nlmsghdr(&buffer)->nlmsg_type, brc_family);
-        goto error;
-    }
-
-    /* Service all pending network device notifications before executing the
-     * command.  This is very important to avoid a race in a scenario like the
-     * following, which is what happens with XenServer Tools version 5.0.0
-     * during boot of a Windows VM:
-     *
-     *      1. Create tap1.0 and vif1.0.
-     *      2. Delete tap1.0.
-     *      3. Delete vif1.0.
-     *      4. Re-create vif1.0.
-     *
-     * We must process the network device notification from step 3 before we
-     * process the brctl command from step 4.  If we process them in the
-     * reverse order, then step 4 completes as a no-op but step 3 then deletes
-     * the port that was just added.
-     *
-     * (XenServer Tools 5.5.0 does not exhibit this behavior, and neither does
-     * a VM without Tools installed at all.)
-     */
-    rtnetlink_link_run();
-
-    switch (genlmsghdr->cmd) {
-    case BRC_GENL_C_DP_ADD:
-        handle_bridge_cmd(&buffer, true);
-        break;
-
-    case BRC_GENL_C_DP_DEL:
-        handle_bridge_cmd(&buffer, false);
-        break;
-
-    case BRC_GENL_C_PORT_ADD:
-        handle_port_cmd(&buffer, true);
-        break;
-
-    case BRC_GENL_C_PORT_DEL:
-        handle_port_cmd(&buffer, false);
-        break;
-
-    case BRC_GENL_C_FDB_QUERY:
-        handle_fdb_query_cmd(&buffer);
-        break;
-
-    case BRC_GENL_C_GET_BRIDGES:
-        handle_get_bridges_cmd(&buffer);
-        break;
-
-    case BRC_GENL_C_GET_PORTS:
-        handle_get_ports_cmd(&buffer);
-        break;
-
-    default:
-        VLOG_WARN_RL(&rl, "received unknown brc netlink command: %d\n",
-                     genlmsghdr->cmd);
-        break;
-    }
-
-error:
-    ofpbuf_uninit(&buffer);
-}
-
-static void
-netdev_changed_cb(const struct rtnetlink_link_change *change,
-                  void *aux OVS_UNUSED)
-{
-    char br_name[IFNAMSIZ];
-    const char *port_name;
-
-    if (!change) {
-        VLOG_WARN_RL(&rl, "network monitor socket overflowed");
-        return;
-    }
-
-    if (change->nlmsg_type != RTM_DELLINK || !change->master_ifindex) {
-        return;
-    }
-
-    port_name = change->ifname;
-    if (!if_indextoname(change->master_ifindex, br_name)) {
-        return;
-    }
-
-    VLOG_INFO("network device %s destroyed, removing from bridge %s",
-              port_name, br_name);
-
-    run_vsctl(vsctl_program, VSCTL_OPTIONS,
-              "--", "--if-exists", "del-port", port_name,
-              "--", "comment", "ovs-brcompatd:", port_name, "disappeared",
-              (char *) NULL);
-}
-
-int
-main(int argc, char *argv[])
-{
-    extern struct vlog_module VLM_reconnect;
-    struct nln_notifier *link_notifier;
-    struct unixctl_server *unixctl;
-    int retval;
-
-    proctitle_init(argc, argv);
-    set_program_name(argv[0]);
-    vlog_set_levels(&VLM_reconnect, VLF_ANY_FACILITY, VLL_WARN);
-
-    parse_options(argc, argv);
-    signal(SIGPIPE, SIG_IGN);
-    process_init();
-
-    daemonize_start();
-
-    retval = unixctl_server_create(NULL, &unixctl);
-    if (retval) {
-        exit(EXIT_FAILURE);
-    }
-
-    if (brc_open(&brc_sock)) {
-        VLOG_FATAL("could not open brcompat socket.  Check "
-                   "\"brcompat\" kernel module.");
-    }
-
-    link_notifier = rtnetlink_link_notifier_create(netdev_changed_cb, NULL);
-
-    daemonize_complete();
-
-    for (;;) {
-        unixctl_server_run(unixctl);
-        rtnetlink_link_run();
-        brc_recv_update();
-
-        netdev_run();
-
-        nl_sock_wait(brc_sock, POLLIN);
-        unixctl_server_wait(unixctl);
-        rtnetlink_link_wait();
-        netdev_wait();
-        poll_block();
-    }
-
-    rtnetlink_link_notifier_destroy(link_notifier);
-
-    return 0;
-}
-
-static void
-parse_options(int argc, char *argv[])
-{
-    enum {
-        OPT_APPCTL,
-        OPT_VSCTL,
-        VLOG_OPTION_ENUMS,
-        LEAK_CHECKER_OPTION_ENUMS,
-        DAEMON_OPTION_ENUMS
-    };
-    static struct option long_options[] = {
-        {"help",             no_argument, NULL, 'h'},
-        {"version",          no_argument, NULL, 'V'},
-        {"appctl",           required_argument, NULL, OPT_APPCTL},
-        {"vsctl",            required_argument, NULL, OPT_VSCTL},
-        DAEMON_LONG_OPTIONS,
-        VLOG_LONG_OPTIONS,
-        LEAK_CHECKER_LONG_OPTIONS,
-        {NULL, 0, NULL, 0},
-    };
-    char *short_options = long_options_to_short_options(long_options);
-    const char *appctl = "ovs-appctl";
-    const char *vsctl = "ovs-vsctl";
-
-    for (;;) {
-        int c;
-
-        c = getopt_long(argc, argv, short_options, long_options, NULL);
-        if (c == -1) {
-            break;
-        }
-
-        switch (c) {
-        case 'h':
-            usage();
-
-        case 'V':
-            ovs_print_version(0, 0);
-            exit(EXIT_SUCCESS);
-
-        case OPT_APPCTL:
-            appctl = optarg;
-            break;
-
-        case OPT_VSCTL:
-            vsctl = optarg;
-            break;
-
-        VLOG_OPTION_HANDLERS
-        DAEMON_OPTION_HANDLERS
-        LEAK_CHECKER_OPTION_HANDLERS
-
-        case '?':
-            exit(EXIT_FAILURE);
-
-        default:
-            abort();
-        }
-    }
-    free(short_options);
-
-    appctl_program = process_search_path(appctl);
-    if (!appctl_program) {
-        VLOG_FATAL("%s: not found in $PATH (use --appctl to specify an "
-                   "alternate location)", appctl);
-    }
-
-    vsctl_program = process_search_path(vsctl);
-    if (!vsctl_program) {
-        VLOG_FATAL("%s: not found in $PATH (use --vsctl to specify an "
-                   "alternate location)", vsctl);
-    }
-
-    if (argc != optind) {
-        VLOG_FATAL("no non-option arguments are supported; "
-                   "use --help for usage");
-    }
-}
-
-static void
-usage(void)
-{
-    printf("%s: bridge compatibility front-end for ovs-vswitchd\n"
-           "usage: %s [OPTIONS]\n",
-           program_name, program_name);
-    printf("\nConfiguration options:\n"
-           "  --appctl=PROGRAM        overrides $PATH for finding ovs-appctl\n"
-           "  --vsctl=PROGRAM         overrides $PATH for finding ovs-vsctl\n"
-          );
-    daemon_usage();
-    vlog_usage();
-    printf("\nOther options:\n"
-           "  -h, --help              display this help message\n"
-           "  -V, --version           display version information\n");
-    leak_checker_usage();
-    exit(EXIT_SUCCESS);
-}
diff --git a/vswitchd/ovs-vswitchd.8.in b/vswitchd/ovs-vswitchd.8.in
index 6bb08c7..9d66a61 100644
--- a/vswitchd/ovs-vswitchd.8.in
+++ b/vswitchd/ovs-vswitchd.8.in
@@ -254,6 +254,5 @@ time linear in the number of flows.
 .
 .SH "SEE ALSO"
 .BR ovs\-appctl (8),
-.BR ovs\-brcompatd (8),
 .BR ovsdb\-server (1),
 \fBINSTALL.Linux\fR in the Open vSwitch distribution.
diff --git a/xenserver/openvswitch-xen.spec.in b/xenserver/openvswitch-xen.spec.in
index 18e421b..c41a7e5 100644
--- a/xenserver/openvswitch-xen.spec.in
+++ b/xenserver/openvswitch-xen.spec.in
@@ -285,7 +285,7 @@ done
 # provided by OVS. Any time a replacement script is removed from OVS,
 # it should be added here to ensure correct reversion from old versions of
 # OVS that don't clean up dangling symlinks during the uninstall phase.
-for orig in /usr/sbin/brctl /usr/sbin/xen-bugtool $keep_files; do
+for orig in /usr/sbin/xen-bugtool $keep_files; do
     saved=/usr/lib/openvswitch/xs-saved/$(basename "$orig")
     [ -e "$saved" ] && mv -f "$saved" "$orig"
 done
@@ -357,7 +357,6 @@ fi
 # this restore-on-upgrade logic.
 for f in \
     /etc/xensource/scripts/vif \
-    /usr/sbin/brctl \
     /usr/sbin/xen-bugtool \
     /opt/xensource/libexec/interface-reconfigure \
     /opt/xensource/libexec/InterfaceReconfigure.py \
@@ -455,8 +454,6 @@ exit 0
 /usr/share/man/man8/ovs-vswitchd.8.gz
 /var/lib/openvswitch
 %exclude /usr/lib/xsconsole/plugins-base/*.py[co]
-%exclude /usr/sbin/ovs-brcompatd
-%exclude /usr/share/man/man8/ovs-brcompatd.8.gz
 %exclude /usr/share/openvswitch/scripts/*.py[co]
 %exclude /usr/share/openvswitch/python/*.py[co]
 %exclude /usr/share/openvswitch/python/ovs/*.py[co]
@@ -464,4 +461,3 @@ exit 0
 
 %files %{module_package}
 /lib/modules/%{xen_version}/extra/openvswitch/openvswitch.ko
-%exclude /lib/modules/%{xen_version}/extra/openvswitch/brcompat.ko
-- 
1.7.10




More information about the dev mailing list