/*
- * Copyright (c) 2009 Nicira Networks.
- * Distributed under the terms of the GNU GPL version 2.
+ * Copyright (c) 2007-2012 Nicira Networks.
*
- * Significant portions of this file may be copied from parts of the Linux
- * kernel, by Linus Torvalds and others.
+ * 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 <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/completion.h>
#include <linux/etherdevice.h>
#include <linux/if_bridge.h>
#include <linux/rtnetlink.h>
#include <net/genetlink.h>
-#include "compat.h"
#include "openvswitch/brcompat-netlink.h"
-#include "brc_procfs.h"
#include "datapath.h"
static struct genl_family brc_genl_family;
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 sk_buff *, struct nlattr **attrs);
+static struct sk_buff *brc_send_command(struct sk_buff *,
+ struct nlattr **attrs);
static int brc_send_simple_command(struct sk_buff *);
static struct sk_buff *brc_make_request(int op, const char *bridge,
struct __bridge_info __user *ub)
{
struct __bridge_info b;
- u64 id = 0;
- int i;
memset(&b, 0, sizeof(struct __bridge_info));
- for (i=0; i<ETH_ALEN; i++)
- id |= (u64)dev->dev_addr[i] << (8*(ETH_ALEN-1 - i));
- b.bridge_id = cpu_to_be64(id);
+ /* 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)))
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;
+ 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;
return err;
}
-static struct genl_ops brc_genl_ops_query_dp = {
- .cmd = BRC_GENL_C_QUERY_MC,
- .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privelege. */
- .policy = NULL,
- .doit = brc_genl_query,
- .dumpit = NULL
-};
-
/* 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_PROC_DIR] = { .type = NLA_NUL_STRING },
- [BRC_GENL_A_PROC_NAME] = { .type = NLA_NUL_STRING },
- [BRC_GENL_A_PROC_DATA] = { .type = NLA_NUL_STRING },
-
[BRC_GENL_A_FDB_DATA] = { .type = NLA_UNSPEC },
};
return err;
}
-static struct genl_ops brc_genl_ops_dp_result = {
- .cmd = BRC_GENL_C_DP_RESULT,
- .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privelege. */
- .policy = brc_genl_policy,
- .doit = brc_genl_dp_result,
- .dumpit = NULL
-};
-
-static struct genl_ops brc_genl_ops_set_proc = {
- .cmd = BRC_GENL_C_SET_PROC,
- .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privelege. */
- .policy = brc_genl_policy,
- .doit = brc_genl_set_proc,
- .dumpit = NULL
+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 sk_buff *request,
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);
{
int err;
- printk("Open vSwitch Bridge Compatibility, built "__DATE__" "__TIME__"\n");
+ pr_info("Open vSwitch Bridge Compatibility, built "__DATE__" "__TIME__"\n");
/* Set the bridge ioctl handler */
brioctl_set(brc_ioctl_deviceless_stub);
/* Set the openvswitch_mod device ioctl handler */
- dp_ioctl_hook = brc_dev_ioctl;
+ 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
/* Register generic netlink family to communicate changes to
* userspace. */
- err = genl_register_family(&brc_genl_family);
+ err = genl_register_family_with_ops(&brc_genl_family,
+ brc_genl_ops, ARRAY_SIZE(brc_genl_ops));
if (err)
goto error;
- err = genl_register_ops(&brc_genl_family, &brc_genl_ops_query_dp);
- if (err != 0)
- goto err_unregister;
-
- err = genl_register_ops(&brc_genl_family, &brc_genl_ops_dp_result);
- if (err != 0)
- goto err_unregister;
-
- err = genl_register_ops(&brc_genl_family, &brc_genl_ops_set_proc);
- if (err != 0)
- goto err_unregister;
-
strcpy(brc_mc_group.name, "brcompat");
err = genl_register_mc_group(&brc_genl_family, &brc_mc_group);
if (err < 0)
static void brc_cleanup(void)
{
/* Unregister ioctl hooks */
- dp_ioctl_hook = NULL;
+ ovs_dp_ioctl_hook = NULL;
brioctl_set(NULL);
genl_unregister_family(&brc_genl_family);
- brc_procfs_exit();
}
module_init(brc_init);
MODULE_DESCRIPTION("Open vSwitch bridge compatibility");
MODULE_AUTHOR("Nicira Networks");
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_mod, so this prevents it.
+ */
+BRIDGE_MUTUAL_EXCLUSION;
+#endif