2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-22 01:51:26 +00:00

openvswitch: Remove Linux bridge compatibility.

Currently brcompat does not work 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@nicira.com>
Acked-by: Jesse Gross <jesse@nicira.com>
This commit is contained in:
Pravin B Shelar 2012-12-27 13:48:51 -08:00
parent a8643e4476
commit 5ca1ba484b
62 changed files with 176 additions and 3256 deletions

9
FAQ
View File

@ -160,15 +160,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.

View File

@ -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

View File

@ -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.

View File

@ -50,7 +50,6 @@ EXTRA_DIST = \
INSTALL.RHEL \
INSTALL.SSL \
INSTALL.XenServer \
INSTALL.bridge \
INSTALL.userspace \
IntegrationGuide \
NOTICE \

9
README
View File

@ -28,7 +28,6 @@ vSwitch supports the following features:
* 802.1ag connectivity fault management
* OpenFlow 1.0 plus numerous extensions
* Transactional configuration database with C and Python bindings
* Compatibility layer for Linux bridging code
* High-performance forwarding using a Linux kernel module
The included Linux kernel module supports Linux 2.6.18 and up, with
@ -52,11 +51,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
@ -103,9 +97,6 @@ To use Open vSwitch...
- ...with Libvirt, read INSTALL.Libvirt.
- ...as a drop-in replacement for the Linux bridge, read
INSTALL.bridge.
- ...without using a kernel module, read INSTALL.userspace.
For answers to common questions, read FAQ.

View File

@ -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

View File

@ -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,15 +11,12 @@ openvswitch_sources = \
checksum.c \
datapath.c \
dp_notify.c \
dp_sysfs_dp.c \
dp_sysfs_if.c \
flow.c \
genl_exec.c \
tunnel.c \
vlan.c \
vport.c \
vport-capwap.c \
vport-generic.c \
vport-gre.c \
vport-internal_dev.c \
vport-netdev.c \
@ -33,14 +27,12 @@ openvswitch_headers = \
checksum.h \
compat.h \
datapath.h \
dp_sysfs.h \
flow.h \
genl_exec.h \
tunnel.h \
vlan.h \
vport.h \
vport-capwap.h \
vport-generic.h \
vport-internal_dev.h \
vport-netdev.h

View File

@ -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

View File

@ -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

View File

@ -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_portid,

View File

@ -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 *);

View File

@ -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;

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -69,11 +69,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

View File

@ -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"

View File

