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:
parent
a8643e4476
commit
5ca1ba484b
9
FAQ
9
FAQ
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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.
|
@ -50,7 +50,6 @@ EXTRA_DIST = \
|
||||
INSTALL.RHEL \
|
||||
INSTALL.SSL \
|
||||
INSTALL.XenServer \
|
||||
INSTALL.bridge \
|
||||
INSTALL.userspace \
|
||||
IntegrationGuide \
|
||||
NOTICE \
|
||||
|
9
README
9
README
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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 *);
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
@ -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 */
|
2
datapath/linux/.gitignore
vendored
2
datapath/linux/.gitignore
vendored
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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 */
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
1
debian/.gitignore
vendored
@ -6,7 +6,6 @@
|
||||
/files
|
||||
/nicira-switch
|
||||
/openvswitch
|
||||
/openvswitch-brcompat
|
||||
/openvswitch-common
|
||||
/openvswitch-common.copyright
|
||||
/openvswitch-controller
|
||||
|
4
debian/automake.mk
vendored
4
debian/automake.mk
vendored
@ -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
22
debian/control
vendored
@ -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
1
debian/copyright.in
vendored
@ -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
3
debian/dkms.conf.in
vendored
@ -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
|
||||
|
1
debian/openvswitch-brcompat.install
vendored
1
debian/openvswitch-brcompat.install
vendored
@ -1 +0,0 @@
|
||||
_debian/vswitchd/ovs-brcompatd usr/sbin
|
1
debian/openvswitch-brcompat.manpages
vendored
1
debian/openvswitch-brcompat.manpages
vendored
@ -1 +0,0 @@
|
||||
_debian/vswitchd/ovs-brcompatd.8
|
17
debian/openvswitch-brcompat.postinst
vendored
17
debian/openvswitch-brcompat.postinst
vendored
@ -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
|
||||
|
||||
|
43
debian/openvswitch-brcompat.postrm
vendored
43
debian/openvswitch-brcompat.postrm
vendored
@ -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
|
||||
|
||||
|
8
debian/openvswitch-switch.init
vendored
8
debian/openvswitch-switch.init
vendored
@ -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
|
||||
"$@"
|
||||
}
|
||||
|
||||
|
4
debian/openvswitch-switch.template
vendored
4
debian/openvswitch-switch.template
vendored
@ -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=
|
||||
|
@ -1,5 +1,4 @@
|
||||
noinst_HEADERS += \
|
||||
include/openvswitch/brcompat-netlink.h \
|
||||
include/openvswitch/datapath-compat.h \
|
||||
include/openvswitch/tunnel.h \
|
||||
include/openvswitch/types.h
|
||||
|
@ -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 */
|
@ -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])])
|
||||
|
12
manpages.mk
12
manpages.mk
@ -220,18 +220,6 @@ ovsdb/remote-active.man:
|
||||
ovsdb/remote-passive.man:
|
||||
ovsdb/remote-passive.man:
|
||||
|
||||
vswitchd/ovs-brcompatd.8: \
|
||||
vswitchd/ovs-brcompatd.8.in \
|
||||
lib/common.man \
|
||||
lib/daemon.man \
|
||||
lib/leak-checker.man \
|
||||
lib/vlog.man
|
||||
vswitchd/ovs-brcompatd.8.in:
|
||||
lib/common.man:
|
||||
lib/daemon.man:
|
||||
lib/leak-checker.man:
|
||||
lib/vlog.man:
|
||||
|
||||
vswitchd/ovs-vswitchd.8: \
|
||||
vswitchd/ovs-vswitchd.8.in \
|
||||
lib/common.man \
|
||||
|
@ -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
|
||||
"$@"
|
||||
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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=
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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
2
vswitchd/.gitignore
vendored
@ -1,7 +1,5 @@
|
||||
/Makefile
|
||||
/Makefile.in
|
||||
/ovs-brcompatd
|
||||
/ovs-brcompatd.8
|
||||
/ovs-vswitchd
|
||||
/ovs-vswitchd.8
|
||||
/ovs-vswitchd.conf.db.5
|
||||
|
@ -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
|
||||
|
@ -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.
|
@ -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);
|
||||
}
|
@ -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.
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user