@ -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
* @portid: destination netlink portid 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 portid,
unsigned int group, int report, gfp_t flags)
{
int err = 0;
if (group) {
int exclude_portid = 0;
if (report) {
atomic_inc(&skb->users);
exclude_portid = portid;
}
/* errors reported via destination sk->sk_err, but propagate
* delivery errors if NETLINK_BROADCAST_ERROR flag is set */
err = nlmsg_multicast(sk, skb, exclude_portid, group, flags);
}
if (report) {
int err2;
err2 = nlmsg_unicast(sk, skb, portid);
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 portid, 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, portid, 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 portid, u32 group, int code)
{
}
#endif

View File

@ -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
* @portid: destination netlink portid 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 portid,
unsigned int group, int report, gfp_t flags)
{
int err = 0;
if (group) {
int exclude_portid = 0;
if (report) {
atomic_inc(&skb->users);
exclude_portid = portid;
}
/* errors reported via destination sk->sk_err, but propagate
* delivery errors if NETLINK_BROADCAST_ERROR flag is set */
err = nlmsg_multicast(sk, skb, exclude_portid, group, flags);
}
if (report) {
int err2;
err2 = nlmsg_unicast(sk, skb, portid);
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 portid, 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, portid, 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 portid, u32 group, int code)
{
}
#endif

View File

@ -49,7 +49,6 @@
#include "tunnel.h"
#include "vlan.h"
#include "vport.h"
#include "vport-generic.h"
#include "vport-internal_dev.h"
#define PORT_TABLE_SIZE 1024

View File

@ -27,7 +27,6 @@
#include "datapath.h"
#include "tunnel.h"
#include "vport.h"
#include "vport-generic.h"
#define CAPWAP_SRC_PORT 58881
#define CAPWAP_DST_PORT 58882
@ -847,9 +846,6 @@ const struct vport_ops ovs_capwap_vport_ops = {
.get_addr = ovs_tnl_get_addr,
.get_options = ovs_tnl_get_options,
.set_options = ovs_tnl_set_options,
.get_dev_flags = ovs_vport_gen_get_dev_flags,
.is_running = ovs_vport_gen_is_running,
.get_operstate = ovs_vport_gen_get_operstate,
.send = ovs_tnl_send,
};
#else

View File

@ -1,36 +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
*/
#include <linux/etherdevice.h>
#include "vport-generic.h"
unsigned ovs_vport_gen_get_dev_flags(const struct vport *vport)
{
return IFF_UP | IFF_RUNNING | IFF_LOWER_UP;
}
int ovs_vport_gen_is_running(const struct vport *vport)
{
return 1;
}
unsigned char ovs_vport_gen_get_operstate(const struct vport *vport)
{
return IF_OPER_UP;
}

View File

@ -1,28 +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 VPORT_GENERIC_H
#define VPORT_GENERIC_H 1
#include "vport.h"
unsigned ovs_vport_gen_get_dev_flags(const struct vport *);
int ovs_vport_gen_is_running(const struct vport *);
unsigned char ovs_vport_gen_get_operstate(const struct vport *);
#endif /* vport-generic.h */

View File

@ -32,7 +32,6 @@
#include "datapath.h"
#include "tunnel.h"
#include "vport.h"
#include "vport-generic.h"
/*
* The GRE header is composed of a series of sections: a base and then a variable
@ -495,9 +494,6 @@ const struct vport_ops ovs_gre_ft_vport_ops = {
.get_addr = ovs_tnl_get_addr,
.get_options = ovs_tnl_get_options,
.set_options = ovs_tnl_set_options,
.get_dev_flags = ovs_vport_gen_get_dev_flags,
.is_running = ovs_vport_gen_is_running,
.get_operstate = ovs_vport_gen_get_operstate,
.send = ovs_tnl_send,
};
@ -513,9 +509,6 @@ const struct vport_ops ovs_gre_vport_ops = {
.get_addr = ovs_tnl_get_addr,
.get_options = ovs_tnl_get_options,
.set_options = ovs_tnl_set_options,
.get_dev_flags = ovs_vport_gen_get_dev_flags,
.is_running = ovs_vport_gen_is_running,
.get_operstate = ovs_vport_gen_get_operstate,
.send = ovs_tnl_send,
};
@ -531,8 +524,5 @@ const struct vport_ops ovs_gre64_vport_ops = {
.get_addr = ovs_tnl_get_addr,
.get_options = ovs_tnl_get_options,
.set_options = ovs_tnl_set_options,
.get_dev_flags = ovs_vport_gen_get_dev_flags,
.is_running = ovs_vport_gen_is_running,
.get_operstate = ovs_vport_gen_get_operstate,
.send = ovs_tnl_send,
};

View File

@ -31,7 +31,6 @@
#include "checksum.h"
#include "datapath.h"
#include "vlan.h"
#include "vport-generic.h"
#include "vport-internal_dev.h"
#include "vport-netdev.h"
@ -141,15 +140,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);
@ -164,7 +154,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 = eth_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,
@ -181,7 +170,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;
@ -307,12 +295,7 @@ const struct vport_ops ovs_internal_vport_ops = {
.set_addr = ovs_netdev_set_addr,
.get_name = ovs_netdev_get_name,
.get_addr = ovs_netdev_get_addr,
.get_kobj = ovs_netdev_get_kobj,
.get_dev_flags = ovs_netdev_get_dev_flags,
.is_running = ovs_netdev_is_running,
.get_operstate = ovs_netdev_get_operstate,
.get_ifindex = ovs_netdev_get_ifindex,
.get_mtu = ovs_netdev_get_mtu,
.send = internal_dev_recv,
};

View File

@ -216,42 +216,12 @@ const unsigned char *ovs_netdev_get_addr(const struct vport *vport)
return netdev_vport->dev->dev_addr;
}
struct kobject *ovs_netdev_get_kobj(const struct vport *vport)
{
const struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
return &netdev_vport->dev->NETDEV_DEV_MEMBER.kobj;
}
unsigned ovs_netdev_get_dev_flags(const struct vport *vport)
{
const struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
return dev_get_flags(netdev_vport->dev);
}
int ovs_netdev_is_running(const struct vport *vport)
{
const struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
return netif_running(netdev_vport->dev);
}
unsigned char ovs_netdev_get_operstate(const struct vport *vport)
{
const struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
return netdev_vport->dev->operstate;
}
int ovs_netdev_get_ifindex(const struct vport *vport)
{
const struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
return netdev_vport->dev->ifindex;
}
int ovs_netdev_get_mtu(const struct vport *vport)
{
const struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
return netdev_vport->dev->mtu;
}
/* Must be called with rcu_read_lock. */
static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)
{
@ -415,21 +385,25 @@ const struct vport_ops ovs_netdev_vport_ops = {
.set_addr = ovs_netdev_set_addr,
.get_name = ovs_netdev_get_name,
.get_addr = ovs_netdev_get_addr,
.get_kobj = ovs_netdev_get_kobj,
.get_dev_flags = ovs_netdev_get_dev_flags,
.is_running = ovs_netdev_is_running,
.get_operstate = ovs_netdev_get_operstate,
.get_ifindex = ovs_netdev_get_ifindex,
.get_mtu = ovs_netdev_get_mtu,
.send = netdev_send,
};
#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.
*
* 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

View File

@ -42,11 +42,6 @@ int ovs_netdev_set_addr(struct vport *, const unsigned char *addr);
const char *ovs_netdev_get_name(const struct vport *);
const unsigned char *ovs_netdev_get_addr(const struct vport *);
const char *ovs_netdev_get_config(const struct vport *);
struct kobject *ovs_netdev_get_kobj(const struct vport *);
unsigned ovs_netdev_get_dev_flags(const struct vport *);
int ovs_netdev_is_running(const struct vport *);
unsigned char ovs_netdev_get_operstate(const struct vport *);
int ovs_netdev_get_ifindex(const struct vport *);
int ovs_netdev_get_mtu(const struct vport *);
#endif /* vport_netdev.h */

View File

@ -25,7 +25,6 @@
#include "compat.h"
#include "datapath.h"
#include "vport.h"
#include "vport-generic.h"
struct patch_config {
struct rcu_head rcu;
@ -312,8 +311,5 @@ const struct vport_ops ovs_patch_vport_ops = {
.get_addr = patch_get_addr,
.get_options = patch_get_options,
.set_options = patch_set_options,
.get_dev_flags = ovs_vport_gen_get_dev_flags,
.is_running = ovs_vport_gen_is_running,
.get_operstate = ovs_vport_gen_get_operstate,
.send = patch_send,
};

View File

@ -35,7 +35,6 @@
#include "datapath.h"
#include "tunnel.h"
#include "vport.h"
#include "vport-generic.h"
#define VXLAN_FLAGS 0x08000000 /* struct vxlanhdr.vx_flags required value. */
@ -377,9 +376,6 @@ const struct vport_ops ovs_vxlan_vport_ops = {
.get_addr = ovs_tnl_get_addr,
.get_options = ovs_tnl_get_options,
.set_options = vxlan_set_options,
.get_dev_flags = ovs_vport_gen_get_dev_flags,
.is_running = ovs_vport_gen_is_running,
.get_operstate = ovs_vport_gen_get_operstate,
.send = ovs_tnl_send,
};
#else

View File

@ -151,19 +151,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
*
@ -197,11 +184,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);
@ -226,8 +208,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);
}
/**

View File

@ -75,7 +75,6 @@ struct vport_err_stats {
* struct vport - one port within a datapath
* @rcu: RCU callback head for deferred destruction.
* @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.
@ -94,7 +93,6 @@ struct vport_err_stats {
struct vport {
struct rcu_head rcu;
struct datapath *dp;
struct kobject kobj;
char linkname[IFNAMSIZ];
u32 upcall_portid;
u16 port_no;
@ -158,15 +156,8 @@ struct vport_parms {
* @get_name: Get the device's name.
* @get_addr: Get the device's MAC address.
* @get_config: Get the device's configuration.
* @get_kobj: Get the kobj associated with the device (may return null).
* @get_dev_flags: Get the device's flags.
* @is_running: Checks whether the device is running.
* @get_operstate: Get the device's operating state.
* @get_ifindex: Get the system interface index associated with the device.
* May be null if the device does not have an ifindex.
* @get_mtu: Get the device's MTU. May be %NULL if the device does not have an
* MTU (as e.g. some tunnels do not). Must be implemented if @get_ifindex is
* implemented.
* @send: Send a packet on the device. Returns the length of the packet sent.
*/
struct vport_ops {
@ -190,16 +181,7 @@ struct vport_ops {
const char *(*get_name)(const struct vport *);
const unsigned char *(*get_addr)(const struct vport *);
void (*get_config)(const struct vport *, void *);
struct kobject *(*get_kobj)(const struct vport *);
unsigned (*get_dev_flags)(const struct vport *);
int (*is_running)(const struct vport *);
unsigned char (*get_operstate)(const struct vport *);
int (*get_ifindex)(const struct vport *);
int (*get_mtu)(const struct vport *);
int (*send)(struct vport *, struct sk_buff *);
};

1
debian/.gitignore vendored
View File

@ -6,7 +6,6 @@
/files
/nicira-switch
/openvswitch
/openvswitch-brcompat
/openvswitch-common
/openvswitch-common.copyright
/openvswitch-controller

4
debian/automake.mk vendored
View File

@ -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 \

22
debian/control vendored
View File

@ -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

1
debian/copyright.in vendored
View File

@ -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

3
debian/dkms.conf.in vendored
View File

@ -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

View File

@ -1 +0,0 @@
_debian/vswitchd/ovs-brcompatd usr/sbin

View File

@ -1 +0,0 @@
_debian/vswitchd/ovs-brcompatd.8

View File

@ -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

View File

@ -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

View File

@ -30,11 +30,6 @@
. /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
network_interfaces () {
INTERFACES="/etc/network/interfaces"
[ -e "${INTERFACES}" ] || return
@ -44,9 +39,6 @@ network_interfaces () {
ovs_ctl () {
set /usr/share/openvswitch/scripts/ovs-ctl "$@"
if test X"$BRCOMPAT" = Xyes; then
set "$@" --brcompat
fi
"$@"
}

View File

@ -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=

View File

@ -1,5 +1,4 @@
noinst_HEADERS += \
include/openvswitch/brcompat-netlink.h \
include/openvswitch/datapath-compat.h \
include/openvswitch/tunnel.h \
include/openvswitch/types.h

View File

@ -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 */

View File

@ -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])])

View File

@ -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 \

View File

@ -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
"$@"

View File

@ -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

View File

@ -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@cisco.com>

View File

@ -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

View File

@ -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=

View File

@ -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,

View File

@ -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.

View File

@ -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

2
vswitchd/.gitignore vendored
View File

@ -1,7 +1,5 @@
/Makefile
/Makefile.in
/ovs-brcompatd
/ovs-brcompatd.8
/ovs-vswitchd
/ovs-vswitchd.8
/ovs-vswitchd.conf.db.5

View File

@ -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

View File

@ -1,47 +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.
This feature is deprecated and will be removed no earlier than February 2013.
.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.

View File

@ -1,945 +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);
VLOG_WARN("Bridge compatibility is deprecated and may be removed "
"no earlier than February 2013");
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);
}

View File

@ -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.

View File

@ -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